from __future__ import print_function import willie import netaddr import urllib2 import re import os import subprocess import socket import SocketServer import threading msgserver = None # TODO: move into config file :) msgserver_known_senders = { "127.0.0.1": "localhost", "10.132.254.1": "gw01", "10.132.254.2": "gw02", "10.132.254.3": "gw03", "10.132.254.80": "public" } class MsgHandler(SocketServer.BaseRequestHandler): def handle(self): data = self.request.recv(2048).strip() sender = self.client_address[0] if sender in msgserver_known_senders: sender = msgserver_known_senders[sender] bot = self.server.bot if bot is None: print("ERROR: No bot in handle() :-(") return target = bot.config.core.owner if bot.config.has_section('ffpb') and not (bot.config.ffpb.msg_target is None): target = bot.config.ffpb.msg_target bot.msg(target, "[{0}] {1}".format(sender, str(data, "utf-8")) class ThreadingTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): pass def setup(bot): global msgserver if bot.config.has_section('ffpb') and int(bot.config.ffpb.msg_enable) == 1: host = "localhost" port = 2342 if not bot.config.ffpb.msg_host is None: host = bot.config.ffpb.msg_host if not bot.config.ffpb.msg_port is None: port = int(bot.config.ffpb.msg_port) msgserver = ThreadingTCPServer((host,port), MsgHandler) msgserver.bot = bot ip, port = msgserver.server_address print("Messaging server listening on {}:{}".format(ip,port)) msgserver_thread = threading.Thread(target=msgserver.serve_forever) msgserver_thread.daemon = True msgserver_thread.start() def shutdown(bot): global msgserver if not msgserver is None: msgserver.shutdown() print("Closed messaging server.") msgserver = None @willie.module.commands('status') def ffpb_status(bot, trigger): """Status des FFPB-Netzes: Anzahl (aktiver) Knoten + Clients""" response = urllib2.urlopen('http://nodecount.paderborn.freifunk.net/') html = response.read() m = re.search('
\s*(\d+)\s*
', html) nodecount = int(m.group(1)) bot.say('nodecount = {}'.format(nodecount)) def ffpb_get_address(name): peerfilename = '/home/ffpb-statusbot/knoten/' + name peer_mac = None if os.path.exists(peerfilename): peerfile = open(peerfilename, "r") for line in peerfile: if line.startswith("# MAC:"): peer_mac = line[6:].strip() peerfile.close() print("peer '", name, "': file '", peerfilename, "', MAC ", peer_mac, sep='') if not (peer_mac is None): return str(netaddr.EUI(peer_mac).ipv6_link_local()) return None @willie.module.commands('ping') def ffpb_ping(bot, trigger): """Ping FFPB-Knoten""" target_name = trigger.group(2) if target_name is None or len(target_name) == 0: bot.say('Alter, wen soll ich denn pingen? Einmal mit Profis arbeiten -.-') return target = ffpb_get_address(target_name) if target is None: bot.say('Kein Plan wer mit \'' + target_name + '\' gemeint ist :/') return if target.startswith('fe80::'): target = 'fdca:ffee:ff12:132:' + target[6:] print("ping '", target , '"', sep='') result = os.system('ping6 -c 1 -W 2 ' + target + ' 2>/dev/null') if result == 0: bot.say('Knoten "' + target_name + '" antwortet \o/') elif result == 1 or result == 256: bot.say('Keine Antwort von "' + target_name + '" :-(') else: bot.say('Uh oh, irgendwas ist kaputt. Chef, ping result = ' + str(result) + ' - darf ich das essen?') @willie.module.commands('exec-on-peer') def ffpb_remoteexec(bot, trigger): """Remote Execution fuer FFPB_Knoten""" bot_params = trigger.group(2).split(' ',1) if len(bot_params) != 2: bot.say('Wenn du nicht sagst wo mach ich remote execution bei dir!') bot.say('Tipp: !exec-on-peer ') return target_name = bot_params[0] target_cmd = bot_params[1] if not trigger.admin: bot.say('I can haz sudo?') return if trigger.is_privmsg: bot.say('Bitte per Channel.') return if not trigger.nick in bot.ops[trigger.sender]: bot.say('Geh weg.') return target = ffpb_get_address(target_name) if target is None: bot.say('Kein Plan wer mit \'' + target_name + '\' gemeint ist :/') return if target.startswith('fe80::'): target = 'fdca:ffee:ff12:132:' + target[6:] cmd = 'ssh -6 -l root ' + target + ' -- "' + target_cmd + '"' print("REMOTE EXEC = " + cmd) try: result = subprocess.check_output(['ssh', '-6n', '-l', 'root', '-o', 'BatchMode=yes', '-o','StrictHostKeyChecking=no', target, target_cmd], stderr=subprocess.STDOUT, shell=False) lines = str(result).splitlines() if len(lines) == 0: bot.say('exec-on-peer(' + target_name + '): No output') return msg = 'exec-on-peer(' + target_name + '): ' + str(len(lines)) + ' Zeilen' if len(lines) > 8: msg += ' (zeige max. 8)' bot.say(msg + ':') for line in lines[0:8]: bot.say(line) except subprocess.CalledProcessError as e: bot.say('Fehler '+str(e.returncode)+' bei exec-on-peer('+target_name+'): ' + e.output)