Sign inSign up

bipy/pusher

By bipy

•Updated 9 months ago

Push Messages to Your Personal Telegram Bot

Image
0

1.5K

bipy/pusher repository overview

ā šŸ“® Pusher

A lightweight, secure Telegram message delivery API

Go Report Card Docker Pulls License: MIT Go Version

Features⁠ • Quick Start⁠ • API⁠ • Configuration⁠ • Examples⁠ • Contributing⁠


ā šŸŽÆ Overview

Pusher is a simple yet powerful HTTP API server that acts as a proxy for sending messages to Telegram. Built with Echo⁠ framework in Go, it simplifies message delivery by remembering your bot credentials and providing an easy-to-use REST interface.

⁠Why Pusher?
  • šŸš€ Simple Integration - Just HTTP GET/POST requests, no Telegram API complexity
  • šŸ”’ Secure - Optional authentication via secure key headers
  • šŸ“¦ Lightweight - Minimal Docker image, low resource usage
  • šŸŒ Proxy-Friendly - Works in regions where Telegram API is blocked
  • šŸ“± Smart Handling - Automatic message splitting and markdown escaping
  • šŸ’Ŗ Production-Ready - Graceful shutdown, health checks, and error handling

⁠✨ Features

FeatureDescription
šŸŽØ Multiple FormatsSupport for plain text and Telegram MarkdownV2
šŸ“Š Request CompressionAutomatic gzip compression for API calls
šŸ” Optional AuthSecure your endpoint with custom header authentication
šŸ“Ø Message SplittingAutomatically splits long messages into chunks
🌐 CORS EnabledWorks seamlessly with web applications
šŸ„ Health ChecksBuilt-in /pulse endpoint for monitoring
šŸ”— Link Preview ControlEnable/disable link previews per message
šŸ“ IP TrackingAutomatically includes sender IP in messages

ā šŸš€ Quick Start

Basic Setup:

docker run -d \
  --name pusher \
  -p 3333:3333 \
  -e TG_TOKEN=your_telegram_bot_token \
  -e CHAT_ID=your_chat_id \
  bipy/pusher:latest

With Security & Custom Port:

docker run -d \
  --name pusher \
  -p 8080:8080 \
  -e TG_TOKEN=your_telegram_bot_token \
  -e CHAT_ID=your_chat_id \
  -e SERVER_HOST=0.0.0.0 \
  -e SERVER_PORT=8080 \
  -e SECURE_KEY=your_secure_password \
  bipy/pusher:latest
⁠Docker Compose

Create a docker-compose.yml:

version: '3.8'

services:
  pusher:
    image: bipy/pusher:latest
    container_name: pusher
    restart: unless-stopped
    ports:
      - "3333:3333"
    environment:
      TG_TOKEN: "your_telegram_bot_token"
      CHAT_ID: "your_chat_id"
      SECURE_KEY: "your_secure_password"  # Optional
    # For production, use behind a reverse proxy with HTTPS

Then run:

docker-compose up -d
⁠Build from Source
# Clone the repository
git clone https://github.com/bipy/pusher.git
cd pusher

# Build the binary
go build -o pusher .

# Run with environment variables
export TG_TOKEN=your_telegram_bot_token
export CHAT_ID=your_chat_id
./pusher

ā āš™ļø Configuration

Configure Pusher using environment variables:

VariableTypeRequiredDefaultDescription
TG_TOKENstringāœ… Yes-Your Telegram bot token from @BotFather⁠
CHAT_IDintegerāœ… Yes-Target chat ID to receive messages
SERVER_HOSTstringNo0.0.0.0Server binding address
SERVER_PORTintegerNo3333Server listening port
SECURE_KEYstringNo-Optional authentication key
⁠Getting Your Credentials
  1. Get Bot Token:

    • Talk to @BotFather⁠ on Telegram
    • Create a new bot with /newbot
    • Copy the token provided
  2. Get Chat ID:

    • Send a message to your bot
    • Visit: https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates
    • Find your chat ID in the response

ā šŸ“” API Reference

⁠Endpoints
⁠POST / - Send Message (JSON)

Send a message using JSON payload.

Request Body:

{
  "text": "Your message here",
  "preview": false,
  "markdown": false
}

Parameters:

FieldTypeRequiredDefaultDescription
textstringāœ… Yes*-Message content
msgstringNo-Alternative to text (fallback)
previewbooleanNofalseEnable link preview
markdownbooleanNofalseEnable Telegram MarkdownV2 parsing

Authentication:

If SECURE_KEY is configured, provide authentication via:

  • Query parameter: POST /?key=your_secure_password
  • Header: Secure-Key: your_secure_password

Response:

{
  "code": 0,
  "msg": "OK",
  "resp": null
}
⁠GET / - Send Message (Query String)

Send a message using URL parameters.

Query Parameters:

ParameterTypeRequiredDescription
textstringāœ… Yes*Message content (URL encoded)
msgstringNoAlternative to text (fallback)
previewflagNoInclude this parameter to enable link preview
markdownflagNoInclude this parameter to enable markdown
keystringConditionalAuthentication key (required if SECURE_KEY is set)

