#!/bin/bash # Beeper Bridge "Green Field" Setup Script # This script sets up a Mautrix bridge for Beeper from scratch. # It overwrites existing configurations to ensure a clean state. BRIDGE_SERVICE=$1 if [ -z "$BRIDGE_SERVICE" ]; then echo "Usage: ./setup_beeper_bridge.sh " echo "Example: ./setup_beeper_bridge.sh telegram" exit 1 fi DATA_DIR="data/$BRIDGE_SERVICE" CONFIG_FILE="$DATA_DIR/config.yaml" REG_FILE="$DATA_DIR/registration.yaml" echo "==================================================" echo " Beeper Bridge Setup: $BRIDGE_SERVICE" echo "==================================================" echo "Warning: This will OVERWRITE contents in $DATA_DIR" read -p "Continue? (y/N) " confirm if [[ $confirm != [yY] && $confirm != [yY][eE][sS] ]]; then exit 0 fi mkdir -p "$DATA_DIR" # --- Step 1: Gather Information --- echo "" echo "--- 1. Beeper Registration ---" # Try auto-discovery via bbctl if command -v bbctl &> /dev/null; then echo "Found 'bbctl'. Attempting to fetch registration automatically..." # Run bbctl and capture output. We need to filter out the "You already have..." text. # Usually the YAML starts with "id:". We try to grep from "id:" down. BBCTL_OUT=$(bbctl register "sh-$BRIDGE_SERVICE" 2>&1) if [ $? -eq 0 ]; then # Extract YAML: Find line starting with "id:" and everything after YAML_CONTENT=$(echo "$BBCTL_OUT" | sed -n '/^id:/,$p') if [ ! -z "$YAML_CONTENT" ]; then echo "$YAML_CONTENT" > "$REG_FILE" echo "Successfully saved registration to $REG_FILE" # Now we need to parse values from this file to populate config variables # We use grep/sed to extract vars to avoid python dependencies echo "Extracting tokens..." # Helper function to extract value by key get_yaml_val() { grep "^$1:" "$REG_FILE" | sed 's/^[^:]*: *//' | tr -d '\r' } REG_ID=$(get_yaml_val "id") AS_TOKEN=$(get_yaml_val "as_token") HS_TOKEN=$(get_yaml_val "hs_token") BOT_USERNAME=$(get_yaml_val "sender_localpart") if [ -n "$REG_ID" ]; then echo " -> ID: $REG_ID" fi else echo "Could not parse YAML from bbctl output. Falling back to manual input." fi else echo "bbctl failed. Falling back to manual input." fi else echo "bbctl not found in PATH. Falling back to manual input." fi # Fallback prompts if variables are still empty if [ -z "$REG_ID" ]; then echo "Manual Input Required:" read -p "ID (e.g., 99ab27...): " REG_ID fi while [[ -z "$REG_ID" ]]; do read -p "ID cannot be empty: " REG_ID; done if [ -z "$AS_TOKEN" ]; then read -p "AS Token (e.g., Agqb...): " AS_TOKEN fi while [[ -z "$AS_TOKEN" ]]; do read -p "AS Token cannot be empty: " AS_TOKEN; done if [ -z "$HS_TOKEN" ]; then read -p "HS Token (e.g., bR5t...): " HS_TOKEN fi while [[ -z "$HS_TOKEN" ]]; do read -p "HS Token cannot be empty: " HS_TOKEN; done # Default Beeper values (can be overridden but we default to what we saw in logs) DEFAULT_HS_URL="https://matrix.beeper.com/_hungryserv/inswe" # Try to extract HS URL from bbctl output if possible, otherwise default read -p "Homeserver URL [$DEFAULT_HS_URL]: " HS_URL HS_URL=${HS_URL:-$DEFAULT_HS_URL} DEFAULT_DOMAIN="beeper.local" read -p "Homeserver Domain [$DEFAULT_DOMAIN]: " HS_DOMAIN HS_DOMAIN=${HS_DOMAIN:-$DEFAULT_DOMAIN} DEFAULT_USER="@inswe:beeper.com" read -p "Your Admin User ID [$DEFAULT_USER]: " ADMIN_USER ADMIN_USER=${ADMIN_USER:-$DEFAULT_USER} if [ -z "$BOT_USERNAME" ]; then DEFAULT_BOT="sh-${BRIDGE_SERVICE}bot" read -p "Bot Username (Localpart) [$DEFAULT_BOT]: " BOT_USERNAME BOT_USERNAME=${BOT_USERNAME:-$DEFAULT_BOT} fi echo "" echo "--- 2. Bridge Specifics ($BRIDGE_SERVICE) ---" if [ "$BRIDGE_SERVICE" == "telegram" ]; then read -p "Telegram API ID: " API_ID read -p "Telegram API Hash: " API_HASH fi # --- Step 2: Generate registration.yaml --- echo "" echo "Generating registration.yaml..." cat < "$REG_FILE" id: $REG_ID url: websocket as_token: $AS_TOKEN hs_token: $HS_TOKEN sender_localpart: $BOT_USERNAME namespaces: users: - regex: ' @${BOT_USERNAME}_.+:${HS_DOMAIN//.\/\\./}' exclusive: true receive_ephemeral: true EOF # --- Step 3: Generate config.yaml (Hardcoded Template) --- echo "Generating config.yaml..." # Escape domain for regex in config if needed, but standard string is fine for config # We use a minimal but complete config optimized for Beeper cat < "$CONFIG_FILE" homeserver: address: $HS_URL domain: $HS_DOMAIN verify_ssl: true software: hungry http_retry_count: 4 async_media: true # Force websocket usage (Beeper requirement) websocket: true appservice: address: http://localhost:29317 id: $REG_ID bot_username: $BOT_USERNAME as_token: $AS_TOKEN hs_token: $HS_TOKEN database: sqlite:////data/bridge.db # Community advice for Beeper: async_transactions: true bridge: username_template: ${BRIDGE_SERVICE}_{userid} displayname_template: "{displayname} ($BRIDGE_SERVICE)" permissions: "*": relay "$HS_DOMAIN": user "beeper.com": user "$ADMIN_USER": admin relay: enabled: true admin_only: false logging: version: 1 formatters: colored: format: "[%(asctime)s] [%(levelname)s@%(name)s] %(message)s" datefmt: "%b %d %H:%M:%S" handlers: console: class: logging.StreamHandler formatter: colored stream: ext://sys.stdout root: level: INFO handlers: [console] telegram: api_id: $API_ID api_hash: $API_HASH device_info: device_model: "Beeper Bridge" system_version: "Docker" app_version: "0.1" EOF # --- Step 4: Fix Docker Compose (Environment Override) --- # We ensure MAUTRIX_TELEGRAM_HOMESERVER_WEBSOCKET is set in docker-compose.yml # This is a bit hacky but ensures we win against any config parsing issues. COMPOSE_FILE="docker-compose.yml" if grep -q "MAUTRIX_TELEGRAM_HOMESERVER_WEBSOCKET" "$COMPOSE_FILE"; then echo "Env var already present in docker-compose.yml" else echo "Adding Websocket Environment Variable to docker-compose.yml..." # We use sed to insert environment block if missing, or append to it. # Simplified: We just warn the user or append it if we find the service. # To be safe/lazy: We rely on the config.yaml 'websocket: true' first. # But let's append it to the file via sed for the telegram service specifically. # Using a temporary file to construct the patch sed -i '/container_name: beeper-telegram/a \ environment:\n - MAUTRIX_TELEGRAM_HOMESERVER_WEBSOCKET=true' "$COMPOSE_FILE" fi # --- Step 5: Start --- echo "" echo "Setup Complete." echo "Starting container..." docker compose up -d $BRIDGE_SERVICE --force-recreate echo "" echo "Logs:" docker compose logs -f $BRIDGE_SERVICE