Home
Softono

Hanna

Open source Go
11
Stars
3
Forks
0
Issues
0
Watchers
10 months
Last Commit

 About Hanna

Build sophisticated IRCv3 bots using n8n's visual interface - no coding required

Platforms

Web Self-hosted

Languages

Go

Links

Need Help Installing Hanna?

We provide expert installation service for this software. Our team will install, configure, and secure Hanna on your server. plans start at just $30.

Hanna - IRC Bot with REST API

npm version

A robust, self-contained Go IRC bot that connects over TLS and exposes a secure, token-authenticated REST API for remote control. Perfect for automation, monitoring, and integration with other services.

πŸš€ Features

  • Secure IRC Connection: TLS-enabled IRC connections with optional server password support
  • SASL Authentication: Optional SASL PLAIN authentication for IRC networks that require it
  • Auto-Reconnect: Intelligent reconnection with exponential backoff for maximum uptime
  • REST API: Token-protected HTTP/HTTPS endpoints for complete bot control
  • IRC Network Discovery: List channels and get user information via LIST and WHOIS commands
  • Flexible Event System: Advanced trigger system supporting multiple IRC events (mentions, joins, parts, mode changes, etc.)
  • n8n Integration: Comprehensive n8n node package with both action and trigger nodes
  • Multiple Webhooks: Support for multiple trigger endpoints with filtering and authentication
  • Channel Management: Join, part, and track channels programmatically
  • Message Control: Send messages, notices, and raw IRC commands via API
  • Graceful Shutdown: Clean disconnection and resource cleanup
  • Zero Dependencies: Self-contained binary with no external dependencies
  • Production Ready: Comprehensive logging, error handling, and monitoring endpoints

πŸ“‹ Requirements

  • Go 1.24 or later
  • IRC server with TLS support
  • (Optional) TLS certificates for HTTPS API

πŸ› οΈ Installation

From Source

# Clone the repository
git clone https://github.com/h4ks-com/hanna
cd hanna

# Build from source (no need for go mod tidy - dependencies are all local)
go build -o hanna .

# Or build with specific flags for production
CGO_ENABLED=0 go build -ldflags="-w -s" -o hanna .

Docker Build

# Build using Docker
docker build -t hanna-bot .

# Or using docker-compose
docker-compose build hanna-bot

Project Structure

The project is organized as a proper Go module:

hanna/
β”œβ”€β”€ main.go              # Main application entry point
β”œβ”€β”€ irc/                 # IRC client package
β”‚   β”œβ”€β”€ client.go        # IRC client implementation
β”‚   └── *_test.go        # Tests for IRC functionality
β”œβ”€β”€ go.mod               # Go module definition
└── Dockerfile           # Docker build configuration

Quick Start

# Basic setup with HTTP API
API_TOKEN=your_secret_token \
IRC_ADDR=irc.libera.chat:6697 \
IRC_NICK=YourBotName \
./hanna

βš™οΈ Configuration

All configuration is done via environment variables:

IRC Configuration

Variable Description Default Required
IRC_ADDR IRC server address (host:port) - βœ…
IRC_TLS Enable TLS connection 1 ❌
IRC_TLS_INSECURE Skip TLS certificate verification 0 ❌
IRC_PASS Server password - ❌
IRC_NICK Bot nickname goircbot ❌
IRC_USER Username/ident goircbot ❌
IRC_NAME Real name/GECOS Go IRC Bot ❌
SASL_USER SASL authentication username - ❌
SASL_PASS SASL authentication password - ❌
AUTOJOIN Comma-separated channels to auto-join - ❌

API Configuration

Variable Description Default Required
API_ADDR HTTP/HTTPS listen address :8080 ❌
API_TOKEN Bearer token for API authentication - ⚠️
API_TLS Enable HTTPS 0 ❌
API_CERT Path to TLS certificate file - ⚠️*
API_KEY Path to TLS private key file - ⚠️*

n8n Integration

Variable Description Default Required
N8N_WEBHOOK Legacy webhook URL for chat integration - ❌
TRIGGER_CONFIG JSON configuration for multiple trigger endpoints - ❌

Event Trigger Configuration

The bot supports a flexible trigger system for sending IRC events to multiple endpoints:

Legacy Mode (backward compatible):

export N8N_WEBHOOK="https://n8n.example.com/webhook/irc-bot"

Advanced Mode (recommended):

export TRIGGER_CONFIG='{
  "endpoints": {
    "mentions": {
      "url": "https://n8n.example.com/webhook/mentions",
      "token": "secret-token-123",
      "events": ["mention"],
      "channels": ["#support", "#general"]
    },
    "moderation": {
      "url": "https://n8n.example.com/webhook/moderation", 
      "token": "mod-token-456",
      "events": ["join", "part", "kick", "mode"],
      "channels": ["#general"]
    }
  }
}'

Supported Event Types:

  • mention - When the bot is mentioned
  • privmsg - All channel/private messages
  • join - User joins a channel
  • part - User leaves a channel
  • quit - User quits IRC
  • kick - User is kicked from channel
  • mode - Mode changes (op, voice, etc.)
  • nick - Nickname changes
  • topic - Channel topic changes
  • notice - IRC notices

*Required when API_TLS=1
⚠️ Highly recommended for security

πŸ”’ HTTPS Setup

Using Let's Encrypt

If you have Let's Encrypt certificates for your domain:

export API_TLS=1
export API_CERT=/etc/letsencrypt/live/yourdomain.com/fullchain.pem
export API_KEY=/etc/letsencrypt/live/yourdomain.com/privkey.pem

Self-Signed Certificates (Development)

# Generate self-signed certificate
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes

# Use with bot
export API_TLS=1
export API_CERT=cert.pem
export API_KEY=key.pem

🌐 API Reference

Authentication

All API endpoints (except /health) require a Bearer token:

curl -H "Authorization: Bearer your_secret_token" https://your-server:8080/api/state

Endpoints

Health Check

GET /health

Returns bot connection status and current nickname.

Response:

{
  "ok": true,
  "nick": "YourBot"
}

Bot State

GET /api/state
Authorization: Bearer <token>

Returns comprehensive bot status including connected channels.

Response:

{
  "connected": true,
  "nick": "YourBot",
  "channels": ["#general", "#bots"]
}

Join Channel

POST /api/join
Authorization: Bearer <token>
Content-Type: application/json

{
  "channel": "#example"
}

Leave Channel

POST /api/part
Authorization: Bearer <token>
Content-Type: application/json

{
  "channel": "#example",
  "reason": "Goodbye!"
}

Send Message

POST /api/send
Authorization: Bearer <token>
Content-Type: application/json

{
  "target": "#example",
  "message": "Hello, world!"
}

Send Notice

POST /api/notice
Authorization: Bearer <token>
Content-Type: application/json

{
  "target": "#example",
  "message": "This is a notice"
}

Change Nickname

POST /api/nick
Authorization: Bearer <token>
Content-Type: application/json

{
  "nick": "NewBotName"
}

Send Raw IRC Command

POST /api/raw
Authorization: Bearer <token>
Content-Type: application/json

{
  "line": "PRIVMSG #channel :Custom message"
}

List IRC Channels

GET /api/list
Authorization: Bearer <token>

Response:

{
  "channels": [
    {
      "channel": "#general",
      "users": "42",
      "topic": "Welcome to the general discussion channel"
    },
    {
      "channel": "#bots",
      "users": "15", 
      "topic": "Bot testing and development"
    }
  ],
  "count": 2
}

Get User Information (WHOIS)

POST /api/whois
Authorization: Bearer <token>
Content-Type: application/json

{
  "nick": "username"
}

Response:

{
  "nick": "username",
  "user": "user",
  "host": "example.com",
  "real_name": "Real Name",
  "server": "irc.libera.chat",
  "server_info": "Stockholm, Sweden",
  "operator": false,
  "idle_seconds": "42",
  "idle_info": "seconds idle",
  "channels": "@#ops +#general #random",
  "raw_data": [
    {
      "type": "user",
      "nick": "username",
      "user": "user",
      "host": "example.com",
      "real_name": "Real Name"
    }
  ]
}

πŸ“ Usage Examples

Basic Bot Setup

#!/bin/bash

# Production setup with HTTPS and advanced n8n trigger integration
export API_TOKEN="$(openssl rand -hex 32)"
export API_TLS=1
export API_CERT="/etc/letsencrypt/live/bot.example.com/fullchain.pem"
export API_KEY="/etc/letsencrypt/live/bot.example.com/privkey.pem"
export API_ADDR=":443"

export IRC_ADDR="irc.libera.chat:6697"
export IRC_NICK="MyAwesomeBot"
export IRC_USER="mybot"
export IRC_NAME="My Awesome IRC Bot"
export AUTOJOIN="#general,#bots"