Example:

# Without authentication
curl "http://localhost:3333/?text=Hello%20World"

# With authentication via query parameter
curl "http://localhost:3333/?text=Hello%20World&key=your_secure_password"
⁠GET /pulse - Health Check

Returns HTTP 204 No Content if the server is healthy.

Example:

curl -I http://localhost:3333/pulse
⁠Authentication

If SECURE_KEY is configured, include it in your requests using either method:

Method 1: Query Parameter (Easier - No Custom Headers Needed)

āš ļø Security Note: Query parameters are visible in URL logs, browser history, and may be leaked via referrer headers. Use this method only in trusted environments or for non-sensitive deployments. For production use with sensitive data, prefer the header method below.

Add key parameter to your URL:

# GET request
curl "http://localhost:3333/?text=Hello&key=your_secure_password"

# POST request
curl -X POST "http://localhost:3333/?key=your_secure_password" \
  -H "Content-Type: application/json" \
  -d '{"text": "Authenticated message"}'

Method 2: Custom Header (Recommended for Production)

šŸ”’ More Secure: Headers are not logged in URLs, don't appear in browser history, and aren't leaked via referrer headers. This is the recommended method for production deployments.

# With Secure-Key header
curl -X POST http://localhost:3333/ \
  -H "Content-Type: application/json" \
  -H "Secure-Key: your_secure_password" \
  -d '{"text": "Authenticated message"}'

> **Note:** When `SECURE_KEY` is not set (empty), authentication is disabled and all requests are allowed.

---

## šŸ’” Usage Examples

### Basic cURL Examples

**Simple Message:**

```bash
curl -X POST http://localhost:3333/ \
  -H "Content-Type: application/json" \
  -d '{"text": "Hello from Pusher!"}'

With Authentication (Query Parameter):

# GET with authentication
curl "http://localhost:3333/?text=Secure%20message&key=your_password"

# POST with authentication
curl -X POST "http://localhost:3333/?key=your_password" \
  -H "Content-Type: application/json" \
  -d '{"text": "Authenticated message"}'

With Link Preview:

curl "http://localhost:3333/?text=Check%20this%20out%20https://github.com&preview"

With Markdown:

curl -X POST http://localhost:3333/ \
  -H "Content-Type: application/json" \
  -d '{"text": "*Bold* and _italic_ text", "markdown": true}'
⁠HTTPie Examples

HTTPie⁠ makes it even simpler:

# Simple message
http POST localhost:3333 text="Hello World"

# With authentication (query parameter - easier)
http POST "localhost:3333?key=your_password" text="Secure message"

# With authentication (header method)
http POST localhost:3333 text="Secure message" Secure-Key:your_password

# With markdown
http POST localhost:3333 text="**Important** update" markdown:=true
⁠Python Example
import requests

def send_telegram_message(text, markdown=False, secure_key=None):
    # Method 1: Using query parameter (simpler)
    params = {}
    if secure_key:
        params['key'] = secure_key
    
    response = requests.post(
        'http://localhost:3333/',
        params=params,
        json={
            'text': text,
            'markdown': markdown,
            'preview': False
        }
    )
    return response.json()

# Alternatively, using header authentication:
def send_with_header(text, secure_key=None):
    headers = {}
    if secure_key:
        headers['Secure-Key'] = secure_key
    
    response = requests.post(
        'http://localhost:3333/',
        json={'text': text},
        headers=headers
    )
    return response.json()

# Usage
send_telegram_message("Deployment successful! šŸš€")
send_telegram_message("Secure message", secure_key="your_password")
⁠JavaScript/Node.js Example
// Method 1: Using query parameter (simpler, no custom headers)
async function sendTelegramMessage(text, options = {}) {
  const params = new URLSearchParams();
  if (options.secureKey) {
    params.append('key', options.secureKey);
  }
  
  const url = `http://localhost:3333/?${params}`;
  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      text,
      preview: options.preview || false,
      markdown: options.markdown || false
    })
  });
  return response.json();
}

// Method 2: Using header authentication
async function sendWithHeader(text, secureKey) {
  const headers = {
    'Content-Type': 'application/json'
  };
  if (secureKey) {
    headers['Secure-Key'] = secureKey;
  }
  
  const response = await fetch('http://localhost:3333/', {
    method: 'POST',
    headers,
    body: JSON.stringify({ text })
  });
  return response.json();
}

// Usage
await sendTelegramMessage('Build completed successfully!');
await sendTelegramMessage('Secure message', { secureKey: 'your_password' });
⁠Bash Script Example
#!/bin/bash

PUSHER_URL="http://localhost:3333/"
SECURE_KEY="your_secure_password"

# Method 1: Using query parameter (simpler)
function notify_simple() {
    local message="$1"
    curl -s -X POST "${PUSHER_URL}?key=${SECURE_KEY}" \
        -H "Content-Type: application/json" \
        -d "{\"text\": \"$message\"}"
}

# Method 2: Using header
function notify_header() {
    local message="$1"
    curl -s -X POST "$PUSHER_URL" \
        -H "Content-Type: application/json" \
        -H "Secure-Key: $SECURE_KEY" \
        -d "{\"text\": \"$message\"}"
}

