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
```