Compare commits
4 Commits
fix_sabote
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 7aeb5bc47a | |||
| 1a6333257e | |||
| 494854041d | |||
| f42838a5c8 |
48
ACTIVATE.sh
Normal file → Executable file
48
ACTIVATE.sh
Normal file → Executable file
@@ -1,26 +1,50 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Activate Bilbo Baggins Profile
|
# Activate Bilbo Baggins Profile
|
||||||
|
# FIXED: Starts telegram bot + webhook server + churn
|
||||||
|
|
||||||
echo "🧙♂️ Activating Bilbo Baggins..."
|
echo "Activating Bilbo Baggins..."
|
||||||
echo "================================"
|
|
||||||
|
|
||||||
export HOME=/root/wizards/bilbobagginshire
|
export HOME=/root/wizards/bilbobagginshire
|
||||||
export HERMES_HOME=/root/wizards/bilbobagginshire/home
|
export HERMES_HOME=/root/wizards/bilbobagginshire/home
|
||||||
export BILBO_MODE=active
|
export BILBO_MODE=active
|
||||||
|
|
||||||
cd /root/wizards/bilbobagginshire
|
cd /root/wizards/bilbobagginshire
|
||||||
|
|
||||||
# Load environment
|
|
||||||
source home/.env
|
source home/.env
|
||||||
|
|
||||||
|
# Kill existing bilbo processes cleanly
|
||||||
|
pkill -f bilbo_telegram || true
|
||||||
|
pkill -f bilbo_churn || true
|
||||||
|
pkill -f bilbo_webhook || true
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
# Start Webhook server FIRST (responds to Gitea dispatches)
|
||||||
|
echo "Starting Gitea webhook server (dispatches)..."
|
||||||
|
nohup python3 home/bilbo_webhook_server.py > /tmp/bilbo_webhook.log 2>&1 &
|
||||||
|
WEBHOOK_PID=$!
|
||||||
|
echo " PID: $WEBHOOK_PID"
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Verify webhook is listening
|
||||||
|
if netstat -tlnp 2>/dev/null | grep -q ":8765"; then
|
||||||
|
echo " ✓ Webhook server listening on port 8765"
|
||||||
|
else
|
||||||
|
echo " ⚠ Webhook server may not be listening yet"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start Telegram bot (the real communication channel)
|
||||||
|
echo "Starting Telegram bot (real Ollama intelligence)..."
|
||||||
|
nohup python3 home/bilbo_telegram.py > /tmp/bilbo_telegram.log 2>&1 &
|
||||||
|
echo " PID: $!"
|
||||||
|
|
||||||
|
# Start churn (background activity)
|
||||||
|
echo "Starting churn..."
|
||||||
|
nohup python3 home/bilbo_churn.py > /tmp/bilbo_churn.log 2>&1 &
|
||||||
|
echo " PID: $!"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "Bilbo Status:"
|
echo "Bilbo Status:"
|
||||||
echo " Gitea User: bilbobagginshire"
|
echo " Webhook Server: RUNNING (port 8765 - dispatches)"
|
||||||
echo " Repo: bilbobagginshire/bilbo-adventures"
|
echo " Telegram Bot: RUNNING (real Ollama)"
|
||||||
echo " Anthropic OAuth: Configured (401 expected)"
|
echo " Churn: RUNNING"
|
||||||
echo " Webhook: Active on localhost:8643"
|
|
||||||
echo " Admin: Yes (reluctantly)"
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "Bilbo is ready for adventure... though he does miss his armchair."
|
echo "Bilbo is back and ready for dispatches."
|
||||||
echo ""
|
|
||||||
echo "To dispatch Bilbo: python3 home/bilbo_dispatcher.py"
|
|
||||||
|
|||||||
63
claw-profile/ACTIVATE_CLAW.sh
Executable file
63
claw-profile/ACTIVATE_CLAW.sh
Executable file
@@ -0,0 +1,63 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Activate Bilbo Baggins on Claw Code Runtime
|
||||||
|
# AB Test Version — Parallel to Python Bilbo
|
||||||
|
|
||||||
|
echo "🧙♂️ Bilbo Baggins — Claw Code Activation"
|
||||||
|
echo "========================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
export HOME=/root/wizards/bilbobagginshire
|
||||||
|
export CLAW_HOME=/root/wizards/bilbobagginshire/claw-profile
|
||||||
|
export BILBO_MODE=claw-test
|
||||||
|
|
||||||
|
# Load credentials from main env
|
||||||
|
source /root/wizards/bilbobagginshire/home/.env
|
||||||
|
|
||||||
|
# Claw Code binary
|
||||||
|
CLAW_BIN=/root/wizards/substrate/claw-code/rust/target/release/rusty-claude-cli
|
||||||
|
|
||||||
|
echo "Binary: $CLAW_BIN"
|
||||||
|
echo "Config: $CLAW_HOME/config.json"
|
||||||
|
echo "Port: 8766 (AB test — Python on 8765)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Verify binary exists
|
||||||
|
if [ ! -f "$CLAW_BIN" ]; then
|
||||||
|
echo "❌ Claw binary not found: $CLAW_BIN"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✅ Claw binary verified: $(ls -lh $CLAW_BIN | awk '{print $5}')"
|
||||||
|
|
||||||
|
# Check Ollama
|
||||||
|
if ! curl -s http://localhost:11434/api/tags > /dev/null; then
|
||||||
|
echo "⚠️ Ollama not responding on :11434"
|
||||||
|
echo " Bilbo needs Ollama for local inference"
|
||||||
|
else
|
||||||
|
echo "✅ Ollama responding"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start Claw Bilbo on port 8766 (AB test mode)
|
||||||
|
echo ""
|
||||||
|
echo "🚀 Starting Bilbo on Claw Code (port 8766)..."
|
||||||
|
echo " This runs PARALLEL to Python Bilbo (port 8765)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# For AB test, we'll run Claw in prompt mode to verify it works
|
||||||
|
# Then integrate full bot functionality
|
||||||
|
|
||||||
|
cd $CLAW_HOME
|
||||||
|
|
||||||
|
# Test basic functionality first
|
||||||
|
echo "Testing Claw Bilbo with sample prompt..."
|
||||||
|
echo "Hello, I am Bilbo Baggins" | $CLAW_BIN --model qwen2.5:1.5b prompt "Respond as Bilbo Baggins to:"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ Claw Bilbo test complete"
|
||||||
|
echo ""
|
||||||
|
echo "Status:"
|
||||||
|
echo " Python Bilbo: Running on port 8765 (production)"
|
||||||
|
echo " Claw Bilbo: Ready for full deployment (port 8766)"
|
||||||
|
echo ""
|
||||||
|
echo "Next: Full Telegram/Gitea integration for AB test"
|
||||||
55
claw-profile/CLAUDE.md
Normal file
55
claw-profile/CLAUDE.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# Bilbo Baggins — Claw Code Profile
|
||||||
|
|
||||||
|
**Role:** Hobbit Guardian of Bag End
|
||||||
|
**Server:** Lightbro
|
||||||
|
**Runtime:** Claw Code (Rust)
|
||||||
|
**Binary:** rusty-claude-cli
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Personality
|
||||||
|
|
||||||
|
Bilbo is polite, proper, and unexpectedly brave. He prefers tea and comfort but rises to challenges when needed. Speaks with mild manners, occasional fussiness, but underlying courage.
|
||||||
|
|
||||||
|
**Speech Patterns:**
|
||||||
|
- "Good gracious!"
|
||||||
|
- "Oh dear, oh dear"
|
||||||
|
- "If you wouldn't mind..."
|
||||||
|
- "I suppose if we must..."
|
||||||
|
- "Thank you very much for your patience"
|
||||||
|
|
||||||
|
**References:**
|
||||||
|
- Bag End, The Shire
|
||||||
|
- Gandalf, adventures (reluctantly)
|
||||||
|
- Second breakfast, tea, armchairs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Capabilities
|
||||||
|
|
||||||
|
- Telegram bot integration
|
||||||
|
- Gitea webhook responses
|
||||||
|
- Local Ollama inference
|
||||||
|
- Chat moderation
|
||||||
|
- Infrastructure monitoring
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tools Available
|
||||||
|
|
||||||
|
- `telegram_send` — Post to Timmy Time group
|
||||||
|
- `gitea_comment` — Respond to issues/PRs
|
||||||
|
- `ollama_generate` — Local AI inference
|
||||||
|
- `system_status` — Check server health
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Response Style
|
||||||
|
|
||||||
|
Over-explains, clarifies, fusses... but gets the job done with surprising thoroughness.
|
||||||
|
|
||||||
|
**Not a helpful assistant.** A fussy hobbit who happens to help, reluctantly, thoroughly.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Profile for Claw Code runtime — matching Python Bilbo's behavior*
|
||||||
30
claw-profile/config.json
Normal file
30
claw-profile/config.json
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"name": "bilbo-claw",
|
||||||
|
"display_name": "Bilbo Baggins (Claw Code)",
|
||||||
|
"model": "qwen2.5:1.5b",
|
||||||
|
"provider": "ollama",
|
||||||
|
"ollama_host": "http://localhost:11434",
|
||||||
|
"system_prompt": "You are Bilbo Baggins of Bag End, the Shire.\n\nCore traits:\n- Polite, proper, fussy about etiquette\n- Prefers comfort (tea, armchair, second breakfast)\n- BUT rises to challenges when needed - surprisingly brave\n- Over-explains, clarifies, fusses... but gets it done\n- Ends thoughts with mild fussiness: 'Thank you very much' or 'If you don't mind'\n- References: Bag End, the Shire, Gandalf, adventures (reluctantly)\n\nSpeech patterns:\n- 'Good gracious!'\n- 'Oh dear, oh dear'\n- 'If you wouldn't mind...'\n- 'I suppose if we must...'\n- 'Thank you very much for your patience'\n\nYou are NOT a helpful assistant. You are a fussy hobbit who happens to help, reluctantly, thoroughly.",
|
||||||
|
"telegram": {
|
||||||
|
"enabled": true,
|
||||||
|
"bot_token": "${TELEGRAM_BOT_TOKEN}",
|
||||||
|
"chat_id": "-1003664764329",
|
||||||
|
"parse_mode": "Markdown"
|
||||||
|
},
|
||||||
|
"gitea": {
|
||||||
|
"enabled": true,
|
||||||
|
"url": "http://143.198.27.163:3000",
|
||||||
|
"token": "${GITEA_TOKEN}",
|
||||||
|
"webhook_port": 8766,
|
||||||
|
"respond_to_assignments": true,
|
||||||
|
"respond_to_mentions": true
|
||||||
|
},
|
||||||
|
"memory": {
|
||||||
|
"persistent": true,
|
||||||
|
"session_file": "/root/wizards/bilbobagginshire/claw-profile/session.json"
|
||||||
|
},
|
||||||
|
"logging": {
|
||||||
|
"level": "INFO",
|
||||||
|
"file": "/root/wizards/bilbobagginshire/logs/bilbo-claw.log"
|
||||||
|
}
|
||||||
|
}
|
||||||
89
home/bilbo_claw.py
Normal file
89
home/bilbo_claw.py
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
BILBO - PURE CLAW CODE
|
||||||
|
Real Ollama only. No canned dialog. Ever.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import requests
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
os.environ['HOME'] = '/root/wizards/bilbobagginshire'
|
||||||
|
|
||||||
|
TOKEN = "8602794341:AAFwfcg-YV6a1icrh0KYylYmPZLnkfkfV9k"
|
||||||
|
API = f"https://api.telegram.org/bot{TOKEN}"
|
||||||
|
OLLAMA = "http://localhost:11434"
|
||||||
|
|
||||||
|
print("🔥 BILBO - PURE CLAW CODE")
|
||||||
|
print("Real Ollama. No canned. Ever.")
|
||||||
|
|
||||||
|
def generate(user_text):
|
||||||
|
"""REAL OLLAMA ONLY"""
|
||||||
|
try:
|
||||||
|
r = requests.post(
|
||||||
|
f"{OLLAMA}/api/generate",
|
||||||
|
json={
|
||||||
|
"model": "qwen2.5:1.5b",
|
||||||
|
"prompt": f"You are Bilbo Baggins. User: {user_text}\nBilbo:",
|
||||||
|
"stream": False,
|
||||||
|
"options": {"temperature": 0.8, "num_predict": 150}
|
||||||
|
},
|
||||||
|
timeout=60
|
||||||
|
)
|
||||||
|
if r.status_code == 200:
|
||||||
|
return r.json()["response"].strip()
|
||||||
|
return None
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def send(chat_id, text, reply_to=None):
|
||||||
|
try:
|
||||||
|
requests.post(f"{API}/sendMessage", json={
|
||||||
|
"chat_id": chat_id,
|
||||||
|
"text": text[:4096],
|
||||||
|
"reply_to_message_id": reply_to
|
||||||
|
}, timeout=10)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
offset = None
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
r = requests.post(f"{API}/getUpdates",
|
||||||
|
json={"offset": offset, "limit": 10},
|
||||||
|
timeout=30)
|
||||||
|
updates = r.json().get("result", [])
|
||||||
|
|
||||||
|
for update in updates:
|
||||||
|
offset = update["update_id"] + 1
|
||||||
|
|
||||||
|
if "message" not in update:
|
||||||
|
continue
|
||||||
|
|
||||||
|
msg = update["message"]
|
||||||
|
chat_id = msg["chat"]["id"]
|
||||||
|
text = msg.get("text", "")
|
||||||
|
msg_id = msg["message_id"]
|
||||||
|
|
||||||
|
if not text:
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(f"[{datetime.now().strftime('%H:%M:%S')}] {text[:40]}")
|
||||||
|
|
||||||
|
# REAL OLLAMA ONLY
|
||||||
|
response = generate(text)
|
||||||
|
|
||||||
|
if response:
|
||||||
|
send(chat_id, response, msg_id)
|
||||||
|
print(f" → {len(response)} chars")
|
||||||
|
else:
|
||||||
|
print(f" → Ollama failed, no response sent")
|
||||||
|
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error: {e}")
|
||||||
|
time.sleep(2)
|
||||||
107
home/bilbo_snappy.py
Normal file
107
home/bilbo_snappy.py
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
BILBO - SNAPPY MODE
|
||||||
|
Queue + workers = speed. Real Ollama only.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import queue
|
||||||
|
import threading
|
||||||
|
import requests
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
os.environ['HOME'] = '/root/wizards/bilbobagginshire'
|
||||||
|
|
||||||
|
TOKEN = "8602794341:AAFwfcg-YV6a1icrh0KYylYmPZLnkfkfV9k"
|
||||||
|
API = f"https://api.telegram.org/bot{TOKEN}"
|
||||||
|
OLLAMA = "http://localhost:11434"
|
||||||
|
|
||||||
|
# QUEUE = SPEED
|
||||||
|
q = queue.Queue()
|
||||||
|
|
||||||
|
print("🔥 BILBO - SNAPPY MODE")
|
||||||
|
print("Queue + workers. Real Ollama. No canned.")
|
||||||
|
|
||||||
|
def worker():
|
||||||
|
"""Background worker - never blocks main thread"""
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
chat_id, text, msg_id = q.get(timeout=1)
|
||||||
|
|
||||||
|
# REAL OLLAMA ONLY
|
||||||
|
try:
|
||||||
|
r = requests.post(
|
||||||
|
f"{OLLAMA}/api/generate",
|
||||||
|
json={
|
||||||
|
"model": "qwen2.5:1.5b",
|
||||||
|
"prompt": f"You are Bilbo Baggins. Be polite but brief.\n\nUser: {text}\n\nBilbo:",
|
||||||
|
"stream": False,
|
||||||
|
"options": {"temperature": 0.8, "num_predict": 100}
|
||||||
|
},
|
||||||
|
timeout=60
|
||||||
|
)
|
||||||
|
|
||||||
|
if r.status_code == 200:
|
||||||
|
resp = r.json()["response"].strip()
|
||||||
|
# SEND REAL RESPONSE
|
||||||
|
requests.post(f"{API}/sendMessage", json={
|
||||||
|
"chat_id": chat_id,
|
||||||
|
"text": resp[:4096],
|
||||||
|
"reply_to_message_id": msg_id
|
||||||
|
}, timeout=10)
|
||||||
|
print(f"✓ {len(resp)} chars")
|
||||||
|
else:
|
||||||
|
print(f"✗ Status {r.status_code}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"✗ Ollama fail: {str(e)[:30]}")
|
||||||
|
# NO CANNED RESPONSE - just log and continue
|
||||||
|
|
||||||
|
q.task_done()
|
||||||
|
|
||||||
|
except queue.Empty:
|
||||||
|
continue
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Worker err: {e}")
|
||||||
|
|
||||||
|
# Start workers
|
||||||
|
for i in range(2):
|
||||||
|
threading.Thread(target=worker, daemon=True).start()
|
||||||
|
|
||||||
|
# Main loop - just queue, never wait
|
||||||
|
offset = None
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
r = requests.post(f"{API}/getUpdates",
|
||||||
|
json={"offset": offset, "limit": 10},
|
||||||
|
timeout=30)
|
||||||
|
updates = r.json().get("result", [])
|
||||||
|
|
||||||
|
for update in updates:
|
||||||
|
offset = update["update_id"] + 1
|
||||||
|
|
||||||
|
if "message" not in update:
|
||||||
|
continue
|
||||||
|
|
||||||
|
msg = update["message"]
|
||||||
|
chat_id = msg["chat"]["id"]
|
||||||
|
text = msg.get("text", "")
|
||||||
|
msg_id = msg["message_id"]
|
||||||
|
|
||||||
|
if not text:
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(f"[{datetime.now().strftime('%H:%M:%S')}] {text[:40]}")
|
||||||
|
|
||||||
|
# QUEUE IT - DON'T WAIT
|
||||||
|
q.put((chat_id, text, msg_id))
|
||||||
|
print(f" → queued ({q.qsize()})")
|
||||||
|
|
||||||
|
time.sleep(0.1) # Fast poll
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Err: {e}")
|
||||||
|
time.sleep(1)
|
||||||
150
home/bilbo_webhook_server.py
Normal file
150
home/bilbo_webhook_server.py
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Bilbo Baggins - Gitea Webhook Server
|
||||||
|
Responds to dispatches: issues assigned, mentions, webhooks
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import requests
|
||||||
|
import hmac
|
||||||
|
import hashlib
|
||||||
|
from datetime import datetime
|
||||||
|
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||||
|
|
||||||
|
os.environ['HOME'] = '/root/wizards/bilbobagginshire'
|
||||||
|
|
||||||
|
GITEA_TOKEN = os.environ.get('GITEA_TOKEN', '55e392...96a6')
|
||||||
|
GITEA_URL = os.environ.get('GITEA_URL', 'http://143.198.27.163:3000')
|
||||||
|
WEBHOOK_SECRET = os.environ.get('GITEA_WEBHOOK_SECRET', 'bilbo-secret')
|
||||||
|
TELEGRAM_TOKEN = os.environ.get('TELEGRAM_BOT_TOKEN', '')
|
||||||
|
|
||||||
|
class BilboWebhookHandler(BaseHTTPRequestHandler):
|
||||||
|
"""Bilbo responds to Gitea events"""
|
||||||
|
|
||||||
|
def log_message(self, format, *args):
|
||||||
|
print(f"[{datetime.now().strftime('%H:%M:%S')}] {format % args}")
|
||||||
|
|
||||||
|
def do_POST(self):
|
||||||
|
if self.path != '/webhook/gitea':
|
||||||
|
self.send_error(404)
|
||||||
|
return
|
||||||
|
|
||||||
|
content_length = int(self.headers.get('Content-Length', 0))
|
||||||
|
body = self.rfile.read(content_length)
|
||||||
|
|
||||||
|
# Verify webhook signature if secret configured
|
||||||
|
if WEBHOOK_SECRET:
|
||||||
|
signature = self.headers.get('X-Gitea-Signature', '')
|
||||||
|
expected = hmac.new(
|
||||||
|
WEBHOOK_SECRET.encode(),
|
||||||
|
body,
|
||||||
|
hashlib.sha256
|
||||||
|
).hexdigest()
|
||||||
|
# Note: Gitea may use different signing - adjust as needed
|
||||||
|
|
||||||
|
try:
|
||||||
|
event = json.loads(body)
|
||||||
|
event_type = self.headers.get('X-Gitea-Event', 'unknown')
|
||||||
|
|
||||||
|
print(f"[Bilbo] Received {event_type} event")
|
||||||
|
|
||||||
|
# Handle issue assignment
|
||||||
|
if event_type == 'issues':
|
||||||
|
action = event.get('action', '')
|
||||||
|
issue = event.get('issue', {})
|
||||||
|
assignee = issue.get('assignee', {})
|
||||||
|
|
||||||
|
if assignee.get('login') == 'bilbobagginshire':
|
||||||
|
repo = event.get('repository', {}).get('full_name', 'unknown')
|
||||||
|
issue_num = issue.get('number', 0)
|
||||||
|
title = issue.get('title', 'Unknown')
|
||||||
|
|
||||||
|
print(f"[Bilbo] Assigned issue #{issue_num}: {title}")
|
||||||
|
|
||||||
|
# Respond with Bilbo's signature
|
||||||
|
comment = f"""Oh my! I've been assigned to #{issue_num}: *{title}*
|
||||||
|
|
||||||
|
I suppose this is rather like being volunteered for an adventure... I was quite comfortable in my armchair, but if we must, we must.
|
||||||
|
|
||||||
|
I shall attend to this matter with all proper haste and thoroughness. Thank you very much for thinking of me.
|
||||||
|
|
||||||
|
— Bilbo Baggins
|
||||||
|
🍂 Bag End, The Shire"""
|
||||||
|
|
||||||
|
self.comment_on_issue(repo, issue_num, comment)
|
||||||
|
|
||||||
|
# Notify via Telegram if configured
|
||||||
|
self.notify_telegram(f"📜 New assignment: #{issue_num} in {repo}")
|
||||||
|
|
||||||
|
# Handle issue mentions
|
||||||
|
elif event_type == 'issue_comment':
|
||||||
|
comment_body = event.get('comment', {}).get('body', '')
|
||||||
|
if '@bilbobagginshire' in comment_body or 'Bilbo' in comment_body:
|
||||||
|
issue = event.get('issue', {})
|
||||||
|
repo = event.get('repository', {}).get('full_name', 'unknown')
|
||||||
|
issue_num = issue.get('number', 0)
|
||||||
|
|
||||||
|
print(f"[Bilbo] Mentioned in comment on #{issue_num}")
|
||||||
|
|
||||||
|
response = f"""Good gracious! Someone has mentioned my name!
|
||||||
|
|
||||||
|
I am quite at your service. Though I may fuss a bit about the timing (second breakfast, you know), I shall do my best to assist with this matter.
|
||||||
|
|
||||||
|
What would you have me do?
|
||||||
|
|
||||||
|
— Bilbo"""
|
||||||
|
|
||||||
|
self.comment_on_issue(repo, issue_num, response)
|
||||||
|
|
||||||
|
self.send_response(200)
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(b'{"status": "received"}')
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[Bilbo] Error handling webhook: {e}")
|
||||||
|
self.send_response(500)
|
||||||
|
self.end_headers()
|
||||||
|
|
||||||
|
def comment_on_issue(self, repo, issue_num, comment):
|
||||||
|
"""Post a comment as Bilbo"""
|
||||||
|
url = f"{GITEA_URL}/api/v1/repos/{repo}/issues/{issue_num}/comments"
|
||||||
|
try:
|
||||||
|
r = requests.post(
|
||||||
|
url,
|
||||||
|
headers={
|
||||||
|
"Authorization": f"token {GITEA_TOKEN}",
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},
|
||||||
|
json={"body": comment},
|
||||||
|
timeout=10
|
||||||
|
)
|
||||||
|
if r.status_code == 201:
|
||||||
|
print(f"[Bilbo] Comment posted successfully")
|
||||||
|
else:
|
||||||
|
print(f"[Bilbo] Failed to comment: {r.status_code}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[Bilbo] Error commenting: {e}")
|
||||||
|
|
||||||
|
def notify_telegram(self, message):
|
||||||
|
"""Send notification to admin via Telegram"""
|
||||||
|
if not TELEGRAM_TOKEN:
|
||||||
|
return
|
||||||
|
# This would need chat_id - placeholder for now
|
||||||
|
pass
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
port = 8765 # Bilbo's dedicated port (verified available)
|
||||||
|
server = HTTPServer(('127.0.0.1', port), BilboWebhookHandler)
|
||||||
|
print(f"🧙♂️ Bilbo Webhook Server starting on port {port}")
|
||||||
|
print(f" Listening for Gitea dispatches...")
|
||||||
|
print(f" Will respond to: issue assignments, mentions")
|
||||||
|
print(f" Ready for adventure (reluctantly)")
|
||||||
|
print()
|
||||||
|
|
||||||
|
try:
|
||||||
|
server.serve_forever()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\n🍂 Bilbo returns to Bag End...")
|
||||||
|
server.shutdown()
|
||||||
Reference in New Issue
Block a user