lightweight asyncio IRC clientΒΆ
With a very small API, bottom lets you wrap an IRC connection and handle events how you want. There are no assumptions about reconnecting, rate limiting, or even when to respond to PINGs.
Explicit is better than implicit: no magic importing or naming to remember for
plugins. Extend the client with the same @on
decorator.
Create an instance:
import asyncio
import bottom
host = 'chat.freenode.net'
port = 6697
ssl = True
NICK = "bottom-bot"
CHANNEL = "#bottom-dev"
bot = bottom.Client(host=host, port=port, ssl=ssl)
Send nick/user/join when connection is established:
@bot.on('CLIENT_CONNECT')
async def connect(**kwargs):
bot.send('NICK', nick=NICK)
bot.send('USER', user=NICK,
realname='https://github.com/numberoverzero/bottom')
# Don't try to join channels until the server has
# sent the MOTD, or signaled that there's no MOTD.
done, pending = await asyncio.wait(
[bot.wait("RPL_ENDOFMOTD"),
bot.wait("ERR_NOMOTD")],
loop=bot.loop,
return_when=asyncio.FIRST_COMPLETED
)
# Cancel whichever waiter's event didn't come in.
for future in pending:
future.cancel()
bot.send('JOIN', channel=CHANNEL)
Respond to ping:
@bot.on('PING')
def keepalive(message, **kwargs):
bot.send('PONG', message=message)
Echo messages (channel and direct messages):
@bot.on('PRIVMSG')
def message(nick, target, message, **kwargs):
""" Echo all messages """
# Don't echo ourselves
if nick == NICK:
return
# Respond directly to direct messages
if target == NICK:
bot.send("PRIVMSG", target=nick, message=message)
# Channel message
else:
bot.send("PRIVMSG", target=target, message=message)
Connect and run the bot forever:
bot.loop.create_task(bot.connect())
bot.loop.run_forever()