Github.tcl

TCL Guest 7 Views Size: 3.39 KB Posted on: Aug 15, 25 @ 7:48 PM
  1. package require http
  2. package require json
  3.  
  4. # Configuration
  5. set webhook_secret "your_webhook_secret_here" ;# Replace with your GitHub webhook secret
  6. set channel "#yourchannel" ;# Replace with your IRC channel
  7. set port 5000 ;# Port for the webhook server
  8. set bind_addr "0.0.0.0" ;# Listen on all interfaces
  9.  
  10. # Utility to compute HMAC-SHA256 for webhook signature verification
  11. proc compute_hmac {secret data} {
  12.     set hmac [::sha256::hmac $secret $data]
  13.     return [binary encode hex $hmac]
  14. }
  15.  
  16. # Verify GitHub webhook signature
  17. proc verify_signature {payload signature} {
  18.     global webhook_secret
  19.     if {$signature == ""} {
  20.         return 0
  21.     }
  22.     set expected_signature [compute_hmac $webhook_secret $payload]
  23.     return [expr {$signature == "sha256=$expected_signature"}]
  24. }
  25.  
  26. # Handle incoming webhook requests
  27. proc webhook_handler {sock addr port} {
  28.     global channel webhook_secret
  29.    # Read the request
  30.     set request [http::geturl "http://$addr:$port" -socket $sock -timeout 10000]
  31.     set headers [http::meta $request]
  32.     set payload [http::data $request]
  33.     http::cleanup $request
  34.  
  35.     # Get the GitHub event type and signature
  36.     set event [dict get $headers X-GitHub-Event]
  37.     set signature [dict get $headers X-Hub-Signature-256]
  38.  
  39.     # Verify signature
  40.     if {![verify_signature $payload $signature]} {
  41.         putserv "PRIVMSG $channel :\[Webhook\] Invalid signature received."
  42.         return
  43.     }
  44.  
  45.     # Parse JSON payload
  46.     if {[catch {set data [::json::json2dict $payload]} err]} {
  47.         putserv "PRIVMSG $channel :\[Webhook\] Error parsing JSON: $err"
  48.         return
  49.     }
  50.  
  51.     # Handle push events
  52.     if {$event == "push"} {
  53.         set repo [dict get $data repository full_name]
  54.         set pusher [dict get $data pusher name]
  55.         set commits [dict get $data commits]
  56.         foreach commit $commits {
  57.             set commit_id [string range [dict get $commit id] 0 6]
  58.             set message [lindex [split [dict get $commit message] "\n"] 0]
  59.             set url [dict get $commit url]
  60.             set author [dict get $commit author name]
  61.             putserv "PRIVMSG $channel :\[${repo}\] New commit by ${author} (${commit_id}): ${message} ${url}"
  62.         }
  63.     }
  64.  
  65.     # Handle issue events (only when opened)
  66.     if {$event == "issues" && [dict get $data action] == "opened"} {
  67.         set repo [dict get $data repository full_name]
  68.         set issue [dict get $data issue]
  69.         set issue_number [dict get $issue number]
  70.         set title [dict get $issue title]
  71.         set url [dict get $issue html_url]
  72.         set user [dict get $issue user login]
  73.         putserv "PRIVMSG $channel :\[${repo}\] New issue #${issue_number} opened by ${user}: ${title} ${url}"
  74.     }
  75.  
  76.     # Send HTTP response
  77.     puts $sock "HTTP/1.1 200 OK"
  78.     puts $sock "Content-Type: text/plain"
  79.     puts $sock "Content-Length: 2"
  80.     puts $sock ""
  81.     puts $sock "OK"
  82.     close $sock
  83. }
  84.  
  85. # Start the webhook server
  86. proc start_webhook_server {} {
  87.     global port bind_addr
  88.     if {[catch {socket -server webhook_handler $bind_addr:$port} err]} {
  89.         putlog "Error starting webhook server: $err"
  90.     } else {
  91.         putlog "Webhook server started on port $port"
  92.     }
  93. }
  94.  
  95. # Load the sha256 package (included with Eggdrop)
  96. package require sha256
  97.  
  98. # Start the server when the script is loaded
  99. start_webhook_server
  100.  
  101. putlog "GitHub Webhook Relay loaded."

Raw Paste