feat: initial IRC bouncer implementation

Async Python IRC bouncer with SOCKS5 proxy support, multi-network
connections, password auth, and persistent SQLite backlog with replay.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
user
2026-02-19 11:29:59 +01:00
commit ced6232373
28 changed files with 2079 additions and 0 deletions

53
docs/CHEATSHEET.md Normal file
View File

@@ -0,0 +1,53 @@
# Cheatsheet
## Commands
```bash
bouncer -c config/bouncer.toml # Start with config
bouncer -c config/bouncer.toml -v # Start with debug output
bouncer --version # Show version
bouncer --help # Show help
```
## Development
```bash
make dev # Install with dev deps
make test # Run pytest
make lint # Run ruff
make fmt # Format with black + ruff
make run # Run with default config
make clean # Remove .venv and build artifacts
```
## Client Connection
```
PASS <network>:<password> # Authenticate + select network
PASS <password> # Authenticate, use first network
```
## Config Structure
```toml
[bouncer] # Listener settings
bind / port / password
[bouncer.backlog] # Backlog settings
max_messages / replay_on_connect
[proxy] # SOCKS5 proxy
host / port
[networks.<name>] # IRC server (repeatable)
host / port / tls
nick / user / realname
channels / autojoin / password
```
## Files
| Path | Purpose |
|------|---------|
| `config/bouncer.toml` | Active configuration |
| `config/bouncer.db` | SQLite backlog database |
| `config/bouncer.example.toml` | Example config template |

75
docs/DEBUG.md Normal file
View File

@@ -0,0 +1,75 @@
# Debugging
## Verbose Mode
```bash
bouncer -c config/bouncer.toml -v
```
Debug logging shows:
- SOCKS5 proxy connection attempts
- IRC server registration
- Client connect/disconnect events
- Message routing
- Backlog replay counts
## Common Issues
### "config not found"
Ensure the config path is correct:
```bash
bouncer -c /full/path/to/bouncer.toml
```
### Connection refused (SOCKS5 proxy)
Verify the proxy is running:
```bash
ss -tlnp | grep 1080
```
### Connection timeout to IRC server
Check the SOCKS5 proxy can reach the IRC server:
```bash
curl --socks5 127.0.0.1:1080 -v telnet://irc.libera.chat:6697
```
### Nick already in use
The bouncer appends `_` to the nick and retries. Check logs for:
```
WARNING bouncer.network [libera] nick in use, trying mynick_
```
### TLS certificate errors
If connecting to a server with a self-signed cert, this is currently not supported. All TLS connections use the system CA store.
## Inspecting the Backlog Database
```bash
sqlite3 config/bouncer.db
-- Recent messages
SELECT * FROM messages ORDER BY id DESC LIMIT 20;
-- Messages per network
SELECT network, COUNT(*) FROM messages GROUP BY network;
-- Client state
SELECT * FROM client_state;
```
## Log Format
```
HH:MM:SS LEVEL module message
```
Levels: `DEBUG`, `INFO`, `WARNING`, `ERROR`

42
docs/INSTALL.md Normal file
View File

@@ -0,0 +1,42 @@
# Installation
## Prerequisites
- Python 3.10+
- SOCKS5 proxy running on `127.0.0.1:1080`
## Setup
```bash
cd ~/git/bouncer
make dev
```
This creates `.venv/`, installs dependencies, and registers the `bouncer` command.
## Verify
```bash
bouncer --version
```
## Configuration
```bash
cp config/bouncer.example.toml config/bouncer.toml
```
Edit `config/bouncer.toml` with your network details. At minimum, set:
- `bouncer.password` -- client authentication password
- `networks.<name>.host` -- IRC server hostname
- `networks.<name>.nick` -- your IRC nickname
- `networks.<name>.channels` -- channels to auto-join
## Symlink
The `make dev` editable install registers `bouncer` in `.venv/bin/`. To make it available system-wide:
```bash
ln -sf ~/git/bouncer/.venv/bin/bouncer ~/.local/bin/bouncer
```

77
docs/USAGE.md Normal file
View File

@@ -0,0 +1,77 @@
# Usage
## Starting the Bouncer
```bash
bouncer -c config/bouncer.toml -v
```
| Flag | Description |
|------|-------------|
| `-c, --config PATH` | Config file (default: `config/bouncer.toml`) |
| `-v, --verbose` | Debug logging |
| `--version` | Show version |
## Connecting with an IRC Client
Configure your IRC client to connect to the bouncer:
| Setting | Value |
|---------|-------|
| Server | `127.0.0.1` |
| Port | `6667` (or as configured) |
| Password | `networkname:yourpassword` |
### Password Format
```
PASS <network>:<password>
```
- `network` -- matches a `[networks.NAME]` section in config
- `password` -- the `bouncer.password` value from config
If you omit the network prefix (`PASS yourpassword`), the first configured network is used.
### Client Examples
**irssi:**
```
/connect -password libera:mypassword 127.0.0.1 6667
```
**weechat:**
```
/server add bouncer 127.0.0.1/6667 -password=libera:mypassword
/connect bouncer
```
**hexchat:**
Set server password to `libera:mypassword` in the network settings.
## Multiple Networks
Define multiple `[networks.*]` sections in the config. Connect with different passwords to access each:
```
PASS libera:mypassword # connects to libera
PASS oftc:mypassword # connects to oftc
```
Multiple clients can attach to the same network simultaneously.
## Backlog
Messages are stored in `bouncer.db` (SQLite) next to the config file. When you reconnect, missed messages are automatically replayed.
Configure backlog in `bouncer.toml`:
```toml
[bouncer.backlog]
max_messages = 10000 # per network, 0 = unlimited
replay_on_connect = true # set false to disable replay
```
## Stopping
Press `Ctrl+C` or send `SIGTERM`. The bouncer shuts down gracefully.