or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

asynchronous-client.mdbot-framework.mdconnection-management.mdevent-system.mdindex.mdprotocol-extensions.mdsynchronous-client.mdutilities.md

synchronous-client.mddocs/

0

# Synchronous IRC Client

1

2

Core IRC client functionality using traditional socket connections with select-based event processing. The synchronous client provides the foundation for IRC protocol communication with blocking operations and callback-based event handling.

3

4

## Capabilities

5

6

### Reactor

7

8

Central event loop that manages IRC connections and dispatches events to handlers. Uses select() for socket monitoring and provides the main event processing infrastructure.

9

10

```python { .api }

11

class Reactor:

12

def __init__(self, on_connect=None, on_disconnect=None):

13

"""

14

Initialize IRC reactor for event processing.

15

16

Parameters:

17

- on_connect: callable, called when connection established

18

- on_disconnect: callable, called when connection lost

19

"""

20

21

def server(self) -> ServerConnection:

22

"""

23

Create a new ServerConnection for IRC server communication.

24

25

Returns:

26

ServerConnection instance

27

"""

28

29

def dcc(self, dcctype: str = "chat") -> DCCConnection:

30

"""

31

Create a DCC connection for direct client communication.

32

33

Parameters:

34

- dcctype: str, type of DCC connection ("chat" or "raw")

35

36

Returns:

37

DCCConnection instance

38

"""

39

40

def process_once(self, timeout: float = 0):

41

"""

42

Process events once with optional timeout.

43

44

Parameters:

45

- timeout: float, timeout in seconds (0 for non-blocking)

46

"""

47

48

def process_forever(self, timeout: float = 0.2):

49

"""

50

Process events indefinitely until disconnection.

51

52

Parameters:

53

- timeout: float, timeout between iterations in seconds

54

"""

55

56

def add_global_handler(self, event: str, handler, priority: int = 0):

57

"""

58

Add global event handler for all connections.

59

60

Parameters:

61

- event: str, event type to handle

62

- handler: callable, handler function (connection, event)

63

- priority: int, handler priority (lower = higher priority)

64

"""

65

66

def remove_global_handler(self, event: str, handler):

67

"""

68

Remove global event handler.

69

70

Parameters:

71

- event: str, event type

72

- handler: callable, handler function to remove

73

"""

74

75

def disconnect_all(self, message: str = ""):

76

"""

77

Disconnect all managed connections.

78

79

Parameters:

80

- message: str, quit message

81

"""

82

```

83

84

### ServerConnection

85

86

Individual IRC server connection handling protocol communication, command sending, and event processing for a single IRC server.

87

88