# Usage
notify_simple "Backup completed at $(date)"
⁠Integration with Uptime Kuma

Pusher supports Uptime Kuma⁠ webhook notifications out of the box!

  1. In Uptime Kuma, add a new notification
  2. Select "Webhook"
  3. Use your Pusher URL: http://your-server:3333/
  4. Uptime Kuma will automatically send status updates to your Telegram

ā šŸ—ļø Architecture

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”         ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”         ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│   Client    │         │   Pusher    │         │  Telegram API    │
│             │         │             │         │                  │
│  HTTP GET   ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā–¶ā”‚  Echo Web   ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā–¶ā”‚  /sendMessage    │
│  HTTP POST  │         │  Framework  │         │                  │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜         ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜         ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
                               │
                               ā”œā”€ Authentication (optional)
                               ā”œā”€ Markdown Escaping
                               ā”œā”€ Message Splitting
                               ā”œā”€ Gzip Compression
                               └─ Error Handling
⁠Key Components
  • Echo Framework: High-performance HTTP router
  • Middleware: CORS, logging, recovery, authentication
  • Message Processing: Automatic markdown escaping and splitting
  • Compression: Gzip compression for Telegram API requests
  • Health Checks: /pulse endpoint for monitoring

ā šŸ”’ Security Best Practices

  1. Use HTTPS in Production

    • Always deploy behind a reverse proxy (nginx, Caddy, Traefik)
    • Enable HTTPS to protect your SECURE_KEY in transit
  2. Choose Authentication Method Wisely

    • Header-based (Recommended): Use Secure-Key header in production environments
      • Not logged in URLs
      • Not visible in browser history
      • Not leaked via referrer headers
    • Query parameter: Use key parameter only in trusted environments
      • Convenient for webhooks and simple integrations
      • āš ļø WARNING: Exposed in server logs, browser history, and referrer headers
      • Best for internal tools or non-production deployments
  3. Strong SECURE_KEY

    • Use a randomly generated, long password
    • Store in environment variables or secrets manager
    • Rotate keys periodically
  4. Network Security

    • Don't expose Pusher directly to the internet
    • Use firewall rules to restrict access
    • Consider VPN or private network deployment
  5. Rate Limiting

    • Implement rate limiting at the reverse proxy level
    • Monitor for unusual activity

Example nginx configuration:

server {
    listen 443 ssl http2;
    server_name pusher.example.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    location / {
        proxy_pass http://localhost:3333;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        
        # Rate limiting
        limit_req zone=pusher_limit burst=10 nodelay;
    }
}

ā šŸ› Troubleshooting

⁠Common Issues

Problem: "TG_TOKEN environment variable is required"

  • Solution: Ensure TG_TOKEN is set correctly in your environment or Docker configuration

Problem: "invalid CHAT_ID"

  • Solution: CHAT_ID must be a valid integer. Remove quotes in Docker compose files

Problem: Messages not received

  • Solution:
    • Verify bot token is correct
    • Check if chat ID is correct
    • Ensure your bot has been started (send /start to it)
    • Check logs for error messages

Problem: 502 Bad Gateway errors

  • Solution: Telegram API might be blocked or unreachable from your server location

ā šŸ“Š Monitoring

⁠Health Check

Use the /pulse endpoint for monitoring:

# Check if service is running
curl -f http://localhost:3333/pulse || echo "Service down"
⁠Docker Health Check

Add to your docker-compose.yml:

services:
  pusher:
    image: bipy/pusher:latest
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3333/pulse"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 5s
⁠Logging

Pusher uses Echo's built-in logger. To view logs:

# Docker logs
docker logs -f pusher

# Follow logs with timestamps
docker logs -f --timestamps pusher

ā šŸ¤ Contributing

Contributions are welcome! Here's how you can help:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request
⁠Development Setup
# Clone your fork
git clone https://github.com/yourusername/pusher.git
cd pusher

# Install dependencies
go mod download

# Run locally
export TG_TOKEN=your_token
export CHAT_ID=your_chat_id
go run main.go
⁠Code Style
  • Follow Go best practices and conventions
  • Run gofmt before committing: gofmt -w .
  • Run go vet to check for issues: go vet ./...

ā šŸ“ Use Cases

  • šŸ“¦ CI/CD Notifications: Get notified about build status, deployments
  • šŸ”” Server Monitoring: Alert on server issues, resource usage
  • šŸ“Š Application Alerts: Runtime errors, important events
  • šŸ” Security Notifications: Failed login attempts, suspicious activity
  • šŸ“ˆ Business Metrics: Daily reports, sales notifications
  • šŸ¤– Automation: Integrate with scripts, cron jobs, webhooks

ā šŸ™ Acknowledgments


ā šŸ“„ License

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

MIT License

Copyright (c) 2021 bipy

ā šŸ“ž Support


Made with ā¤ļø using Go

⬆ Back to Top⁠

Tag summary

Content type

Image

Digest

sha256:599a30f99…

Size

6.9 MB

Last updated

9 months ago

docker pull bipy/pusher