#!/usr/bin/env python3 import http import hmac import json import socket import threading from flask import Flask, request from pprint import pprint from hashlib import sha256 from phabricator import Phabricator website = "https://phab.lubuntu.me" phab = Phabricator(host=website+"/api/", token="API KEY") app = Flask(__name__) global username username = "lugito" server = "irc.freenode.net" port = 6667 channel = "#lubuntu-devel" def connecttoirc(): global conn, username conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) conn.connect((server, port)) setup = False usersuffix = 0 while setup == False: response = conn.recv(512).decode("utf-8") if "No Ident response" in response: conn.send("NICK {}\r\n".format(username).encode("utf-8")) conn.send("USER {} * * :{}\r\n".format(username, username).encode("utf-8")) if "376" in response: conn.send("JOIN {}\r\n".format(channel).encode("utf-8")) if "433" in response: usersuffix = usersuffix + 1 username = username + str(usersuffix) conn.send("NICK {}\r\n".format(username).encode("utf-8")) conn.send("USER {} * * :{}\r\n".format(username, username).encode("utf-8")) if "PING" in response: conn.send("PONG :{}\r\n".format(response.split(":")[1]).encode("utf-8")) if "366" in response: setup = True def isnewtask(task): modified = None for data in task: if modified: if data["dateCreated"] == data["dateModified"] and data["dateCreated"] == modified: modified = data["dateCreated"] newtask = True else: newtask = False break else: modified = data["dateCreated"] return newtask def sendnotice(message): conn.send("NOTICE {} :{}\r\n".format(channel, message).encode("utf-8")) def ircmessage(objectstr, who, body, link): # e.g. [T31: Better IRC integration] message = "\x033[\x03\x0313" + objectstr + "\x03\x033]\x03 " # e.g. tsimonq2 (Simon Quigley) message = message + "\x0315" + who + "\x03 " # e.g. commented on the task: message = message + body + ": " # e.g. https://phab.lubuntu.me/T40#779 message = message + "\x032" + link + "\x03" # Make sure we can debug this if it goes haywire print(message) # Aaaaand, send it off! sendnotice(message) def listenirc(): while 1: ircmsg = conn.recv(512) if len(ircmsg) == 0: print("Connection lost, reconnecting!") connecttoirc() continue ircmsg = ircmsg.decode("UTF-8").strip('\n\r') print(ircmsg) if ircmsg.find("PING :") != -1: conn.send(bytes("PONG :pingis\n", "UTF-8")) @app.route("/", methods=["POST"]) def main(): data = request.data hash = hmac.new(bytes(u"HMAC KEY", "utf-8"), data, sha256) # We MUST ensure that the request came from Phab. if hash.hexdigest() == request.headers["X-Phabricator-Webhook-Signature"]: data = json.loads(data) print(data) print exists = True try: # Try to find the object. search = phab.transaction.search(objectIdentifier=data["object"]["phid"])["data"] # Find the author too. userlookup = search[0]["authorPHID"] who = str(dict(phab.phid.query(phids=[userlookup]))[userlookup]["fullName"]) # If the object exists, no worries, let's just return a good response. except http.client.HTTPException: exists = False if exists: print("Object exists, checking to see if it's a task or a commit.") if data["object"]["type"] == "TASK": print("This is a task. Checking if it's new.") newtask = isnewtask(search) if newtask: print("Yes, it's a new task.") else: print("No, it's not a new task.") # If it's not a new task, let's see if it's a comment, and if it's just an edit. comment = None commentid = None edited = None if not newtask: commentid = None edited = False for task in search: dataepoch = data["action"]["epoch"] datemodified = task["dateModified"] # All comments within ten seconds of the request are fair game. if datemodified >= (dataepoch - 10) and datemodified <= (dataepoch + 10) and task["comments"] != []: print("It's a comment, yes.") comment = True commentid = task["id"] if datemodified != task["dateCreated"]: print("The comment was edited.") edited = True else: print("The comment was NOT edited.") edited = False break else: comment = False if comment or edited or newtask: objectstr = phab.phid.query(phids=[data["object"]["phid"]])[data["object"]["phid"]]["fullName"] if comment: body = "commented on the task" elif edited: body = "edited a message on the task" elif newtask: body = "just created this task" # Assuming this is a comment, there should always be a URI associated with it. link = phab.phid.query(phids=[data["object"]["phid"]])[data["object"]["phid"]]["uri"] # Even though this can be off sometimes, let's include the comment ID in the link too. # FIXME: Make this more accurate, and figure out why it's inaccurate at times. if commentid: link = link + "#" + str(commentid) ircmessage(objectstr, who, body, link) elif data["object"]["type"] == "CMIT": print("It's a commit!") commitphid = data["object"]["phid"] objectstr = phab.phid.query(phids=[commitphid])[commitphid]["fullName"] body = "committed" # The URI for this one is waaaaaaay too long. Let's assemble it ourselves. link = website + "/" + phab.phid.query(phids=[commitphid])[commitphid]["name"] ircmessage(objectstr, who, body, link) return "OK" if __name__ == "__main__": connecttoirc() t = threading.Thread(target=listenirc) t.daemon = True t.start() app.run(host="0.0.0.0", port=5000)