```python { .api }

89

class ServerConnection:

90

@property

91

def connected(self) -> bool:

92

"""Whether connection is established."""

93

94

@property

95

def features(self) -> FeatureSet:

96

"""Server-announced features and capabilities."""

97

98

def connect(self, server: str, port: int, nickname: str, password: str | None = None,

99

username: str | None = None, ircname: str | None = None,

100

connect_factory=connection.Factory(), sasl_login: str | None = None):

101

"""

102

Connect to IRC server.

103

104

Parameters:

105

- server: str, server hostname

106

- port: int, server port

107

- nickname: str, desired nickname

108

- password: str, optional server password

109

- username: str, optional username (defaults to nickname)

110

- ircname: str, optional real name (defaults to nickname)

111

- connect_factory: Factory, optional connection factory

112

- sasl_login: str | None, optional SASL username for authentication

113

"""

114

115

def reconnect(self):

116

"""Reconnect to the same server with same parameters."""

117

118

def disconnect(self, message: str = ""):

119

"""

120

Disconnect from server.

121

122

Parameters:

123

- message: str, quit message

124

"""

125

126

def close(self):

127

"""Close connection immediately without sending QUIT."""

128

129

def get_server_name(self) -> str:

130

"""Get connected server name."""

131

132

def get_nickname(self) -> str:

133

"""Get current nickname."""

134

135

def is_connected(self) -> bool:

136

"""Check if connected to server."""

137

138

def as_nick(self, name: str):

139

"""

140

Context manager for temporary nickname changes.

141

142

Parameters:

143

- name: str, temporary nickname

144

145

Usage:

146

with connection.as_nick("tempnick"):

147

# nickname is temporarily changed

148

pass

149

# nickname is restored

150

"""

151

152

def send_raw(self, string: str):

153

"""

154

Send raw IRC command.

155

156

Parameters:

157

- string: str, raw IRC protocol message

158

"""

159

160

def send_items(self, *items):

161

"""

162

Send IRC command from items.

163

164

Parameters:

165

- items: IRC command components

166

"""

167

168

def set_rate_limit(self, frequency: float):

169

"""

170

Set rate limiting for outgoing messages.

171

172

Parameters:

173

- frequency: float, maximum messages per second

174

"""

175

176

def set_keepalive(self, interval: int):

177

"""

178

Set keepalive ping interval.

179

180

Parameters:

181

- interval: int, seconds between keepalive pings

182

"""

183

184

def add_global_handler(self, event: str, handler, priority: int = 0):

185

"""

186

Add event handler for this connection.

187

188

Parameters:

189

- event: str, event type

190

- handler: callable, handler function

191

- priority: int, handler priority

192

"""

193

194

def remove_global_handler(self, event: str, handler):

195

"""

196

Remove event handler from this connection.

197

198

Parameters:

199

- event: str, event type

200

- handler: callable, handler to remove

201

"""

202

```

203

204

### IRC Protocol Commands

205

206

Standard IRC protocol commands for server communication, channel operations, and user interactions.

207

208