# Advanced trigger configuration for multiple n8n workflows
export TRIGGER_CONFIG='{
  "endpoints": {
    "mentions": {
      "url": "https://n8n.example.com/webhook/bot-mentions",
      "token": "mention-token-123",
      "events": ["mention"],
      "channels": ["#general", "#support"]
    },
    "moderation": {
      "url": "https://n8n.example.com/webhook/moderation",
      "token": "mod-token-456", 
      "events": ["join", "part", "kick", "mode"],
      "channels": ["#general"]
    },
    "private-messages": {
      "url": "https://n8n.example.com/webhook/private-chat",
      "token": "private-token-789",
      "events": ["privmsg"],
      "channels": []
    }
  }
}'

./hanna

n8n Integration & Event Triggers

The bot provides comprehensive integration with n8n through both legacy webhooks and the new trigger system.

Legacy Webhook Integration (Simple)

When someone mentions the bot in IRC with @botname message, the bot will automatically call the configured n8n webhook:

{
  "eventType": "mention",
  "sender": "username",
  "target": "#channel", 
  "message": "hello bot",
  "chatInput": "@botname hello bot",
  "botNick": "MyAwesomeBot",
  "sessionId": "IRC",
  "timestamp": 1692345678,
  "messageTags": {
    "time": "2023-09-01T12:00:00.000Z"
  }
}

Advanced Trigger System (Recommended)

The new trigger system supports multiple IRC events and endpoints:

1. Install the n8n Node Package

# In your n8n installation
npm install n8n-nodes-hanna

2. Create Trigger Workflows

  • Add "Hanna Bot Trigger" nodes to your workflows
  • Configure authentication tokens and event filters
  • Copy webhook URLs to your TRIGGER_CONFIG

3. Event Examples:

User Joins Channel:

{
  "eventType": "join",
  "sender": "newuser",
  "target": "#general",
  "message": "",
  "botNick": "MyBot",
  "timestamp": 1692345678
}

Channel Mode Change:

{
  "eventType": "mode", 
  "sender": "operator",
  "target": "#general",
  "message": "Mode #general +o newop",
  "timestamp": 1692345678
}

Private Message:

{
  "eventType": "privmsg",
  "sender": "user123",
  "target": "MyBot",
  "message": "Hello bot, how are you?",
  "chatInput": "Hello bot, how are you?",
  "timestamp": 1692345678
}

Example n8n Workflow Setup

Using the New Trigger Node (Recommended):

  1. Install n8n-nodes-hanna package in your n8n instance
  2. Create a new workflow in n8n
  3. Add a "Hanna Bot Trigger" node
  4. Configure:
    • Authentication token (create a secure random token)
    • Select events you want to monitor (mention, join, part, etc.)
    • Optional: Filter by channels or users
  5. Copy the webhook URL from the trigger node
  6. Add the URL and token to your bot's TRIGGER_CONFIG
  7. Add processing nodes (OpenAI, database, notifications, etc.)
  8. Optionally add "Hanna Bot" action node to send responses back to IRC

Using Legacy Webhook:

  1. Create a new workflow in n8n
  2. Add a "Webhook" trigger node
  3. Set the webhook URL in the N8N_WEBHOOK environment variable
  4. Process the incoming IRC data and respond as needed
  5. Optionally use the Hanna API to send responses back to IRC

Advanced Workflow Examples

AI-Powered Chat Bot:

Hanna Bot Trigger (mention events) 
  β†’ OpenAI Chat Completion
  β†’ Hanna Bot Send Message

Channel Moderation:

Hanna Bot Trigger (kick, mode events)
  β†’ Log to Database
  β†’ Send Alert if Spam Detected
  β†’ Auto-Ban Repeat Offenders

Welcome System:

Hanna Bot Trigger (join events)
  β†’ Check User Database
  β†’ Send Welcome Message for New Users
  β†’ Assign Roles Based on Rules

Multi-Channel Bot:

