From f73eea0194466f52b27f8bb9fca9159f90e2e7da Mon Sep 17 00:00:00 2001 From: PCBZ Date: Sun, 12 Apr 2026 22:19:45 -0700 Subject: [PATCH] add Line Support. TODO: set domain --- .env.example | 5 +++ README.md | 7 ++- terraform/digitalOcean/.envrc | 2 + terraform/digitalOcean/bootstrap.sh | 14 +++++- terraform/digitalOcean/main.tf | 45 ++++++++++++++++--- .../digitalOcean/terraform.tfvars.example | 5 +++ terraform/digitalOcean/variables.tf | 17 +++++++ 7 files changed, 85 insertions(+), 10 deletions(-) diff --git a/.env.example b/.env.example index d488560..2c9982c 100644 --- a/.env.example +++ b/.env.example @@ -7,6 +7,11 @@ OPENROUTER_API_KEY=sk-or-v1-your-key-here # Telegram Bot Token (from @BotFather) TELEGRAM_BOT_TOKEN=1234567890:your-token-here +# LINE Messaging API credentials (optional) +# Channel Access Token + Channel Secret from LINE Developers Console +LINE_CHANNEL_ACCESS_TOKEN= +LINE_CHANNEL_SECRET= + # Gateway Token (set any strong password) OPENCLAW_GATEWAY_TOKEN=your-secret-gateway-token diff --git a/README.md b/README.md index 01fca3d..e250def 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,14 @@ [![OpenRouter](https://img.shields.io/badge/OpenRouter-Free%20Tier-ff6b35?logoColor=white)](https://openrouter.ai) [![OpenClaw](https://img.shields.io/badge/OpenClaw-2026-00e5cc?logoColor=white)](https://openclaw.bot) [![Telegram](https://img.shields.io/badge/Telegram-Bot-26a5e4?logo=telegram&logoColor=white)](https://telegram.org) +[![LINE](https://img.shields.io/badge/LINE-Bot-00c300?logo=line&logoColor=white)](https://line.me) -One-command deployment of an [OpenClaw](https://openclaw.bot) AI agent as a Telegram bot on DigitalOcean. After `terraform apply`, the bot is fully operational with no manual SSH steps required. +One-command deployment of an [OpenClaw](https://openclaw.bot) AI agent on DigitalOcean with Telegram support and optional LINE support. After `terraform apply`, the bot is fully operational with no manual SSH steps required. ## Features - Telegram bot with DM and group chat support +- Optional LINE Messaging API channel - Web search via Brave Search (falls back to DuckDuckGo) - 8 switchable free LLM models via `/model ` - Secrets managed via `.env` — never committed @@ -26,6 +28,7 @@ One-command deployment of an [OpenClaw](https://openclaw.bot) AI agent as a Tele - DigitalOcean account + API token - OpenRouter API key - Telegram bot token (from [@BotFather](https://t.me/BotFather)) +- LINE channel access token + channel secret (optional) ## Setup @@ -41,6 +44,8 @@ Edit `.env` and fill in your values: |---|---| | `OPENROUTER_API_KEY` | From [openrouter.ai/keys](https://openrouter.ai/keys) | | `TELEGRAM_BOT_TOKEN` | From [@BotFather](https://t.me/BotFather) | +| `LINE_CHANNEL_ACCESS_TOKEN` | From LINE Developers Console (optional, enables LINE channel) | +| `LINE_CHANNEL_SECRET` | From LINE Developers Console (optional, enables LINE channel) | | `OPENCLAW_GATEWAY_TOKEN` | Any strong random string | | `BRAVE_API_KEY` | From [api.search.brave.com](https://api.search.brave.com) — optional, falls back to DuckDuckGo | | `TELEGRAM_OWNER_ID` | Your Telegram user ID from [@userinfobot](https://t.me/userinfobot) — grants `/model` and other privileged commands | diff --git a/terraform/digitalOcean/.envrc b/terraform/digitalOcean/.envrc index 9d352ad..67b5812 100644 --- a/terraform/digitalOcean/.envrc +++ b/terraform/digitalOcean/.envrc @@ -5,6 +5,8 @@ dotenv ../../.env export TF_VAR_openrouter_api_key="$OPENROUTER_API_KEY" export TF_VAR_telegram_bot_token="$TELEGRAM_BOT_TOKEN" +export TF_VAR_line_channel_access_token="${LINE_CHANNEL_ACCESS_TOKEN:-}" +export TF_VAR_line_channel_secret="${LINE_CHANNEL_SECRET:-}" export TF_VAR_openclaw_gateway_token="$OPENCLAW_GATEWAY_TOKEN" export TF_VAR_brave_api_key="${BRAVE_API_KEY:-}" export TF_VAR_telegram_owner_id="${TELEGRAM_OWNER_ID:-}" diff --git a/terraform/digitalOcean/bootstrap.sh b/terraform/digitalOcean/bootstrap.sh index e5613b9..e0279de 100644 --- a/terraform/digitalOcean/bootstrap.sh +++ b/terraform/digitalOcean/bootstrap.sh @@ -86,11 +86,12 @@ cat > /root/.openclaw/openclaw.json << JSONEOF "plugins": { "load": { "paths": [ - "/usr/lib/node_modules/openclaw/dist/extensions/telegram" + "/usr/lib/node_modules/openclaw/dist/extensions/telegram"${line_channel_access_token != "" && line_channel_secret != "" ? ",\n \"/usr/lib/node_modules/openclaw/dist/extensions/line\"" : ""} ] }, "entries": { "telegram": { "enabled": true }, + ${line_channel_access_token != "" && line_channel_secret != "" ? "\"line\": { \"enabled\": true }," : ""} "openrouter": { "enabled": true }, "brave": { "enabled": true, @@ -112,7 +113,7 @@ cat > /root/.openclaw/openclaw.json << JSONEOF "groupPolicy": "open"${telegram_owner_id != "" ? ",\n \"allowFrom\": [\"${telegram_owner_id}\"]" : ""} } } - } + }${line_channel_access_token != "" && line_channel_secret != "" ? ",\n \"line\": {\n \"enabled\": true,\n \"accounts\": {\n \"default\": {\n \"channelAccessToken\": \"${line_channel_access_token}\",\n \"channelSecret\": \"${line_channel_secret}\"\n }\n }\n }" : ""} } } JSONEOF @@ -124,6 +125,8 @@ write_config cat > /root/.openclaw/.env << ENVEOF OPENROUTER_API_KEY=${openrouter_api_key} TELEGRAM_BOT_TOKEN=${telegram_bot_token} +LINE_CHANNEL_ACCESS_TOKEN=${line_channel_access_token} +LINE_CHANNEL_SECRET=${line_channel_secret} OPENCLAW_GATEWAY_TOKEN=${openclaw_gateway_token} BRAVE_API_KEY=${brave_api_key} OPENCLAW_ONBOARD_NON_INTERACTIVE=1 @@ -132,12 +135,19 @@ ENVEOF # ── 8. Export env vars for subsequent commands ─────────────── export OPENROUTER_API_KEY=${openrouter_api_key} export TELEGRAM_BOT_TOKEN=${telegram_bot_token} +export LINE_CHANNEL_ACCESS_TOKEN=${line_channel_access_token} +export LINE_CHANNEL_SECRET=${line_channel_secret} export OPENCLAW_GATEWAY_TOKEN=${openclaw_gateway_token} export BRAVE_API_KEY=${brave_api_key} # ── 9. Install Telegram plugin ─────────────────────────────── openclaw plugins install @openclaw/telegram +# Install LINE plugin when LINE credentials are configured. +if [ -n "${line_channel_access_token}" ] && [ -n "${line_channel_secret}" ]; then + openclaw plugins install @openclaw/line || echo "LINE plugin install skipped (package unavailable in this release)." +fi + # ── 10. Auto-fix common config issues ──────────────────────── openclaw doctor --fix || true diff --git a/terraform/digitalOcean/main.tf b/terraform/digitalOcean/main.tf index 8d25895..c61cfb7 100644 --- a/terraform/digitalOcean/main.tf +++ b/terraform/digitalOcean/main.tf @@ -14,10 +14,36 @@ provider "digitalocean" { # ── SSH Key ────────────────────────────────────────────────── resource "digitalocean_ssh_key" "openclaw" { + count = var.existing_ssh_key_fingerprint == "" ? 1 : 0 name = "openclaw-key" public_key = file(var.ssh_public_key_path) } +locals { + openclaw_ssh_key_fingerprint = var.existing_ssh_key_fingerprint != "" ? var.existing_ssh_key_fingerprint : digitalocean_ssh_key.openclaw[0].fingerprint + + # Build plugin paths based on enabled channels + plugin_paths = join( + ",\n ", + concat( + ["\"/usr/lib/node_modules/openclaw/dist/extensions/telegram\""], + var.line_channel_access_token != "" && var.line_channel_secret != "" ? ["\"/usr/lib/node_modules/openclaw/dist/extensions/line\""] : [] + ) + ) + + # Build plugin entries based on enabled channels + plugin_entries = join( + "\n ", + concat( + ["\"telegram\": { \"enabled\": true },"], + var.line_channel_access_token != "" && var.line_channel_secret != "" ? ["\"line\": { \"enabled\": true },"] : [] + ) + ) + + # Build LINE channel JSON section (empty if not configured) + line_channel_json = var.line_channel_access_token != "" && var.line_channel_secret != "" ? ",\n \"line\": {\n \"enabled\": true,\n \"accounts\": {\n \"default\": {\n \"channelAccessToken\": \"${var.line_channel_access_token}\",\n \"channelSecret\": \"${var.line_channel_secret}\"\n }\n }\n }" : "" +} + # ── Firewall ───────────────────────────────────────────────── resource "digitalocean_firewall" "openclaw" { @@ -59,15 +85,20 @@ resource "digitalocean_droplet" "openclaw" { region = var.region size = var.droplet_size image = "ubuntu-24-04-x64" - ssh_keys = [digitalocean_ssh_key.openclaw.fingerprint] + ssh_keys = [local.openclaw_ssh_key_fingerprint] user_data = templatefile("${path.module}/bootstrap.sh", { - openrouter_api_key = var.openrouter_api_key - telegram_bot_token = var.telegram_bot_token - openclaw_gateway_token = var.openclaw_gateway_token - brave_api_key = var.brave_api_key - swap_size = var.swap_size - telegram_owner_id = var.telegram_owner_id + openrouter_api_key = var.openrouter_api_key + telegram_bot_token = var.telegram_bot_token + line_channel_access_token = var.line_channel_access_token + line_channel_secret = var.line_channel_secret + openclaw_gateway_token = var.openclaw_gateway_token + brave_api_key = var.brave_api_key + swap_size = var.swap_size + telegram_owner_id = var.telegram_owner_id + plugin_paths = local.plugin_paths + plugin_entries = local.plugin_entries + line_channel_json = local.line_channel_json }) } diff --git a/terraform/digitalOcean/terraform.tfvars.example b/terraform/digitalOcean/terraform.tfvars.example index 1321610..30edb68 100644 --- a/terraform/digitalOcean/terraform.tfvars.example +++ b/terraform/digitalOcean/terraform.tfvars.example @@ -8,6 +8,9 @@ do_token = "your-digitalocean-api-token" # ── SSH ────────────────────────────────────────────────────── ssh_public_key_path = "~/.ssh/id_rsa.pub" +# Optional: reuse an existing SSH key in your DO account to avoid duplicate-key errors. +# existing_ssh_key_fingerprint = "3b:16:bf:e5:8f:89:02:8c:67:63:6a:73:b4:7d:85:4d" + # ── Droplet ────────────────────────────────────────────────── # Regions: tor1 (Toronto), sfo3 (San Francisco), nyc3 (New York), sgp1 (Singapore), ams3 (Amsterdam) region = "tor1" @@ -26,6 +29,8 @@ swap_size = "3G" # ── Secrets ────────────────────────────────────────────────── openrouter_api_key = "sk-or-v1-your-key-here" telegram_bot_token = "1234567890:your-token-here" +line_channel_access_token = "" +line_channel_secret = "" openclaw_gateway_token = "your-secret-gateway-token" # ── Web Search ─────────────────────────────────────────────── diff --git a/terraform/digitalOcean/variables.tf b/terraform/digitalOcean/variables.tf index 07a5b11..2c21e5a 100644 --- a/terraform/digitalOcean/variables.tf +++ b/terraform/digitalOcean/variables.tf @@ -9,6 +9,11 @@ variable "ssh_public_key_path" { default = "~/.ssh/id_rsa.pub" } +variable "existing_ssh_key_fingerprint" { + description = "Existing DigitalOcean SSH key fingerprint to reuse. Leave empty to create a new SSH key from ssh_public_key_path." + default = "" +} + # ── Droplet ────────────────────────────────────────────────── variable "region" { description = "DigitalOcean region slug (e.g. tor1, sfo3, nyc3, sgp1, ams3)" @@ -46,6 +51,18 @@ variable "telegram_bot_token" { sensitive = true } +variable "line_channel_access_token" { + description = "LINE Messaging API channel access token. Leave empty to disable LINE channel." + sensitive = true + default = "" +} + +variable "line_channel_secret" { + description = "LINE Messaging API channel secret. Leave empty to disable LINE channel." + sensitive = true + default = "" +} + variable "openclaw_gateway_token" { sensitive = true }