```python { .api }

209

class ServerConnection:

210

def nick(self, newnick: str):

211

"""

212

Change nickname.

213

214

Parameters:

215

- newnick: str, new nickname

216

"""

217

218

def user(self, username: str, ircname: str):

219

"""

220

Send USER command during registration.

221

222

Parameters:

223

- username: str, username

224

- ircname: str, real name

225

"""

226

227

def join(self, channel: str, key: str = ""):

228

"""

229

Join IRC channel.

230

231

Parameters:

232

- channel: str, channel name (with # prefix)

233

- key: str, optional channel key/password

234

"""

235

236

def part(self, channel: str, message: str = ""):

237

"""

238

Leave IRC channel.

239

240

Parameters:

241

- channel: str, channel name

242

- message: str, optional part message

243

"""

244

245

def privmsg(self, target: str, text: str):

246

"""

247

Send private message to user or channel.

248

249

Parameters:

250

- target: str, recipient (nickname or channel)

251

- text: str, message text

252

"""

253

254

def notice(self, target: str, text: str):

255

"""

256

Send notice to user or channel.

257

258

Parameters:

259

- target: str, recipient (nickname or channel)

260

- text: str, notice text

261

"""

262

263

def quit(self, message: str = ""):

264

"""

265

Quit IRC server.

266

267

Parameters:

268

- message: str, quit message

269

"""

270

271

def ping(self, target: str):

272

"""

273

Send PING to server or user.

274

275

Parameters:

276

- target: str, ping target

277

"""

278

279

def pong(self, target: str):

280

"""

281

Send PONG response.

282

283

Parameters:

284

- target: str, pong target

285

"""

286

287

def kick(self, channel: str, nick: str, comment: str = ""):

288

"""

289

Kick user from channel.

290

291

Parameters:

292

- channel: str, channel name

293

- nick: str, user to kick

294

- comment: str, optional kick reason

295

"""

296

297

def mode(self, target: str, command: str):

298

"""

299

Set user or channel mode.

300

301

Parameters:

302

- target: str, mode target (user or channel)

303

- command: str, mode command (+/-modes)

304

"""

305

306

def topic(self, channel: str, new_topic: str = None):

307

"""

308

Get or set channel topic.

309

310

Parameters:

311

- channel: str, channel name

312

- new_topic: str, optional new topic (None to query)

313

"""

314

315

def whois(self, target: str):

316

"""

317

Query user information.

318

319

Parameters:

320

- target: str, user nickname

321

"""

322

323

def who(self, target: str, op: str = ""):

324

"""

325

Query user list.

326

327

Parameters:

328

- target: str, query target (channel or mask)

329

- op: str, optional WHO flags

330

"""

331

332

def action(self, target: str, action: str):

333

"""

334

Send CTCP ACTION command (/me action).

335

336

Parameters:

337

- target: str, channel or user to send action to

338

- action: str, action message

339

"""

340

341

def admin(self, server: str = ""):

342

"""

343

Query server administrative information.

344

345

Parameters:

346

- server: str, optional server name

347

"""

348

349

def cap(self, subcommand: str, *args):

350

"""

351

Send CAP command for IRCv3 capability negotiation.

352

353

Parameters:

354

- subcommand: str, CAP subcommand (LS, REQ, ACK, etc.)

355

- *args: additional arguments for the subcommand

356

"""

357

358

def ctcp(self, ctcptype: str, target: str, parameter: str = ""):

359

"""

360

Send CTCP command to target.

361

362

Parameters:

363

- ctcptype: str, CTCP command type (VERSION, TIME, etc.)

364

- target: str, target user

365

- parameter: str, optional parameter

366

"""

367

368

def ctcp_reply(self, target: str, parameter: str):

369

"""

370

Send CTCP reply.

371

372

Parameters:

373

- target: str, reply target

374

- parameter: str, reply parameter

375

"""

376

377

def info(self, server: str = ""):

378

"""

379

Query server information.

380

381

Parameters:

382

- server: str, optional server name

383

"""

384

385

def invite(self, nick: str, channel: str):

386

"""

387

Invite user to channel.

388

389

Parameters:

390

- nick: str, user to invite

391

- channel: str, target channel

392

"""

393

394

def ison(self, nicks: list):

395

"""

396

Check if nicknames are online.

397

398

Parameters:

399

- nicks: list, nicknames to check

400

"""

401

402

def list(self, channels: list = None, server: str = ""):

403

"""

404

List channels.

405

406

Parameters:

407

- channels: list, optional channel list to query

408

- server: str, optional server name

409

"""

410

411

def names(self, channels: list = None):

412

"""

413

Get channel member lists.

414

415

Parameters:

416

- channels: list, optional channel list

417

"""

418

419

def oper(self, nick: str, password: str):

420

"""

421

Authenticate as IRC operator.

422

423

Parameters:

424

- nick: str, operator nickname

425

- password: str, operator password

426

"""

427

428

def pass_(self, password: str):

429

"""

430

Send server password (PASS command).

431

432

Parameters:

433

- password: str, server password

434

"""

435

436

def privmsg_many(self, targets: list, text: str):

437

"""

438

Send message to multiple targets.

439

440

Parameters:

441

- targets: list, target channels/users

442

- text: str, message text

443

"""

444

445

def stats(self, statstype: str, server: str = ""):

446

"""

447

Query server statistics.

448

449

Parameters:

450

- statstype: str, statistics type

451

- server: str, optional server name

452

"""

453

454

def time(self, server: str = ""):

455

"""

456

Query server time.

457

458

Parameters:

459

- server: str, optional server name

460

"""

461

462

def userhost(self, nicks: list):

463

"""

464

Get user hostmask information.

465

466

Parameters:

467

- nicks: list, nicknames to query

468

"""

469

470

def version(self, server: str = ""):

471

"""

472

Query server version.

473

474

Parameters:

475

- server: str, optional server name

476

"""

477

478

def wallops(self, text: str):

479

"""

480

Send operator wall message.

481

482

Parameters:

483

- text: str, message text

484

"""

485

486

def whowas(self, nick: str, max: str = "", server: str = ""):

487

"""

488

Query historical user information.

489

490

Parameters:

491

- nick: str, nickname to query

492

- max: str, optional maximum entries

493

- server: str, optional server name

494

"""

495

```

496

497

### SimpleIRCClient

498

499

High-level IRC client that manages a single server connection with simplified event handling and automatic connection management.

