diff --git a/run_lugito b/run_lugito deleted file mode 100755 index dddd80a..0000000 --- a/run_lugito +++ /dev/null @@ -1,365 +0,0 @@ -#!/usr/bin/env python3 - -import regex -import ssl -import http -import http.client -import hmac -import json -import socket -import threading -import logging -from time import sleep -from flask import Flask, request -from pprint import pprint -from hashlib import sha256 -from phabricator import Phabricator -from launchpadlib.launchpad import Launchpad - -website = "https://phab.lubuntu.me" -phab = Phabricator(host=website + "/api/", token="API KEY") -username = "lugito" -password = "" -server = "irc.freenode.net" -port = 6697 -channel = "#lubuntu-devel" -lp = Launchpad.login_with("lugito", "production", "devel") -bugmessage = ("This bug has been marked as fixed in the Git repository: LINK\n" - "The commit message is the following: COMMITMESSAGE\n\n" - "(Note: I am only a bot. If this message was received in error, " - "please contact my owners on the Lubuntu Team.)") -cursupportedrels = ["Cosmic", "Bionic", "Xenial", "Trusty"] - -logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.DEBUG) -logger = logging.getLogger(__name__) - -app = Flask(__name__) - - -def connecttoirc(): - global conn, username - rawconn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - conn = ssl.wrap_socket(rawconn) - conn.connect((server, port)) - setup = False - usersuffix = 0 - logger.info("Connecting to IRC.") - while not setup: - response = conn.recv(512).decode("utf-8") - logger.debug(response) - 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")) - conn.send("PRIVMSG nickserv :identify {} {}\r\n".format(username, password).encode("utf-8")) - - if "You are now identified" in response: - sleep(5) - conn.send("JOIN {}\r\n".format(channel).encode("utf-8")) - - if "477" in response: - sleep(5) - 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 - logger.info("Successfully connected to the IRC server.") - - -def isnewtask(task): - newtask = None - 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 - logger.debug(message) - # Sleep for a fifth of a second, so when we have a bunch of messages we have a buffer - sleep(0.2) - # Aaaaand, send it off! - sendnotice(message) - - -def gettaskinfo(task): - sendmessage = "" - try: - # We only need the task number. - taskinfo = phab.maniphest.info(task_id=int(task.split("T")[1])) - - sendmessage = sendmessage + "\x033[\x03" - - # The color of the priority text should correspond to its value. - color = taskinfo["priorityColor"] - if color == "violet": - sendmessage = sendmessage + "\x036Needs Triage" - elif color == "pink": - sendmessage = sendmessage + "\x035Unbreak Now!" - elif color == "red": - sendmessage = sendmessage + "\x034High" - elif color == "orange": - sendmessage = sendmessage + "\x037Medium" - elif color == "yellow": - sendmessage = sendmessage + "\x038Low" - elif color == "sky": - sendmessage = sendmessage + "\x037Wishlist" - - # Put the task status in the message. - sendmessage = sendmessage + ", " + taskinfo["statusName"] + "\x03" - - sendmessage = sendmessage + "\x033]\x03 " - - # Put the title in there as well. - sendmessage = sendmessage + taskinfo["title"].strip() + ": " - - # And the link. - sendmessage = sendmessage + "\x032" + taskinfo["uri"] + "\x03" - - # Send it off! - sendnotice(sendmessage) - # If someone wrote something like "Tblah", obviously that's not right. - except ValueError: - sendnotice("\x034Error: " + task.strip() + "is an invalid task reference.\x03") - return None - - -def ircbot(message, msgtype): - if msgtype == "info": - message = message.split(" :" + username + ": info")[1] - for item in message.split(): - if item.startswith("T"): - gettaskinfo(item.strip()) - elif msgtype == "link": - for item in message.split("https://phab.lubuntu.me/"): - if item.split()[0].strip().startswith("T"): - gettaskinfo(item.split()[0].strip()) - else: - sendnotice("\x034Error: unknown command.\x03") - return None - - -def listenirc(): - while True: - ircmsg = conn.recv(512) - if len(ircmsg) == 0: - # logger.warn is deprecated, use .warning. - logger.warning("Connection lost, reconnecting!") - connecttoirc() - continue - ircmsg = ircmsg.decode("UTF-8").strip('\n\r') - logger.debug(ircmsg) - if ircmsg.find("PING :") != -1: - conn.send(bytes("PONG :pingis\n", "UTF-8")) - elif ircmsg.find(" :" + username + ": info") != -1: - ircbot(ircmsg, "info") - elif ircmsg.find("https://phab.lubuntu.me/T") != -1: - ircbot(ircmsg, "link") - - -@app.route("/commithook", methods=["POST"]) -def commithook(): - data = request.data - # Use hash_ instead of hash to not shadow other globals/protecteds - 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) - logger.debug(data) - - 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: - if data["object"]["type"] == "CMIT": - logger.debug("It's a commit!") - commitphid = data["object"]["phid"] - phidquery = phab.phid.query(phids=[commitphid])[commitphid] - commitmessage = phidquery["fullName"].replace(phidquery["name"] + ": ", "") - - # When we're messing with bug importances, we need to be - # absolutely 100% sure we aren't screwing with the rest of the bug. - # Since there's no super clean way to get source package names, - # we have to hardcode them. - lpname = None - if "rDEFAULTSETTINGS" in phidquery["name"]: - lpname = "lubuntu-default-settings" - elif "rART" in phidquery["name"]: - lpname = "lubuntu-artwork" - elif "rCALASETTINGS" in phidquery["name"]: - lpname = "calamares-settings-ubuntu" - elif "rQTERMINALPACKAGING" in phidquery["name"]: - lpname = "qterminal" - elif "rLXQTCONFIGPACKAGING" in phidquery["name"]: - lpname = "lxqt-config" - elif "rNMTRAYPACKAGING" in phidquery["name"]: - lpname = "nm-tray" - else: - logger.debug("Somehow, an unsupported repository showed up here.") - - if lpname: - # https://help.launchpad.net/Code/Git#Linking_to_bugs - regexp = regex.compile(r"lp:\s+\#\d+(?:,\s*\#\d+)*") - regexpsearch = regexp.search(commitmessage.lower()) - if regexpsearch: - lpbugs = regexpsearch.group(0).strip("lp: ").replace("#", "") - for bug in lpbugs.split(", "): - goodtask = None - lbug = lp.load("/bugs/" + str(bug).strip()) - bug = lbug - for task in bug.bug_tasks: - for rel in cursupportedrels: - if lpname + " (Ubuntu " + rel + ")" in task.bug_target_display_name: - goodtask = task - break - if not goodtask: - if lpname + " (Ubuntu)" in task.bug_target_display_name: - goodtask = task - if goodtask: - message = bugmessage - message = message.replace("LINK", website + "/" + phidquery["name"]) - message = message.replace("COMMITMESSAGE", commitmessage) - bug.newMessage(content=message) - goodtask.status = "Fix Committed" - goodtask.lp_save() - - return "OK" - - -@app.route("/irc", methods=["POST"]) -def main(): - data = request.data - # Use hash_ instead of 'hash' to not shadow externally global values/variables/protecteds - 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) - logger.debug(data) - - 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: - logger.debug("Object exists, checking to see if it's a task or a commit.") - - if data["object"]["type"] == "TASK": - logger.debug("This is a task. Checking if it's new.") - newtask = isnewtask(search) - if newtask: - logger.debug("Yes, it's a new task.") - else: - logger.debug("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 (dataepoch - 10) <= datemodified <= (dataepoch + 10) and task["comments"] != []: - logger.debug("It's a comment, yes.") - comment = True - commentid = task["id"] - if datemodified != task["dateCreated"]: - logger.debug("The comment was edited.") - edited = True - else: - logger.debug("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"] - - body = "" - - 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": - logger.debug("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)