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

asynchronous-client.mddocs/

0

# Asynchronous IRC Client

1

2

Asyncio-based IRC client implementation providing full async/await support for modern Python applications. Uses asyncio protocols for non-blocking network communication and integrates seamlessly with asyncio event loops.

3

4

## Capabilities

5

6

### AioReactor

7

8

Asyncio-based reactor for managing IRC connections in asynchronous applications. Integrates with asyncio event loops for non-blocking event processing.

9

10

```python { .api }

11

class AioReactor:

12

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

13

"""

14

Initialize asyncio IRC reactor.

15

16

Parameters:

17

- on_connect: callable, called when connection established

18

- on_disconnect: callable, called when connection lost

19

- loop: asyncio event loop, uses current loop if None

20

"""

21

22

@property

23

def loop(self):

24

"""Asyncio event loop used by reactor."""

25

26

def server(self) -> AioConnection:

27

"""

28

Create new AioConnection for IRC server communication.

29

30

Returns:

31

AioConnection instance

32

"""

33

34

async def process_forever(self):

35

"""

36

Process events indefinitely using asyncio.

37

38

This method runs until all connections are closed.

39

"""

40

41

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

42

"""

43

Add global event handler for all connections.

44

45

Parameters:

46

- event: str, event type to handle

47

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

48

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

49

"""

50

51

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

52

"""

53

Remove global event handler.

54

55

Parameters:

56

- event: str, event type

57

- handler: callable, handler function to remove

58

"""

59

60

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

61

"""

62

Disconnect all managed connections.

63

64

Parameters:

65

- message: str, quit message

66

"""

67

```

68

69

### AioConnection

70

71

Asyncio-based IRC server connection using asyncio protocols for non-blocking network communication.

72

73

```python { .api }

74

class AioConnection:

75

@property

76

def connected(self) -> bool:

77

"""Whether connection is established."""

78

79

@property

80

def features(self) -> FeatureSet:

81

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

82

83

async def connect(self, server, port, nickname, password=None,

84

username=None, ircname=None, connect_factory=connection.AioFactory()):

85

"""

86

Connect to IRC server asynchronously.

87

88

Parameters:

89

- server: server hostname

90

- port: server port

91

- nickname: desired nickname

92

- password: optional server password

93

- username: optional username (defaults to nickname)

94

- ircname: optional real name (defaults to nickname)

95

- connect_factory: optional connection factory (defaults to AioFactory())

96

"""

97

98

def process_data(self, new_data: str):

99

"""

100

Process incoming IRC data.

101

102

Parameters:

103

- new_data: str, raw IRC protocol data

104

"""

105

106

def send_raw(self, string: str):

107

"""

108

Send raw IRC command.

109

110

Parameters:

111

- string: str, raw IRC protocol message

112

"""

113

114

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

115

"""

116

Disconnect from server.

117

118

Parameters:

119

- message: str, quit message

120

"""

121

122

def get_server_name(self) -> str:

123

"""Get connected server name."""

124

125

def get_nickname(self) -> str:

126

"""Get current nickname."""

127

128

def is_connected(self) -> bool:

129

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

130

131

def set_rate_limit(self, frequency: float):

132

"""

133

Set rate limiting for outgoing messages.

134

135

Parameters:

136

- frequency: float, maximum messages per second

137

"""

138

139

def set_keepalive(self, interval: int):

140

"""

141

Set keepalive ping interval.

142

143

Parameters:

144

- interval: int, seconds between keepalive pings

145

"""

146

```

147

148

### AioSimpleIRCClient

149

150

High-level asyncio IRC client that manages a single server connection with simplified event handling for async applications.

151

152

```python { .api }

153

class AioSimpleIRCClient:

154

@property

155

def reactor(self) -> AioReactor:

156

"""Access to underlying asyncio reactor."""

157

158

@property

159

def connection(self) -> AioConnection:

160

"""Active server connection."""

161

162

def __init__(self):

163

"""Initialize asyncio simple IRC client."""

164

165

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

166

"""

167

Connect to IRC server asynchronously.

168

169

Parameters:

170

- server: str, server hostname

171

- port: int, server port

172

- nickname: str, desired nickname

173

- **kwargs: additional connection parameters

174

"""

175

```

176

177

### IrcProtocol

178

179

Asyncio protocol implementation for IRC communication handling low-level network operations.

180

181

```python { .api }

182

class IrcProtocol:

183

def __init__(self, connection, loop):

184

"""

185

Initialize IRC protocol handler.

186

187

Parameters:

188

- connection: AioConnection, associated connection

189

- loop: asyncio event loop

190

"""

191

192

def data_received(self, data: bytes):

193

"""

194

Handle received network data.

195

196

Parameters:

197

- data: bytes, raw network data

198

"""

199

200

def connection_lost(self, exc):

201

"""

202

Handle connection loss.

203

204

Parameters:

205

- exc: Exception, optional exception that caused disconnection

206

"""

207

```

208

209

## IRC Protocol Commands (Async)

210

211

All standard IRC protocol commands are available on AioConnection with the same interface as ServerConnection:

212

213

```python { .api }

214

class AioConnection:

215

def nick(self, newnick: str):

216

"""Change nickname."""

217

218

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

219

"""Send USER command during registration."""

220

221

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

222

"""Join IRC channel."""

223

224

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

225

"""Leave IRC channel."""

226

227

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

228

"""Send private message to user or channel."""

229

230

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

231

"""Send notice to user or channel."""

232

233

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

234

"""Quit IRC server."""

235

236

def ping(self, target: str):

237

"""Send PING to server or user."""

238

239

def pong(self, target: str):

240

"""Send PONG response."""

241

242

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

243

"""Kick user from channel."""

244

245

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

246

"""Set user or channel mode."""

247

248

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

249

"""Get or set channel topic."""

250

251

def whois(self, target: str):

252

"""Query user information."""

253

254

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

255

"""Query user list."""

256

```

