You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
6.9 KiB
193 lines
6.9 KiB
#!/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 != None:
|
|
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) |