Просмотр исходного кода

bin/ircd: add github commits notifier bot

Dastan-glitch 3 лет назад
Родитель
Сommit
0250647a1d
1 измененных файлов с 146 добавлено и 0 удалено
  1. 146 0
      bin/ircd/script/bots/commitbot.py

+ 146 - 0
bin/ircd/script/bots/commitbot.py

@@ -0,0 +1,146 @@
+# -*- coding: utf-8 -*-
+
+from http.server import BaseHTTPRequestHandler,HTTPServer
+import json
+import sys
+import irc
+
+# Attributes of the server this bot will run on
+SERVER_HOST = 'server.url.or.ip'
+SERVER_PORT = 11022
+
+# Attributes of the IRC connection
+IRC_SERVER = '127.0.0.1'
+IRC_PORT = 6667
+IRC_CHANNEL = ['#dev']
+IRC_NICK = 'commits-notifier'
+
+# Set the password for your registered empty, leave empty if not applicable
+# Note: freenode(and potentially other servers) want password to be of the form
+# "nick:pass", so for ex. IRC_PASS = 'WfTestBot:mypass123'
+IRC_PASS = ''
+
+# a dictionary of branches push-related events should be enabled for, or empty if all are enabled
+GH_PUSH_ENABLED_BRANCHES = [] # for example, ['master', 'testing', 'author/repo:branch']
+
+# a dictionary of branches push-related events should be ignored for, or empty if all are enabled
+GH_PUSH_IGNORE_BRANCHES = ['gh-pages']
+
+# a list of push-related events the bot should post notifications for
+GH_PUSH_ENABLED_EVENTS = ['push'] # no others supported for now
+
+# a list of PR-related events the bot should post notifications for
+# notice 'merged' is just a special case of 'closed'
+GH_PR_ENABLED_EVENTS = ['opened', 'closed', 'reopened'] # could also add 'synchronized', 'labeled', etc.
+
+# handle POST events from github server
+# We should also make sure to ignore requests from the IRC, which can clutter
+# the output with errors
+CONTENT_TYPE = 'content-type'
+CONTENT_LEN = 'content-length'
+EVENT_TYPE = 'x-github-event'
+
+ircc = irc.IRC()
+ircc.connect(IRC_SERVER, IRC_PORT, IRC_CHANNEL, IRC_NICK)
+
+def handle_push_event(irc, data):
+    if GH_PUSH_ENABLED_BRANCHES:
+        branch = get_branch_name_from_push_event(data)
+        repo = data['repository']['full_name']
+        repobranch = repo + ':' + branch
+        if not branch in GH_PUSH_ENABLED_BRANCHES:
+            if not repobranch in GH_PUSH_ENABLED_BRANCHES:
+                return
+    
+    if GH_PUSH_IGNORE_BRANCHES:
+        branch = get_branch_name_from_push_event(data)
+        if branch in GH_PUSH_IGNORE_BRANCHES:
+            return
+
+    if 'push' in GH_PUSH_ENABLED_EVENTS:
+        handle_forward_push(irc, data)
+
+def handle_pull_request(irc, data):
+    author = data['sender']['login']
+    if not data['action'] in GH_PR_ENABLED_EVENTS:
+        return
+
+    action = data['action']
+    merged = data['pull_request']['merged']
+    action = 'merged' if action == 'closed' and merged else action
+    pr_num = '#' + str(data['number'])
+    title = data['pull_request']['title']
+
+    print("PR event:")
+    print(f"@{author} {action} pull request {pr_num}: {title}")
+    print("==============================================")
+
+    irc.send("#dev", f"@{author} {action} pull request {pr_num}: {title}")
+
+def get_branch_name_from_push_event(data):
+    return data['ref'].split('/')[-1]
+
+def handle_forward_push(irc, data):
+    author = data['pusher']['name']
+
+    num_commits = len(data['commits'])
+    num_commits = str(num_commits) + " commit" + ('s' if num_commits > 1 else '')
+
+    branch = get_branch_name_from_push_event(data)
+
+    commits = list(map(fmt_commit, data['commits']))
+    for commit in commits:
+        print("Push event:")
+        print(f"@{author} pushed {num_commits} to {branch}: {commit}")
+        print("==============================================")
+        irc.send("#dev", f"@{author} pushed {num_commits} to {branch}: {commit}")
+
+MAX_COMMIT_LEN = 256
+
+def fmt_commit(cmt):
+    hsh = cmt['id'][:10]
+    # author = cmt['author']['name']
+    message = cmt['message']
+    message = message[:MAX_COMMIT_LEN] \
+            + ('..' if len(message) > MAX_COMMIT_LEN else '')
+
+    return '{}: {}'.format(hsh, message)
+
+class MyHandler(BaseHTTPRequestHandler):
+    def do_GET(self):
+        pass
+    def do_CONNECT(self):
+        pass
+    def do_POST(self):
+        if not all(x in self.headers for x in [CONTENT_TYPE, CONTENT_LEN, EVENT_TYPE]):
+            return
+        content_type = self.headers['content-type']
+        content_len = int(self.headers['content-length'])
+        event_type = self.headers['x-github-event']
+
+        if content_type != "application/json":
+            self.send_error(400, "Bad Request", "Expected a JSON request")
+            return
+
+        data = self.rfile.read(content_len)
+        if sys.version_info < (3, 6):
+            data = data.decode()
+
+        self.send_response(200)
+        self.send_header('content-type', 'text/html')
+        self.end_headers()
+        self.wfile.write(bytes('OK', 'utf-8'))
+
+        if event_type == 'push':
+            handle_push_event(ircc, json.loads(data))
+        elif event_type == 'pull_request':
+            handle_pull_request(ircc, json.loads(data))
+        return
+
+# Run Github webhook handling server
+try:
+    server = HTTPServer((SERVER_HOST, SERVER_PORT), MyHandler)
+    server.serve_forever()
+except KeyboardInterrupt:
+    print("Exiting")
+    server.socket.close()