Trigger 1: Support Channel (mention, privmsg in #support)
  β†’ Route to Support AI
  β†’ Log Support Ticket
  
Trigger 2: General Chat (mention in #general)  
  β†’ Route to Fun AI
  β†’ Random Responses

Mention Examples:

  • @MyAwesomeBot what's the weather? β†’ Triggers mention event
  • @MyAwesomeBot help β†’ Triggers mention event
  • MyAwesomeBot hello β†’ Does NOT trigger mention (missing @)
  • @DifferentBot hello β†’ Does NOT trigger mention (wrong bot name)

Other Event Examples:

  • User joins #general β†’ Triggers join event
  • User types hello everyone in #general β†’ Triggers privmsg event
  • Operator gives voice to user β†’ Triggers mode event
  • User gets kicked from channel β†’ Triggers kick event

Send Message via API

# Send a message to a channel
curl -X POST \
  -H "Authorization: Bearer your_secret_token" \
  -H "Content-Type: application/json" \
  -d '{"target": "#general", "message": "Hello from the API!"}' \
  https://bot.example.com/api/send

# Check bot status
curl -H "Authorization: Bearer your_secret_token" \
  https://bot.example.com/api/state

# Join a new channel
curl -X POST \
  -H "Authorization: Bearer your_secret_token" \
  -H "Content-Type: application/json" \
  -d '{"channel": "#newchannel"}' \
  https://bot.example.com/api/join

Integration Examples

Python Integration

import requests
import json

class IRCBotAPI:
    def __init__(self, base_url, token):
        self.base_url = base_url.rstrip('/')
        self.headers = {
            'Authorization': f'Bearer {token}',
            'Content-Type': 'application/json'
        }
    
    def send_message(self, target, message):
        data = {'target': target, 'message': message}
        response = requests.post(
            f'{self.base_url}/api/send',
            headers=self.headers,
            json=data
        )
        return response.json()
    
    def get_status(self):
        response = requests.get(
            f'{self.base_url}/api/state',
            headers=self.headers
        )
        return response.json()

# Usage
bot = IRCBotAPI('https://bot.example.com', 'your_secret_token')
bot.send_message('#general', 'Hello from Python!')
status = bot.get_status()
print(f"Bot is {'connected' if status['connected'] else 'disconnected'}")

Shell Script Integration

#!/bin/bash

BOT_URL="https://bot.example.com"
BOT_TOKEN="your_secret_token"

send_irc_message() {
    local channel="$1"
    local message="$2"
    
    curl -s -X POST \
        -H "Authorization: Bearer $BOT_TOKEN" \
        -H "Content-Type: application/json" \
        -d "{\"target\": \"$channel\", \"message\": \"$message\"}" \
        "$BOT_URL/api/send"
}

# Send system status to IRC
LOAD=$(uptime | awk -F'load average:' '{print $2}')
send_irc_message "#monitoring" "Server load: $LOAD"

🐳 Docker Deployment

Quick Start with Docker Compose

The easiest way to run Hanna is using Docker Compose with the included configuration:

  1. Copy environment template:

    cp .env.example .env
    
  2. Configure your bot: Edit .env and set at least:

    IRC_ADDR=irc.libera.chat:6697
    IRC_NICK=YourBotName
    API_TOKEN=your-secure-token-here
    AUTOJOIN=#your-channels
    
  3. Start the services:

    docker compose up -d
    

This will start both Hanna IRC bot and n8n for workflow automation. The bot will be available at http://localhost:8080 and n8n at http://localhost:5678.

Docker Compose Configuration

The included compose.yaml provides:

  • Hanna IRC Bot: Main bot service with API
  • n8n: Workflow automation platform for chat processing
  • n8n Workflow Loader: Sidecar container that automatically loads workflows on startup
  • Automatic networking: Bot can communicate with n8n via http://n8n:5678
  • Persistent storage: n8n workflows and data are preserved
  • Environment-based config: All settings from .env file

Automatic Workflow Loading

The Docker Compose setup includes a workflow loader that automatically imports workflows into n8n:

  1. Default Echo Bot: A pre-configured workflow that echoes IRC messages
  2. Auto-Import: Workflows in n8n-workflow-loader/workflows/ are loaded on startup
  3. Skip Existing: Already-imported workflows are detected and skipped
  4. Auto-Activation: Imported workflows are automatically activated
  5. Trigger Integration: The bot's TRIGGER_CONFIG is automatically configured

Adding Custom Workflows:

  1. Place workflow JSON files in n8n-workflow-loader/workflows/
  2. Remove the id field from the workflow JSON
  3. Restart with docker-compose up -d

The workflow loader uses the n8n REST API and includes error handling and duplicate detection.

Manual Docker Build

If you prefer to build and run manually:

# Build the image
docker build -t hanna-bot .

# Run with environment variables
docker run -d \
  --name hanna \
  -p 8080:8080 \
  -e API_TOKEN=your_secret_token \
  -e IRC_ADDR=irc.libera.chat:6697 \
  -e IRC_NICK=DockerBot \
  -e AUTOJOIN="#general,#bots" \
  hanna-bot

πŸ”§ Systemd Service

Create /etc/systemd/system/hanna.service:

[Unit]
Description=Hanna IRC Bot
After=network.target

[Service]
Type=simple
User=ircd
Group=ircd
WorkingDirectory=/opt/hanna
ExecStart=/opt/hanna/hanna
EnvironmentFile=/opt/hanna/.env
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Environment file /opt/hanna/.env:

API_TOKEN=your_secret_token
API_TLS=1
API_CERT=/etc/letsencrypt/live/bot.example.com/fullchain.pem
API_KEY=/etc/letsencrypt/live/bot.example.com/privkey.pem
IRC_ADDR=irc.libera.chat:6697
IRC_NICK=HannaBot
AUTOJOIN=#general

# Advanced trigger configuration
TRIGGER_CONFIG={"endpoints":{"mentions":{"url":"https://n8n.example.com/webhook/mentions","token":"secure-token-123","events":["mention"],"channels":["#general","#support"]},"moderation":{"url":"https://n8n.example.com/webhook/moderation","token":"mod-token-456","events":["join","part","kick","mode"],"channels":["#general"]}}}

Enable and start:

sudo systemctl enable hanna
sudo systemctl start hanna
sudo systemctl status hanna

πŸ“Š Monitoring

Health Check Endpoint

The /health endpoint provides a simple way to monitor bot status:

# Check if bot is connected
curl -f https://bot.example.com/health || echo "Bot is down!"

Prometheus Metrics (Future Enhancement)

Consider extending the bot with Prometheus metrics for comprehensive monitoring.

πŸ›‘οΈ Security Considerations

  1. API Token: Use a strong, randomly generated token
  2. HTTPS: Always use HTTPS in production
  3. Firewall: Restrict API access to trusted networks
  4. File Permissions: Protect certificate files (0600 permissions)
  5. Regular Updates: Keep dependencies and certificates updated

πŸ“¦ n8n Node Package

Hanna includes a comprehensive n8n node package (n8n-nodes-hanna) that provides both action and trigger nodes for complete IRC automation.

Installation

# Install in your n8n instance
npm install n8n-nodes-hanna

# Or install globally
npm install -g n8n-nodes-hanna

Available Nodes

1. Hanna Bot (Action Node)

  • Send messages and notices to IRC channels
  • Join and part channels programmatically
  • Change bot nickname
  • Send raw IRC commands
  • Get bot status and connected channels

2. Hanna Bot Trigger (Trigger Node)

  • Webhook-based trigger for IRC events
  • Configurable event filtering (mention, join, part, etc.)
  • Channel and user filtering
  • Authentication token validation
  • Support for multiple simultaneous triggers

Node Configuration

Action Node Setup:

  1. Add "Hanna Bot" node to your workflow
  2. Configure credentials:
    • API URL: https://your-bot.example.com
    • API Token: Your bot's API token
  3. Select operation (Send Message, Join Channel, etc.)
  4. Configure target and message parameters

Trigger Node Setup:

  1. Add "Hanna Bot Trigger" node to your workflow
  2. Set authentication token (secure random string)
  3. Select IRC events to monitor
  4. Optional: Set channel/user filters
  5. Copy webhook URL to bot's TRIGGER_CONFIG

Example Workflows

See the Advanced Workflow Examples section above for complete workflow configurations using both trigger and action nodes.

πŸ§ͺ Testing

# Run all tests
go test -v

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests if applicable
  5. Run go test -v to ensure all tests pass
  6. Submit a pull request

πŸ“„ License

This project is licensed under the GPLv3 License - see the LICENSE file for details.

πŸ› Troubleshooting

Common Issues

Bot won't connect to IRC:

  • Check IRC_ADDR format (must include port)
  • Verify TLS settings match server requirements
  • Check firewall/network connectivity

API returns 401 Unauthorized:

  • Verify API_TOKEN is set and matches request
  • Check Authorization header format: Bearer <token>

HTTPS certificate errors:

  • Verify certificate and key file paths
  • Check file permissions
  • Ensure certificate is valid and not expired

Bot keeps reconnecting:

  • Check IRC server logs for connection issues
  • Verify SASL credentials if using authentication
  • Check for nick conflicts

Debug Mode

For detailed logging, you can modify the log level in the source code or redirect output:

./hanna 2>&1 | tee bot.log

Built with ❀️ in Go