500

501

```python { .api }

502

class SimpleIRCClient:

503

@property

504

def reactor(self) -> Reactor:

505

"""Access to underlying reactor."""

506

507

@property

508

def connection(self) -> ServerConnection:

509

"""Active server connection."""

510

511

@property

512

def dcc_connections(self) -> list:

513

"""List of active DCC connections."""

514

515

def __init__(self):

516

"""Initialize simple IRC client."""

517

518

def connect(self, server: str, port: int, nickname: str, **kwargs):

519

"""

520

Connect to IRC server.

521

522

Parameters:

523

- server: str, server hostname

524

- port: int, server port

525

- nickname: str, desired nickname

526

- **kwargs: additional connection parameters

527

"""

528

529

def start(self):

530

"""Start client event processing loop."""

531

532

def dcc(self, dcctype: str = "chat") -> DCCConnection:

533

"""

534

Create DCC connection.

535

536

Parameters:

537

- dcctype: str, DCC connection type

538

539

Returns:

540

DCCConnection instance

541

"""

542

543

def dcc_connect(self, address: tuple, port: int, dcctype: str = "chat") -> DCCConnection:

544

"""

545

Connect to DCC peer.

546

547

Parameters:

548

- address: tuple, peer address

549

- port: int, peer port

550

- dcctype: str, DCC type

551

552

Returns:

553

DCCConnection instance

554

"""

555

556

def dcc_listen(self, dcctype: str = "chat") -> DCCConnection:

557

"""

558

Listen for DCC connections.

559

560

Parameters:

561

- dcctype: str, DCC type

562

563

Returns:

564

DCCConnection instance

565

"""

566

```

567

568

## Usage Examples

569

570

### Basic Connection and Event Handling

571

572

```python

573

import irc.client

574

575

def on_connect(connection, event):

576

print("Connected to server")

577

connection.join("#mychannel")

578

579

def on_join(connection, event):

580

print(f"Joined {event.target}")

581

connection.privmsg(event.target, "Hello everyone!")

582

583

def on_pubmsg(connection, event):

584

print(f"<{event.source.nick}> {event.arguments[0]}")

585

586

# Create client and connect

587

client = irc.client.SimpleIRCClient()

588

client.connect("irc.libera.chat", 6667, "mybot")

589

590

# Add event handlers

591

client.connection.add_global_handler("welcome", on_connect)

592

client.connection.add_global_handler("join", on_join)

593

client.connection.add_global_handler("pubmsg", on_pubmsg)

594

595

# Start processing events

596

client.start()

597

```

598

599

### Multiple Connections with Reactor

600

601

```python

602

import irc.client

603

604

reactor = irc.client.Reactor()

605

606

# Create multiple connections

607

conn1 = reactor.server()

608

conn2 = reactor.server()

609

610

def on_connect(connection, event):

611

if connection == conn1:

612

connection.join("#channel1")

613

else:

614

connection.join("#channel2")

615

616

reactor.add_global_handler("welcome", on_connect)

617

618

# Connect to different servers

619

conn1.connect("irc.libera.chat", 6667, "bot1")

620

conn2.connect("irc.oftc.net", 6667, "bot2")

621

622

# Process events for all connections

623

reactor.process_forever()

624

```

625

626

### Rate Limiting and Connection Management

627

628

```python

629

import irc.client

630

631

client = irc.client.SimpleIRCClient()

632

client.connect("irc.libera.chat", 6667, "mybot")

633

634

# Set rate limiting to 1 message per second

635

client.connection.set_rate_limit(1.0)

636

637

# Set keepalive to ping every 60 seconds

638

client.connection.set_keepalive(60)

639

640

def on_connect(connection, event):

641

connection.join("#test")

642

643

def on_disconnect(connection, event):

644

print("Disconnected, attempting reconnection...")

645

connection.reconnect()

646

647

client.connection.add_global_handler("welcome", on_connect)

648

client.connection.add_global_handler("disconnect", on_disconnect)

649

650

client.start()

651

```