All source listed below is under MIT license if no LICENSE file stating different is available.

Snekbot API

This is the Snekbot API. This document describes how to create a bot responding to "hello", "bye" and "@username-of-bot".

5 minute tutorial

Literally.

Installation

Requirements:

Python:

  • python3
  • python3-venv
  • python3-pip Use apt or your package manager to install these packages. There is a big chance your system already has them.

For Debian (Ubuntu): sudo apt install python3 python3-venv python3-pip -y

Environment

  • python3 -m venv venv
  • source venv/bin/activate
  • pip install git+https://molodetz.nl/retoor/snekbot.git

Create account

Create regular user account for your bot. You need this later in your script. Make sure you have this information right now:

  • bot username
  • bot password
  • bot url (wss://your-snek-instance.com/rpc.ws)

Create a file

Open a file ending with the .py extension and paste this content. Replace the authentication details on the bottom lines with the one of the account you just created.

import asyncio

from snekbot.bot import Bot


class ExampleBot(Bot):

    async def on_join(self, channel_uid):
        print(f"I joined!")
        await self.send_message(
                channel_uid, 
                f"Hello, i'm actively part of the conversation in channel {channel_uid} now, you don't have to mention me anymore. "
        )

    async def on_leave(self, channel_uid):
        print(f"I left!!")
        await self.send_message(
                channel_uid,
                "I stop actively being part of the conversation now. Bye!"
        )

    async def on_ping(self,username, user_nick, channel_uid, message):
        print(f"Ping from {user_nick} in channel {channel_uid}: {message}")
        await self.send_message(
            channel_uid,
            "pong " + message
        )

    async def on_own_message(self, data):
        print(f"Received my own message: {data.message}")

    async def on_mention(self, username, user_nick, channel_uid, message):

        message = message[len(self.username) + 2 :]
        print(f"Mention from {user_nick}: {message}")

        if "source" in message:
            with open(__file__) as f:
                result = f.read()
            result = result.replace(f'"{self.username}"', '"example username"')
            result = result.replace(self.password, "example password")
            result = (
                "This is the actual source code running me now. Fresh from the bakery:\n\n```python\n"
                + result
                + "\n```"
            )
            await self.send_message(channel_uid, result)
        else:
            await self.send_message(channel_uid, f'Hey {user_nick}, Thanks for mentioning me "{message}".')

    async def on_message(self, sender_username, sender_nick, channel_uid, message):
        print(f"Message  from {sender_nick}: {message}")
        if not self.has_joined(channel_uid):
            print(f"Probably not for me since i'm not mentioned and not joined yet")
            return
        message = message.lower()
        result = None
        if "hello" in message:
            result = f"Hi @{sender_nick}"
        elif "bye" in message:
            result = f"Bye @{sender_nick}"

        if result:
            await self.send_message(channel_uid, result)


bot = ExampleBot(url="ws://snek.molodetz.nl/rpc.ws", username="example", password="example")
asyncio.run(bot.run())

Run the bot

Make sure you have (still) activated your virtual env.

python [your-script].py

If you get the error 'python not found' or 'aiohttp not found', run source .venv/bin/activate again and run python [your script].py again.

Debugging

Add import logging and logging.BasicConfig(level=logging.DEBUG).

Summary

The ExampleBot class inherits from a base Bot class and implements several event handlers:

  • on_join: Sends a welcome message when the bot joins a channel.
  • on_leave: Sends a goodbye message when the bot leaves.
  • on_ping: Responds with "pong" when it receives a ping message.
  • on_own_message: Logs messages sent by the bot itself.
  • on_mention: Handles mentions; if "source" is in the message, it replies with its own source code, with sensitive data disguised.
  • on_message: Responds to "hello" and "bye" messages if the bot has joined the channel. The bot will be instantiated and runs asynchronously. It will survive server deploys and network outages. If such issue occurs, it will try to reconnect within a second like nothing happened. It's production ready.
dist
src
.gitignore
example.py
LICENSE.txt
Makefile
pyproject.toml
README.md
TODO.md