from __future__ import print_function
import willie
import netaddr
import urllib2
import re
import os
import subprocess
from random import randint
import math
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):
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,self.data))
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))
if trigger.nick=='peki75':
bot.say('nodecount = {}+{} ;)'.format(randint(nodecount-30,nodecount-4),math.pi))
elif trigger.nick=='craegga':
bot.say('nodecount = 222{:+}'.format(nodecount-222))
elif trigger.nick=='THiSCO':
bot.say('Heute gibt es keine Nussecken fuer dich!')
else:
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, e:
bot.say('Fehler '+str(e.returncode)+' bei exec-on-peer('+target_name+'): ' + e.output)