parent
9f4ba7da6e
commit
ac7b470dbc
@ -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)
|
|
Loading…
Reference in new issue