Skip to content

Getting started

pinhook needs Python 3.8 or newer.

pip install pinhook

A bot can be started two ways: from a config file with the pinhook command, or from your own python file. Both take the same options.

From a config file

Config files can be YAML, TOML or JSON.

nickname: "ph-bot"
server: "irc.libera.chat"
port: 6697
ssl_required: true
channels:
    - "#foo"
    - "#bar"
nickname = "ph-bot"
server = "irc.libera.chat"
port = 6697
ssl_required = true
channels = ["#foo", "#bar"]
{
    "nickname": "ph-bot",
    "server": "irc.libera.chat",
    "port": 6697,
    "ssl_required": true,
    "channels": ["#foo", "#bar"]
}

nickname, server and channels are required, everything else is optional.

YAML configs need pip install pinhook[yaml]. TOML configs work out of the box on Python 3.11 and newer, older versions need pip install pinhook[toml].

Start the bot with:

pinhook config.yaml

pinhook works out the format from the file extension. If it can't, tell it with --format:

pinhook --format yaml my-bot.conf

Passwords and other secrets

Keep secrets out of the config file by writing ${NAME}. pinhook fills it in from the environment variable called NAME when the bot starts:

ns_pass: "${PH_NICKSERV_PASSWORD}"
PH_NICKSERV_PASSWORD=hunter2 pinhook config.yaml

It works in any value, including inside lists and plugin settings. If the variable isn't set, the bot doesn't start, and says which one is missing. To write a literal ${ in a value, write $${. New in 1.12.

Mistakes in the config

If the config has a mistake pinhook stops and says which key is wrong. A key it doesn't recognise, like a typo, is logged as a warning with a suggestion instead.

From a python file

from pinhook.bot import Bot

bot = Bot(
    channels=['#foo', '#bar'],
    nickname='ph-bot',
    server='irc.libera.chat',
    port=6697,
    ssl_required=True,
)
bot.start()

Bot can also be subclassed to add your own behaviour. adminbot is a good example.

Your first plugin

When it starts, the bot loads every .py file in its plugin folder (plugins by default, see plugin_dir).

Save this as plugins/hello.py:

import pinhook.plugin

@pinhook.plugin.command('!hello', help_text='says hello back')
def hello(msg):
    return pinhook.plugin.message('hi {}!'.format(msg.nick))

Now !hello in a channel gets a reply, and the command shows up in !help. Change the file and an op can run !reload to pick it up without restarting the bot.

Writing plugins covers the rest: listeners, op-only commands, and everything a plugin can see about a message.

Logs

The bot logs to the console and to <nickname>.log in the folder it runs from. See log_level and log_file to change that, and Troubleshooting for what the messages mean.