#!/usr/bin/env python3
"""
GitHub Webhook 接收服务
监听 9000 端口，接收 GitHub 推送通知并触发部署
"""

import http.server
import subprocess
import hashlib
import hmac
import os
import json
import sys

WEBHOOK_SECRET = os.environ.get('WEBHOOK_SECRET', '')
DEPLOY_SCRIPT = '/root/hexo-blog/deploy.sh'
PORT = 9000

class WebhookHandler(http.server.BaseHTTPRequestHandler):
    def log_message(self, format, *args):
        print(f"[Webhook] {args[0]}")
    
    def do_POST(self):
        # 验证签名
        signature = self.headers.get('X-Hub-Signature-256', '')
        if WEBHOOK_SECRET and signature:
            body = self.rfile.read(int(self.headers.get('Content-Length', 0)))
            expected = 'sha256=' + hmac.new(
                WEBHOOK_SECRET.encode(), body, hashlib.sha256
            ).hexdigest()
            if not hmac.compare_digest(signature, expected):
                self.send_response(403)
                self.end_headers()
                self.wfile.write(b'Invalid signature')
                return
            # 重新读取 body
            import io
            self.rfile = io.BytesIO(body)
        
        # 验证事件类型
        event = self.headers.get('X-GitHub-Event', '')
        if event not in ['push', 'ping']:
            self.send_response(400)
            self.end_headers()
            self.wfile.write(b'Invalid event type')
            return
        
        # 读取 payload
        content_length = int(self.headers.get('Content-Length', 0))
        payload = json.loads(self.rfile.read(content_length))
        
        # 处理 ping 事件
        if event == 'ping':
            self.send_response(200)
            self.end_headers()
            self.wfile.write(b'pong')
            print("[Webhook] Ping received")
            return
        
        # 检查分支（只部署 main/master 分支）
        ref = payload.get('ref', '')
        if ref not in ['refs/heads/main', 'refs/heads/master']:
            self.send_response(200)
            self.end_headers()
            self.wfile.write(b'Ignored non-main branch')
            print(f"[Webhook] Ignored branch: {ref}")
            return
        
        # 触发部署
        print(f"[Webhook] Push received from {ref}, triggering deploy...")
        try:
            result = subprocess.run(
                ['bash', DEPLOY_SCRIPT],
                capture_output=True,
                text=True,
                timeout=300
            )
            if result.returncode == 0:
                self.send_response(200)
                self.end_headers()
                self.wfile.write(b'Deploy success')
                print("[Webhook] Deploy success")
            else:
                self.send_response(500)
                self.end_headers()
                self.wfile.write(f'Deploy failed: {result.stderr}'.encode())
                print(f"[Webhook] Deploy failed: {result.stderr}")
        except subprocess.TimeoutExpired:
            self.send_response(504)
            self.end_headers()
            self.wfile.write(b'Deploy timeout')
            print("[Webhook] Deploy timeout")
        except Exception as e:
            self.send_response(500)
            self.end_headers()
            self.wfile.write(f'Error: {str(e)}'.encode())
            print(f"[Webhook] Error: {e}")

if __name__ == '__main__':
    server = http.server.HTTPServer(('0.0.0.0', PORT), WebhookHandler)
    print(f"[Webhook] Starting server on port {PORT}...")
    server.serve_forever()
