From 0ba2001b62a0d610f5b5fe4153d7bddd39342470 Mon Sep 17 00:00:00 2001 From: ChChBot admin Date: Wed, 18 Feb 2015 22:44:57 +0100 Subject: [PATCH] some new plugins (thx to _20h_) --- disabled_stuff/freddy.py | 13 +++ disabled_stuff/status.py | 53 ++++++++++++ plugins/bandwidth.py | 21 +++++ plugins/chch_worker.py | 183 +++++++++++++++++++++++++++++++++++++++ plugins/statuslog.py | 76 ++++++++++++++++ 5 files changed, 346 insertions(+) create mode 100644 disabled_stuff/freddy.py create mode 100644 disabled_stuff/status.py create mode 100644 plugins/bandwidth.py create mode 100644 plugins/chch_worker.py create mode 100644 plugins/statuslog.py diff --git a/disabled_stuff/freddy.py b/disabled_stuff/freddy.py new file mode 100644 index 0000000..c77fa5a --- /dev/null +++ b/disabled_stuff/freddy.py @@ -0,0 +1,13 @@ +from util import hook, http, web +from subprocess import check_output, CalledProcessError + +@hook.command +def freddycode(inp): + """freddycode - Check if the Freddy Fresh code is correct.""" + + try: + return "Freddy: '%s' ist %s" % (inp, \ + check_output(["/bin/freddycheck", inp])) + except CalledProcessError as err: + return "Freddy: Skript returned %s" % (str(err)) + diff --git a/disabled_stuff/status.py b/disabled_stuff/status.py new file mode 100644 index 0000000..977ac8e --- /dev/null +++ b/disabled_stuff/status.py @@ -0,0 +1,53 @@ +from util import hook +import re +import time +from subprocess import check_output + +def getstatus(): + try: + return check_output("sudo /bin/chch-status", shell=True).strip("\n").decode("utf-8") + except: + return "unbekannt" + +@hook.command("status", autohelp=False) +def cmd_status(inp, reply=None): + """status - Return the door status""" + reply("Chaostreff Status: %s" % (getstatus())) + +@hook.event("TOPIC") +def topic_update(info, conn=None, chan=None): + """topic_update -- Update the topic on TOPIC command""" + status = getstatus() + + topic = info[-1] + + sstr = "Status: %s" % (status) + if sstr in topic: + return + + if 'Status: ' in topic: + new_topic = re.sub("Status: [^ ]*", sstr, topic) + else: + new_topic = "%s | %s" % (topic.rstrip(' |'), sstr) + + if new_topic != topic: + conn.send("TOPIC %s :%s" % (chan, new_topic)) + +@hook.event("332") +def e332_update(info, conn=None, chan=None): + """e332_update -- run after current topic was requested""" + chan = info[1] + topic_update(info, conn=conn, chan=chan) + +@hook.singlethread +@hook.event("353") +def e353_update(info, conn=None, chan=None): + """e353_update -- runs after a channel was joined""" + chan = info[2] + if chan.lower() == "#chaoschemnitz": + conn.send("PRIVMSG Chanserv :op #chaoschemnitz") + + while True: + conn.send("TOPIC %s" % (chan)) + time.sleep(60) + diff --git a/plugins/bandwidth.py b/plugins/bandwidth.py new file mode 100644 index 0000000..ea23333 --- /dev/null +++ b/plugins/bandwidth.py @@ -0,0 +1,21 @@ +from util import hook, http, web +from subprocess import check_output, CalledProcessError +from datetime import datetime + +@hook.command("bw", autohelp=False) +def bw(inp): + """bw - list last bandwidth measurement to the outside.""" + + try: + o = check_output("/bin/chch-bandwidth") + except CalledProcessError as err: + return "chch-bandwidth: returned %s" % (str(err)) + + os = o.split(",") + upl = int(os[-1])/1024.0/1024.0 + dl = int(os[-2])/1024.0/1024.0 + ts = os[0] + tsd = datetime.strptime(ts, "%Y%m%d%H%M%S") + + return "%s: upl = %f Mbit/s; dl = %f Mbit/s;" % (tsd, upl, dl) + diff --git a/plugins/chch_worker.py b/plugins/chch_worker.py new file mode 100644 index 0000000..5ebc24f --- /dev/null +++ b/plugins/chch_worker.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +from util import hook +import re +import time +import requests +import urllib +from subprocess import check_output +import json + +def run_ecmd(cmd): +# baseuri = "http://netio.chch.lan.ffc/ecmd?" + baseuri = "http://10.8.128.35/ecmd?" + cmds = "%20".join(cmd) + req = requests.get("%s%s" % (baseuri, cmds)) + return req.text.strip() + +# Lamp handling +@hook.command("lamp", autohelp=True) +def cmd_lamp(inp, reply=None): + """lamp color [mode] - set the lamp color""" + args = inp.split(" ") + if len(args) < 1: + reply("""lamp color [mode] - set the lamp color""") + return + + if len(args[0]) != 6: + reply("""lamp color [mode] - set the lamp color""") + return + + cmode = "s" + if len(args) > 1: + if args[1] == "s" or args[1] == "y" or args[1] == "f": + cmode = args[1] + + c = [] + c.append([5, int(args[0][0:2], 16)]) + c.append([4, int(args[0][2:4], 16)]) + c.append([3, int(args[0][4:6], 16)]) + + for ce in c: + res = run_ecmd(["channel", str(ce[0]), str(ce[1]), cmode]) + if res != "OK": + return + reply("OK") + +@hook.command("lamp_fadestep", autohelp=True) +def cmd_lamp_fadestep(inp, reply=None): + """lamp_fadestep step - set the lamp fadestep""" + args = inp.split(" ") + + if len(args) < 1: + reply("""lamp_fadestep step - set the lamp fadestep""") + return + + reply(run_ecmd(["fadestep", args[0]])) + +@hook.command("lamp_fadestep_get", autohelp=False) +def cmd_lamp_fadestep_get(inp, reply=None): + """lamp_fadestep_get - get the lamp fadestep""" + reply(run_ecmd(["fadestep"])) + +@hook.command("lamp_channels", autohelp=False) +def cmd_lamp_channels(inp, reply=None): + """lamp_chanels - get the lamp channel count""" + reply(run_ecmd(["channels"])) + +# Wiki handling +def wiki_changes(cmd=False): + tmpfile = "/tmp/wikichanges.timestamp.txt" + basewikiuri = "https://www.chaoschemnitz.de/index.php?title=%s" + wikiapiuri = "https://www.chaoschemnitz.de/api.php?"\ + "action=query&list=recentchanges&format=json&"\ + "rcprop=user|userid|comment|parsedcomment|timestamp|"\ + "title|sha1|sizes|redirect|loginfo|tags|flags"\ + "&rclist=edit|external|new|log" + + try: + fdch = open(tmpfile, "rw") + timestamp = fdch.read() + fdch.close() + except IOError: + timestamp = None + + try: + r = requests.get(wikiapiuri, verify=False) + except: + return [] + + rarr = [] + changes = r.json["query"]["recentchanges"] + ntimestamp = changes[0]["timestamp"] + for change in changes: + if change["timestamp"] == timestamp: + break + uri = basewikiuri % (urllib.quote(change["title"].encode("utf-8"), safe="")) + rarr.append("wiki: %s changed '%s' ( %s ) comment: %s" %\ + (change["user"], change["title"], uri,\ + change["comment"].strip("\r\n\t"))) + + if cmd == False: + fdch = open(tmpfile, "w+") + fdch.write("%s" % (ntimestamp)) + fdch.close() + + return rarr + +def print_wiki_changes(info, conn=None, chan=None): + """print_wiki_changes - print wiki changes, when the worker calls""" + ch = wiki_changes(cmd=False) + if len(ch) == 0: + return + for c in ch[::-1]: + conn.msg("#chaoschemnitz", c) + time.sleep(0.5) + +@hook.command("wikichanges", autohelp=False) +def cmd_wikichanges(inp, reply=None): + """wikichanges - Return new recent wiki changes""" + ch = wiki_changes(cmd=True) + if len(ch) == 0: + reply("No changes since the last call were made to the wiki.") + else: + for c in ch[::-1][-4:]: + reply(c) + time.sleep(0.5) + +# Status handling +def getstatus(): + try: + response = urllib.urlopen('https://www.chaoschemnitz.de/chch.json') + chch_json = response.read() + chch_info = json.loads(chch_json) + if chch_info['state']['open']: + return "geƶffnet".decode("utf-8") + else: + return "geschlossen" +# return check_output("sudo /bin/chch-status", shell=True).strip("\n").decode("utf-8") + except: + return "unbekannt" + +@hook.command("status", autohelp=False) +def cmd_status(inp, reply=None): + """status - Return the door status""" + reply("Chaostreff Status: %s" % (getstatus())) + +@hook.event("TOPIC") +def topic_update(info, conn=None, chan=None): + """topic_update -- Update the topic on TOPIC command""" + status = getstatus() + + topic = info[-1] + + sstr = "Status: %s" % (status) + if sstr in topic: + return + + if 'Status: ' in topic: + new_topic = re.sub("Status: [^ ]*", sstr, topic) + else: + new_topic = "%s | %s" % (topic.rstrip(' |'), sstr) + + if new_topic != topic: + conn.send("TOPIC %s :%s" % (chan, new_topic)) + +@hook.event("332") +def e332_update(info, conn=None, chan=None): + """e332_update -- run after current topic was requested, runs worker tasks too""" + chan = info[1] + topic_update(info, conn=conn, chan=chan) + print_wiki_changes(info, conn=conn, chan=chan) + +@hook.singlethread +@hook.event("353") +def e353_update(info, conn=None, chan=None): + """e353_update -- runs after a channel (#chaoschemnitz) was joined""" + chan = info[2] + if chan.lower() == "#chaoschemnitz": + conn.send("PRIVMSG Chanserv :op #chaoschemnitz") + + while True: + time.sleep(60) + conn.send("TOPIC %s" % (chan)) + diff --git a/plugins/statuslog.py b/plugins/statuslog.py new file mode 100644 index 0000000..e70c7f8 --- /dev/null +++ b/plugins/statuslog.py @@ -0,0 +1,76 @@ +import os +import codecs +import time +import re + +from util import hook + +timestamp_format = '%H:%M:%S' + +formats = { + 'PRIVMSG': '<%(nick)s> %(msg)s', + 'PART': '-!- %(nick)s [%(user)s@%(host)s] has left %(chan)s', + 'JOIN': '-!- %(nick)s [%(user)s@%(host)s] has joined %(param0)s', + 'MODE': '-!- mode/%(chan)s [%(param_tail)s] by %(nick)s', + 'KICK': '-!- %(param1)s was kicked from %(chan)s by %(nick)s [%(msg)s]', + 'TOPIC': '-!- %(nick)s changed the topic of %(chan)s to: %(msg)s', + 'QUIT': '-!- %(nick)s has quit [%(msg)s]', + 'PING': '', + 'NOTICE': '-%(nick)s- %(msg)s' +} + +ctcp_formats = { + 'ACTION': '* %(nick)s %(ctcpmsg)s', + 'VERSION': '%(nick)s has requested CTCP %(ctcpcmd)s from %(chan)s: %(ctcpmsg)s', + 'PING': '%(nick)s has requested CTCP %(ctcpcmd)s from %(chan)s: %(ctcpmsg)s', + 'TIME': '%(nick)s has requested CTCP %(ctcpcmd)s from %(chan)s: %(ctcpmsg)s', + 'FINGER': '%(nick)s has requested CTCP %(ctcpcmd)s from %(chan)s: %(ctcpmsg)s' +} + +irc_color_re = re.compile(r'(\x03(\d+,\d+|\d)|[\x0f\x02\x16\x1f])') + + +def gmtime(format): + return time.strftime(format, time.gmtime()) + + +def beautify(input): + format = formats.get(input.command, '%(raw)s') + args = dict(input) + + leng = len(args['paraml']) + for n, p in enumerate(args['paraml']): + args['param' + str(n)] = p + args['param_' + str(abs(n - leng))] = p + + args['param_tail'] = ' '.join(args['paraml'][1:]) + args['msg'] = irc_color_re.sub('', args['msg']) + + if input.command == 'PRIVMSG' and input.msg.count('\x01') >= 2: + ctcp = input.msg.split('\x01', 2)[1].split(' ', 1) + if len(ctcp) == 1: + ctcp += [''] + args['ctcpcmd'], args['ctcpmsg'] = ctcp + format = ctcp_formats.get(args['ctcpcmd'], + '%(nick)s [%(user)s@%(host)s] requested unknown CTCP ' + '%(ctcpcmd)s from %(chan)s: %(ctcpmsg)s') + + return format % args + +@hook.singlethread +@hook.event('*') +def log(paraml, input=None, bot=None): + timestamp = gmtime(timestamp_format) + + if input.command == 'QUIT': # these are temporary fixes until proper + input.chan = 'quit' # presence tracking is implemented + if input.command == 'NICK': + input.chan = 'nick' + + beau = beautify(input) + + if beau == '': # don't log this + return + + print timestamp, input.chan, beau.encode('utf8', 'ignore') +