257

258

## Usage Examples

259

260

### Basic Asyncio IRC Client

261

262

```python

263

import asyncio

264

from irc.client_aio import AioSimpleIRCClient

265

266

async def main():

267

client = AioSimpleIRCClient()

268

269

def on_connect(connection, event):

270

print("Connected to server")

271

connection.join("#test")

272

273

def on_join(connection, event):

274

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

275

connection.privmsg(event.target, "Hello from async bot!")

276

277

def on_pubmsg(connection, event):

278

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

279

# Echo messages back

280

connection.privmsg(event.target, f"Echo: {event.arguments[0]}")

281

282

# Add event handlers

283

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

284

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

285

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

286

287

# Connect to server

288

await client.connect("irc.libera.chat", 6667, "asyncbot")

289

290

# Keep running

291

await asyncio.Event().wait()

292

293

asyncio.run(main())

294

```

295

296

### Multiple Async Connections

297

298

```python

299

import asyncio

300

from irc.client_aio import AioReactor

301

302

async def main():

303

reactor = AioReactor()

304

305

# Create multiple connections

306

conn1 = reactor.server()

307

conn2 = reactor.server()

308

309

def on_connect(connection, event):

310

if connection == conn1:

311

connection.join("#channel1")

312

else:

313

connection.join("#channel2")

314

315

def on_pubmsg(connection, event):

316

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

317

318

reactor.add_global_handler("welcome", on_connect)

319

reactor.add_global_handler("pubmsg", on_pubmsg)

320

321

# Connect to multiple servers

322

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

323

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

324

325

# Process events for all connections

326

await reactor.process_forever()

327

328

asyncio.run(main())

329

```

330

331

### Async Bot with Periodic Tasks

332

333

```python

334

import asyncio

335

from irc.client_aio import AioSimpleIRCClient

336

337

async def periodic_announce(client):

338

"""Send periodic announcements."""

339

while True:

340

await asyncio.sleep(300) # 5 minutes

341

if client.connection.is_connected():

342

client.connection.privmsg("#test", "Periodic announcement!")

343

344

async def main():

345

client = AioSimpleIRCClient()

346

347

def on_connect(connection, event):

348

connection.join("#test")

349

print("Connected and joined channel")

350

351

def on_pubmsg(connection, event):

352

message = event.arguments[0]

353

if message.startswith("!time"):

354

import datetime

355

now = datetime.datetime.now().strftime("%H:%M:%S")

356

connection.privmsg(event.target, f"Current time: {now}")

357

358

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

359

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

360

361

# Connect to server

362

await client.connect("irc.libera.chat", 6667, "timebot")

363

364

# Start periodic task

365

announce_task = asyncio.create_task(periodic_announce(client))

366

367

try:

368

# Wait indefinitely

369

await asyncio.Event().wait()

370

except KeyboardInterrupt:

371

announce_task.cancel()

372

client.connection.quit("Bot shutting down")

373

374

asyncio.run(main())

375

```

376

377

### Async Connection with SSL

378

379

```python

380

import asyncio

381

import ssl

382

from irc.client_aio import AioSimpleIRCClient

383

from irc.connection import AioFactory

384

385

async def main():

386

# Create SSL context

387

ssl_context = ssl.create_default_context()

388

389

# Create SSL connection factory

390

ssl_factory = AioFactory(ssl=ssl_context)

391

392

client = AioSimpleIRCClient()

393

394

def on_connect(connection, event):

395

connection.join("#secure")

396

print("Connected via SSL")

397

398

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

399

400

# Connect with SSL on port 6697

401

await client.connect(

402

"irc.libera.chat",

403

6697,

404

"sslbot",

405

connect_factory=ssl_factory

406

)

407

408

await asyncio.Event().wait()

409

410

asyncio.run(main())

411

```

412

413

### Integration with Web Framework

414

415

```python

416

import asyncio

417

from aiohttp import web

418

from irc.client_aio import AioSimpleIRCClient

419

420

class IRCBot:

421

def __init__(self):

422

self.client = AioSimpleIRCClient()

423

self.messages = []

424

425

async def start(self):

426

def on_connect(connection, event):

427

connection.join("#webapp")

428

429

def on_pubmsg(connection, event):

430

self.messages.append({

431

'nick': event.source.nick,

432

'message': event.arguments[0],

433

'timestamp': asyncio.get_event_loop().time()

434

})

435

# Keep only last 100 messages

436

self.messages = self.messages[-100:]

437

438

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

439

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

440

441

await self.client.connect("irc.libera.chat", 6667, "webapp_bot")

442

443

def send_message(self, message):

444

self.client.connection.privmsg("#webapp", message)

445

446

bot = IRCBot()

447

448

async def send_message(request):

449

data = await request.json()

450

bot.send_message(data['message'])

451

return web.json_response({'status': 'sent'})

452

453

async def get_messages(request):

454

return web.json_response({'messages': bot.messages})

455

456

async def init_app():

457

await bot.start()

458

459

app = web.Application()

460

app.router.add_post('/send', send_message)

461

app.router.add_get('/messages', get_messages)

462

463

return app

464

465

if __name__ == '__main__':

466

web.run_app(init_app(), host='0.0.0.0', port=8080)

467

```