# -*- coding: utf-8 -*- from __future__ import print_function import time import willie from ffpb import \ ffpb_findnode_from_botparam, \ mac2ipv6, playitsafe, pretty_date from batcave import BatcaveClient __batcave = None def setup(bot): """Called by willie upon loading this plugin.""" global __batcave, highscores __batcave = BatcaveClient(bot.config.ffpb.batcave_url) pass def shutdown(bot): """Called by willie upon unloading this plugin.""" pass @willie.module.commands('identify') def ffpb_identify(bot, trigger): """Identify node.""" # query must be as OP in the channel if not playitsafe(bot, trigger, via_channel=True, need_op=True): # the check function already gives a bot reply, just exit here return ident = trigger.group(2) or "" ident = ident.lower() result = __batcave.identify(ident) if result is None: bot.say('Mist, ich erreiche den Detektiv nicht.') return if not ident in result: bot.say('Mein Detektiv hat getrunken und erzählt Blödsinn.') return if len(result[ident]) == 0: bot.say('"%s" konnte nicht zugeordnet werden :/' % ident) elif len(result[ident]) == 1: bot.say('"%s" ist eindeutig: %s' % (ident, result[ident][0])) else: bot.say('"{0}" ist mehrdeutig: {1}'.format( ident, str.join(', ', result[ident]))) @willie.module.commands('raw-data') def ffpb_peerdata(bot, trigger): """Show ALFRED data of the given node.""" # identify node or bail out target_name = trigger.group(2) node = ffpb_findnode_from_botparam(bot, target_name) if node is None: return # query must be a PM or as OP in the channel if not playitsafe(bot, trigger, via_privmsg=True, node=node): # the check function already gives a bot reply, just exit here return # reply each key in the node's data for key in node: # skip some fields if key in ['hostname']: continue bot.say("{0}.{1} = {2}".format( node.get('hostname', '?-' + target_name), key, node[key])) @willie.module.commands('info') def ffpb_peerinfo(bot, trigger): """Show information of the given node.""" # identify node or bail out target_name = trigger.group(2) node = ffpb_findnode_from_botparam(bot, target_name) if node is None: return output = [] # read node information info_mac = node.get('network', {}).get('mac', '??:??:??:??:??:??') info_id = node.get('node_id', info_mac.replace(':', '')) info_name = node.get('hostname', '?-' + info_id) output.append("[" + info_name + "]") if "hardware" in node: model = node["hardware"] output.append("model='" + model + "'") if "software" in node: if "firmware" in node["software"]: output.append("firmware=" + str(node["software"]["firmware"])) if "autoupdater" in node["software"]: autoupdater = node["software"]["autoupdater"] output.append("(autoupdater="+autoupdater+")") uptime = node.get('uptime', -1) if uptime > 0: days, rem_d = divmod(uptime, 86400) hours, rem_h = divmod(rem_d, 3600) minutes, _ = divmod(rem_h, 60) if days > 0: output.append('up {0}d {1}h'.format(days, hours)) elif hours > 0: output.append('up {0}h {1}m'.format(hours, minutes)) else: output.append('up {0}m'.format(minutes)) clientcount = node.get('clientcount') if not clientcount is None: clientcount = int(clientcount) output.append('clients={0}'.format(clientcount)) nodestatus = node.get('status', 'unknown') if nodestatus != 'active': output.append("[" + nodestatus.upper() + "]") bot.say(str.join(" ", output)) @willie.module.commands('last-seen') @willie.module.commands('last_seen') @willie.module.commands('lastseen') def ffpb_lastseen(bot, trigger): """Display when the given node has last been seen.""" # identify node or bail out target_name = trigger.group(2) node = ffpb_findnode_from_botparam(bot, target_name) if node is None: return node_name = node.get('hostname') last_seen = node.get('__UPDATED__') if last_seen is not None: a_value = int(last_seen.get('alfred')) b_value = int(last_seen.get('batadv')) else: a_value = b_value = None a_delta = time.time() - a_value if a_value is not None else None b_delta = time.time() - b_value if b_value is not None else None if a_value is None and b_value is None: bot.say('{0} wurde offenbar noch gar nicht gesehen?'.format(node_name)) return if a_delta < 30 and b_delta < 30: bot.say('{0} wurde gerade eben gesehen.'.format(node_name)) return if a_value is not None and b_value is not None and \ abs(a_value - b_value) < 60: bot.say('{0} wurde zuletzt gesehen: {1}'.format( node_name, pretty_date((a_value + b_value) / 2))) else: bot.say('{0} wurde zuletzt gesehen: {1} (ALFRED,) bzw. {2} (BATMAN)'.format( node_name, pretty_date(a_value) if not a_value is None else "nie", pretty_date(b_value) if not b_value is None else "nie" )) @willie.module.commands('uptime') def ffpb_peeruptime(bot, trigger): """Display the uptime of the given node.""" # identify node or bail out target_name = trigger.group(2) node = ffpb_findnode_from_botparam(bot, target_name) if node is None: return # get name and raw uptime from node info_name = node["hostname"] info_uptime = '' u_raw = None if 'statistics' in node and 'uptime' in node['statistics']: u_raw = node['statistics']['uptime'] elif 'uptime' in node: u_raw = node['uptime'] # pretty print uptime if not u_raw is None: uptime = int(float(u_raw)) days, rem_d = divmod(uptime, 86400) hours, rem_h = divmod(rem_d, 3600) minutes, _ = divmod(rem_h, 60) if days > 0: info_uptime += '{0}d '.format(days) if hours > 0: info_uptime += '{0}h '.format(hours) info_uptime += '{0}m'.format(minutes) info_uptime += ' # raw: \'{0}\''.format(u_raw) else: info_uptime += '?' # reply to user bot.say('uptime(\'{0}\') = {1}'.format(info_name, info_uptime)) @willie.module.commands('link') def ffpb_peerlink(bot, trigger): """Display MAC and link to statuspage for the given node.""" # identify node or bail out target_name = trigger.group(2) node = ffpb_findnode_from_botparam(bot, target_name) if node is None: return # get node's MAC info_mac = node.get('mac') info_name = node.get('hostname') # get node's v6 address in the mesh (derived from MAC address) info_v6 = mac2ipv6(info_mac, 'fdca:ffee:ff12:132:') # reply to user bot.say('[{1}] mac {0} -> http://[{2}]/'.format( info_mac, info_name, info_v6))