Skip to content

nielsbosma/SlackServer

Repository files navigation

SlackServer

A flexible Slack bot framework that allows you to create multiple bots powered by local CLI scripts (PowerShell, C#, Python, etc.). Bots communicate with Slack through a simple JSON protocol, enabling rich interactions without requiring scripts to implement the Slack API directly.

🎯 What is SlackServer?

SlackServer acts as a bridge between Slack and your local scripts. Instead of writing complex Slack bot logic, you write simple scripts that output JSON commands, and SlackServer handles all the Slack API interactions.

πŸš€ NEW HERE? Start with the Quick Start Guide (15 minutes) to get your @mention bot running!

Key Features

  • βœ… Multi-Bot Support: Configure multiple bots in a single YAML file
  • βœ… Language Agnostic: Write bots in PowerShell, C#, Python, Bash, or any language
  • βœ… Simple JSON Protocol: Output JSON lines to control Slack (messages, reactions, blocks, etc.)
  • βœ… Rich Formatting: Full support for Slack Block Kit, reactions, threads, ephemeral messages
  • βœ… Pattern Matching: Use regex to match specific messages including @mentions
  • βœ… Channel & DM Support: Bots can respond in channels or direct messages
  • βœ… Windows Service Ready: Deploy as a Windows service or systemd service

πŸ“‹ Complete Setup Guide: @Mention Bot in Channel

This guide will walk you through creating a Slack bot that responds when @mentioned in a channel.

Step 1: Create a Slack App

  1. Go to Slack API: Visit https://api.slack.com/apps
  2. Click "Create New App"
  3. Choose "From scratch"
  4. Enter App Name: e.g., "MyBot" (this will be your bot's @mention name)
  5. Select Workspace: Choose your workspace
  6. Click "Create App"

Step 2: Enable Socket Mode

Socket Mode allows your bot to receive events without needing a public URL.

  1. Go to "Socket Mode" in the left sidebar
  2. Toggle "Enable Socket Mode" to ON
  3. Name your token: e.g., "SlackServer Connection"
  4. Click "Generate"
  5. Copy the App-Level Token (starts with xapp-) - Save this! ⚠️
  6. Click "Done"

Step 3: Add Bot Scopes (Permissions)

  1. Go to "OAuth & Permissions" in the left sidebar

  2. Scroll to "Scopes" β†’ "Bot Token Scopes"

  3. Click "Add an OAuth Scope" and add these scopes:

    Required Scopes:

    • app_mentions:read - Read messages that @mention your bot
    • chat:write - Send messages
    • channels:history - Read messages in channels
    • im:history - Read messages in DMs
    • users:read - Get user information

    Optional Scopes:

    • reactions:write - Add/remove emoji reactions
    • files:write - Upload files

Step 4: Subscribe to Events

  1. Go to "Event Subscriptions" in the left sidebar

  2. Toggle "Enable Events" to ON

  3. Expand "Subscribe to bot events"

  4. Click "Add Bot User Event" and add:

    • app_mention - When someone @mentions your bot
    • message.channels - Messages in channels (if you want to respond without @mention)
    • message.im - Direct messages to your bot
  5. Click "Save Changes"

Step 5: Install Bot to Workspace

  1. Go to "Install App" in the left sidebar
  2. Click "Install to Workspace"
  3. Review permissions and click "Allow"
  4. Copy the "Bot User OAuth Token" (starts with xoxb-) - Save this! ⚠️

Step 6: Invite Bot to Channel

  1. Open Slack and go to the channel where you want the bot
  2. Type: /invite @MyBot (replace with your bot's name)
  3. Press Enter
  4. Your bot should now appear in the channel

Step 7: Get Channel ID

You'll need the channel ID for configuration:

  1. Right-click the channel name in Slack
  2. Select "View channel details"
  3. Scroll down - Channel ID is at the bottom (starts with C, e.g., C01234ABCDE)
  4. Copy the Channel ID

Step 8: Configure SlackServer

  1. Copy config.example.yaml to config.yaml:

    cp config.example.yaml config.yaml
  2. Edit config.yaml with your tokens and channel:

slack:
  appToken: "xapp-1-YOUR-APP-LEVEL-TOKEN"    # From Step 2
  botToken: "xoxb-YOUR-BOT-USER-TOKEN"       # From Step 5
  logLevel: "Information"

bots:
  # Bot that responds to @mentions
  - name: "Question Bot"
    description: "Answers questions when @mentioned"
    type: channel
    channelId: "C01234ABCDE"              # Your channel ID from Step 7
    messagePattern: "<@\\w+>\\s+.*"       # Matches "@bot_name question"
    script: "pwsh ./scripts/question-bot.ps1"
    timeout: 30

Pattern Explanation:

  • <@\\w+> - Matches the @mention (Slack sends it as <@U01234>)
  • \\s+ - Matches whitespace
  • .* - Matches the rest of the message (the question)

Step 9: Create Your Bot Script

Create scripts/question-bot.ps1:

#!/usr/bin/env pwsh
# Question bot - responds to @mentions

param(
    [string]$Message = $env:TRIGGER_MESSAGE,
    [string]$Channel = $env:TRIGGER_CHANNEL,
    [string]$Timestamp = $env:TRIGGER_TS,
    [string]$User = $env:TRIGGER_USER
)

function Send-SlackAction {
    param([hashtable]$Action)
    $json = $Action | ConvertTo-Json -Compress -Depth 10
    Write-Output $json
}

# Extract the question (remove the @mention part)
$question = $Message -replace '<@\w+>\s*', ''

# Post a thinking message
Send-SlackAction @{
    action = "post_message"
    channel = $Channel
    thread_ts = $Timestamp
    text = "πŸ€” Let me think about that..."
    store_as = "thinking_msg"
}

Start-Sleep -Milliseconds 500

# Process the question (call your CLI tool here)
# Example: calling a simple echo, but you could call any CLI
$answer = "You asked: '$question'"
$answer += "`n`nThis is where you would call your CLI tool!"
$answer += "`nExample: `python ./my-cli-tool.py `"$question`"`"

# Update with the answer
Send-SlackAction @{
    action = "update_message"
    channel = $Channel
    message_ref = "thinking_msg"
    text = "βœ… *Answer:*`n$answer"
}

# You could also post a rich formatted response
Send-SlackAction @{
    action = "post_blocks"
    channel = $Channel
    thread_ts = $Timestamp
    text = "Response details"
    blocks = @(
        @{
            type = "section"
            text = @{
                type = "mrkdwn"
                text = "*Your Question:*`n> $question"
            }
        }
        @{
            type = "divider"
        }
        @{
            type = "section"
            text = @{
                type = "mrkdwn"
                text = "*Answer:*`n$answer"
            }
        }
    )
}

exit 0

Make script executable (Linux/Mac):

chmod +x scripts/question-bot.ps1

Step 10: Build and Run SlackServer

# Build the C# test bot (optional, but good to verify)
cd TestBotCli
dotnet build -c Release
cd ..

# Run SlackServer
dotnet run

You should see:

info: SlackServer.Services.SlackListenerService[0]
      Loaded 1 bot(s) from config.yaml
info: SlackServer.Services.SlackListenerService[0]
        - Question Bot: channel | <@\w+>\s+.* | pwsh ./scripts/question-bot.ps1
info: SlackServer.Services.SlackListenerService[0]
      Connecting to Slack via Socket Mode...
info: SlackServer.Services.SlackListenerService[0]
      βœ… Connected to Slack! Ready to process bot commands.

Step 11: Test Your Bot!

  1. Go to your Slack channel
  2. Type: @MyBot what is the weather?
  3. Press Enter

Your bot should:

  • Post "πŸ€” Let me think about that..."
  • Update it to show the answer
  • Post a formatted response in the thread

πŸ”§ Advanced Configuration

Respond to Any Message (No @mention Required)

bots:
  - name: "Auto Responder"
    type: channel
    channelId: "C01234ABCDE"
    messagePattern: ".*help.*"    # Matches any message containing "help"
    script: "pwsh ./scripts/help-bot.ps1"
    timeout: 15

Respond to Direct Messages

bots:
  - name: "DM Bot"
    type: bot_dm                  # Only responds to DMs
    messagePattern: ".*"          # Matches any DM
    script: "python ./bots/dm-handler.py"
    timeout: 30

Multiple Patterns (Multiple Bots)

bots:
  - name: "Help Bot"
    type: channel
    channelId: "C01234ABCDE"
    messagePattern: "^help"
    script: "pwsh ./scripts/help.ps1"
    timeout: 10

  - name: "Deploy Bot"
    type: channel
    channelId: "C01234ABCDE"
    messagePattern: "^deploy (staging|production)"
    script: "pwsh ./scripts/deploy.ps1"
    timeout: 120

  - name: "Question Bot"
    type: channel
    channelId: "C01234ABCDE"
    messagePattern: "<@\\w+>\\s+.*"
    script: "pwsh ./scripts/question-bot.ps1"
    timeout: 30

Call External CLI Tools

# Example: Call Python CLI tool
$question = $Message -replace '<@\w+>\s*', ''
$result = python ./my-tool.py $question | Out-String

Send-SlackAction @{
    action = "post_message"
    channel = $Channel
    thread_ts = $Timestamp
    text = $result
}
# Example: Call C# CLI tool
$answer = dotnet run --project ./MyCliTool -- $question | Out-String

Send-SlackAction @{
    action = "post_message"
    channel = $Channel
    thread_ts = $Timestamp
    text = "βœ… Result:`n``````$answer``````"
}

πŸ“– JSON Protocol

Bots communicate by outputting line-delimited JSON (one JSON object per line) to stdout.

Environment Variables Available to Bots

TRIGGER_MESSAGE     # The full message text (includes @mention)
TRIGGER_CHANNEL     # Channel ID (e.g., C01234ABCDE)
TRIGGER_TS          # Message timestamp (unique ID)
TRIGGER_USER        # User ID who sent the message (e.g., U01234ABCDE)
TRIGGER_USER_NAME   # Username (display name)
BOT_NAME            # Name of the bot from config

Available Actions

Post a Message

{"action": "post_message", "channel": "$TRIGGER_CHANNEL", "text": "Hello!"}

Post in Thread

{"action": "post_message", "channel": "$TRIGGER_CHANNEL", "thread_ts": "$TRIGGER_TS", "text": "Reply"}

Update a Message

{"action": "post_message", "channel": "$CHANNEL", "text": "Processing...", "store_as": "msg1"}
{"action": "update_message", "channel": "$CHANNEL", "message_ref": "msg1", "text": "Done!"}

Post with Rich Blocks

{
  "action": "post_blocks",
  "channel": "$TRIGGER_CHANNEL",
  "thread_ts": "$TRIGGER_TS",
  "text": "Fallback text",
  "blocks": [
    {
      "type": "header",
      "text": {"type": "plain_text", "text": "πŸ“Š Report"}
    },
    {
      "type": "section",
      "text": {"type": "mrkdwn", "text": "*Status:* βœ… Success"}
    }
  ]
}

Delete a Message

{"action": "delete_message", "channel": "$CHANNEL", "message_ref": "msg1"}

See DESIGN.md for complete protocol documentation.


πŸ€– Example Bots Included

PowerShell Test Bot

Location: scripts/test-bot.ps1

Demonstrates all response types:

  • Simple text messages
  • Thread replies
  • Rich Block Kit formatting
  • Message updates (progress indicators)

Trigger: Send test ps in configured channel

C# Test Bot

Location: TestBotCli/

Demonstrates:

  • Message analysis (length, word count)
  • JSON code snippets in messages
  • Progress indicators with updates
  • Rich formatted blocks

Trigger: Send test cs in configured channel


πŸš€ Deployment

As Windows Service

# Publish the app
dotnet publish -c Release -o C:\SlackServer

# Copy config.yaml to publish directory
copy config.yaml C:\SlackServer\

# Create Windows service
sc.exe create SlackServer binPath="C:\SlackServer\SlackServer.exe" start=auto
sc.exe start SlackServer

As Linux Service (systemd)

# Publish
dotnet publish -c Release -o /opt/slackserver

# Copy config
cp config.yaml /opt/slackserver/

# Create service file: /etc/systemd/system/slackserver.service
[Unit]
Description=SlackServer Bot Framework
After=network.target

[Service]
Type=notify
WorkingDirectory=/opt/slackserver
ExecStart=/usr/bin/dotnet /opt/slackserver/SlackServer.dll
Restart=always
User=slackserver

[Install]
WantedBy=multi-user.target

# Enable and start
sudo systemctl daemon-reload
sudo systemctl enable slackserver
sudo systemctl start slackserver

πŸ› Troubleshooting

See TROUBLESHOOTING.md for detailed solutions to common issues.

Quick Fixes

Bot doesn't respond:

  • Check logs for "Bot matched message"
  • Verify channel ID in config
  • Ensure bot is invited to channel: /invite @YourBot
  • Test pattern at https://regex101.com/

"Permission denied" errors:

  • Go to Slack App β†’ OAuth & Permissions
  • Verify all required scopes are added
  • Click "Reinstall App" after adding scopes

Bot not connecting:

  • Verify Socket Mode is enabled
  • Check tokens start with xapp- and xoxb-
  • Check logs for connection errors

Script not executing:

  • Verify script path is correct
  • Make script executable: chmod +x (Linux/Mac)
  • Test manually with environment variables

More help: See TROUBLESHOOTING.md


πŸ“š Documentation

Getting Started

  • πŸš€ QUICKSTART.md - 15-minute setup guide for @mention bots
  • βœ… TODO.md - Setup checklist to track your progress
  • πŸ“– README.md - This file - complete user guide

Reference

  • πŸ—οΈ ARCHITECTURE.md - System architecture, diagrams, and component details
  • πŸ“ DESIGN.md - JSON protocol specification and implementation plan
  • πŸ“Š STATUS.md - Current implementation status and roadmap
  • πŸ“‹ SUMMARY.md - Complete implementation summary
  • βš™οΈ config.example.yaml - Configuration file examples

Support

Examples

  • πŸ’¬ scripts/question-bot.ps1 - @Mention bot that integrates with CLI tools
  • πŸ§ͺ scripts/test-bot.ps1 - PowerShell bot demonstrating all features
  • πŸ”§ TestBotCli/ - C# bot with message analysis

External Resources


πŸ“„ License

MIT License - See LICENSE file for details

🀝 Contributing

Contributions welcome! Please read the design document first to understand the architecture.


πŸ’‘ Quick Examples

Simple Echo Bot

#!/usr/bin/env pwsh
$message = $env:TRIGGER_MESSAGE
$channel = $env:TRIGGER_CHANNEL
$ts = $env:TRIGGER_TS

@{
    action = "post_message"
    channel = $channel
    thread_ts = $ts
    text = "You said: $message"
} | ConvertTo-Json -Compress | Write-Output

Python Bot

#!/usr/bin/env python3
import os
import json

channel = os.getenv('TRIGGER_CHANNEL')
ts = os.getenv('TRIGGER_TS')
message = os.getenv('TRIGGER_MESSAGE')

# Post response
print(json.dumps({
    'action': 'post_message',
    'channel': channel,
    'thread_ts': ts,
    'text': f'Python bot received: {message}'
}))

C# Bot

var channel = Environment.GetEnvironmentVariable("TRIGGER_CHANNEL")!;
var ts = Environment.GetEnvironmentVariable("TRIGGER_TS")!;
var message = Environment.GetEnvironmentVariable("TRIGGER_MESSAGE")!;

Console.WriteLine(JsonSerializer.Serialize(new {
    action = "post_message",
    channel = channel,
    thread_ts = ts,
    text = $"C# bot says: {message}"
}, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower }));

Ready to build your bot? Follow the setup guide above and start creating! πŸš€

About

A flexible Slack bot framework that bridges Slack and local CLI scripts through a JSON protocol. Create bots in any language!

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors