|
@@ -23,13 +23,10 @@ import threading
|
|
|
|
|
|
msgserver = None
|
|
|
peers_repo = None
|
|
|
-highscores = None
|
|
|
|
|
|
nodeaccess = None
|
|
|
|
|
|
alfred_method = None
|
|
|
-alfred_data = None
|
|
|
-alfred_update = datetime.datetime(1970,1,1,23,42)
|
|
|
|
|
|
ffpb_resolver = dns.resolver.Resolver ()
|
|
|
ffpb_resolver.nameservers = ['10.132.254.53']
|
|
@@ -75,20 +72,11 @@ class ThreadingTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
|
|
|
pass
|
|
|
|
|
|
def setup(bot):
|
|
|
- global msgserver, peers_repo, alfred_method, highscores, nodeaccess
|
|
|
+ global msgserver, peers_repo, alfred_method, nodeaccess
|
|
|
|
|
|
# signal begin of setup routine
|
|
|
bot.memory['ffpb_in_setup'] = True
|
|
|
|
|
|
- # load highscores from disk
|
|
|
- highscores = shelve.open('highscoredata', writeback=True)
|
|
|
- if not 'nodes' in highscores:
|
|
|
- highscores['nodes'] = 0
|
|
|
- highscores['nodes_ts'] = time.time()
|
|
|
- if not 'clients' in highscores:
|
|
|
- highscores['clients'] = 0
|
|
|
- highscores['clients_ts'] = time.time()
|
|
|
-
|
|
|
# load list of seen nodes from disk
|
|
|
seen_nodes = shelve.open('nodes.seen', writeback=True)
|
|
|
bot.memory['seen_nodes'] = seen_nodes
|
|
@@ -124,19 +112,17 @@ def setup(bot):
|
|
|
|
|
|
# initially fetch ALFRED data
|
|
|
alfred_method = bot.config.ffpb.alfred_method
|
|
|
+ if not 'alfred_data' in bot.memory:
|
|
|
+ bot.memory['alfred_data'] = {}
|
|
|
+ if not 'alfred_update' in bot.memory:
|
|
|
+ bot.memory['alfred_update'] = datetime.datetime(1970,1,1,23,42)
|
|
|
ffpb_updatealfred(bot)
|
|
|
|
|
|
# signal end of setup routine
|
|
|
bot.memory['ffpb_in_setup'] = False
|
|
|
|
|
|
def shutdown(bot):
|
|
|
- global msgserver, highscores, nodeaccess
|
|
|
-
|
|
|
- # store highscores
|
|
|
- if not highscores is None:
|
|
|
- highscores.sync()
|
|
|
- highscores.close()
|
|
|
- highscores = None
|
|
|
+ global msgserver, nodeaccess
|
|
|
|
|
|
# store node acl
|
|
|
if not nodeaccess is None:
|
|
@@ -337,7 +323,7 @@ def ffpb_ensurenodeid(nodedata):
|
|
|
|
|
|
return result
|
|
|
|
|
|
-def ffpb_findnode(name):
|
|
|
+def ffpb_findnode(name, alfred_data = None):
|
|
|
"""helper: try to identify the node the user meant by the given name"""
|
|
|
|
|
|
# no name, no node
|
|
@@ -348,41 +334,42 @@ def ffpb_findnode(name):
|
|
|
|
|
|
names = {}
|
|
|
|
|
|
- # try to match MAC
|
|
|
- m = re.search("^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$", name)
|
|
|
- if (not m is None):
|
|
|
- mac = m.group(0).lower()
|
|
|
- if mac in alfred_data:
|
|
|
- return ffpb_ensurenodeid(alfred_data[mac])
|
|
|
+ if not alfred_data is None:
|
|
|
+ # try to match MAC
|
|
|
+ m = re.search("^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$", name)
|
|
|
+ if (not m is None):
|
|
|
+ mac = m.group(0).lower()
|
|
|
+ if mac in alfred_data:
|
|
|
+ return ffpb_ensurenodeid(alfred_data[mac])
|
|
|
+
|
|
|
+ # try to find alias MAC in ALFRED data
|
|
|
+ for nodeid in alfred_data:
|
|
|
+ node = alfred_data[nodeid]
|
|
|
+ if "network" in node:
|
|
|
+ if "mac" in node["network"] and node["network"]["mac"].lower() == mac:
|
|
|
+ return ffpb_ensurenodeid(node)
|
|
|
+ if "mesh_interfaces" in node["network"]:
|
|
|
+ for mim in node["network"]["mesh_interfaces"]:
|
|
|
+ if mim.lower() == mac:
|
|
|
+ return ffpb_ensurenodeid(node)
|
|
|
+
|
|
|
+ nodeid = mac.replace(':','').lower()
|
|
|
+ return {
|
|
|
+ 'nodeid': nodeid,
|
|
|
+ 'hostname': '?-' + nodeid,
|
|
|
+ 'network': { 'addresses': [ mac2ipv6(mac, 'fdca:ffee:ff12:132:') ], 'mac': mac, },
|
|
|
+ 'hardware': { 'model': 'derived-from-mac' },
|
|
|
+ }
|
|
|
|
|
|
- # try to find alias MAC in ALFRED data
|
|
|
+ # look through the ALFRED peers
|
|
|
for nodeid in alfred_data:
|
|
|
node = alfred_data[nodeid]
|
|
|
- if "network" in node:
|
|
|
- if "mac" in node["network"] and node["network"]["mac"].lower() == mac:
|
|
|
- return ffpb_ensurenodeid(node)
|
|
|
- if "mesh_interfaces" in node["network"]:
|
|
|
- for mim in node["network"]["mesh_interfaces"]:
|
|
|
- if mim.lower() == mac:
|
|
|
- return ffpb_ensurenodeid(node)
|
|
|
-
|
|
|
- nodeid = mac.replace(':','').lower()
|
|
|
- return {
|
|
|
- 'nodeid': nodeid,
|
|
|
- 'hostname': '?-' + nodeid,
|
|
|
- 'network': { 'addresses': [ mac2ipv6(mac, 'fdca:ffee:ff12:132:') ], 'mac': mac, },
|
|
|
- 'hardware': { 'model': 'derived-from-mac' },
|
|
|
- }
|
|
|
-
|
|
|
- # look through the ALFRED peers
|
|
|
- for nodeid in alfred_data:
|
|
|
- node = alfred_data[nodeid]
|
|
|
- if 'hostname' in node:
|
|
|
- h = node['hostname']
|
|
|
- if h.lower() == name.lower():
|
|
|
- return node
|
|
|
- else:
|
|
|
- names[h] = nodeid
|
|
|
+ if 'hostname' in node:
|
|
|
+ h = node['hostname']
|
|
|
+ if h.lower() == name.lower():
|
|
|
+ return node
|
|
|
+ else:
|
|
|
+ names[h] = nodeid
|
|
|
|
|
|
# not found in ALFRED data -> try peers_repo
|
|
|
if not peers_repo is None:
|
|
@@ -412,11 +399,12 @@ def ffpb_findnode(name):
|
|
|
}
|
|
|
|
|
|
# do a similar name lookup in the ALFRED data
|
|
|
- possibilities = difflib.get_close_matches(name, [ x for x in names ], cutoff=0.75)
|
|
|
- print('findnode: Fuzzy matching \'{0}\' got {1} entries: {2}'.format(name, len(possibilities), ', '.join(possibilities)))
|
|
|
- if len(possibilities) == 1:
|
|
|
- # if we got exactly one candidate that might be it
|
|
|
- return ffpb_ensurenodeid(alfred_data[names[possibilities[0]]])
|
|
|
+ if not alfred_data is None:
|
|
|
+ possibilities = difflib.get_close_matches(name, [ x for x in names ], cutoff=0.75)
|
|
|
+ print('findnode: Fuzzy matching \'{0}\' got {1} entries: {2}'.format(name, len(possibilities), ', '.join(possibilities)))
|
|
|
+ if len(possibilities) == 1:
|
|
|
+ # if we got exactly one candidate that might be it
|
|
|
+ return ffpb_ensurenodeid(alfred_data[names[possibilities[0]]])
|
|
|
|
|
|
# none of the above was able to identify the requested node
|
|
|
return None
|
|
@@ -428,15 +416,13 @@ def ffpb_findnode_from_botparam(bot, name, ensure_recent_alfreddata = True):
|
|
|
if not bot is None: bot.reply("Grün.")
|
|
|
return None
|
|
|
|
|
|
+ alfred_data = get_alfred_data(bot, ensure_recent_alfreddata)
|
|
|
if ensure_recent_alfreddata and alfred_data is None:
|
|
|
- if not bot is None: bot.say("Informationen sind ausverkauft, kommen erst morgen wieder rein.")
|
|
|
- return None
|
|
|
-
|
|
|
- if ensure_recent_alfreddata and ffpb_alfred_data_outdated():
|
|
|
- if not bot is None: bot.say("Ich habe gerade keine aktuellen Informationen, daher sage ich mal lieber nichts zu '" + name + "'.")
|
|
|
+ if not bot is None:
|
|
|
+ bot.say("Informationen sind ausverkauft bzw. veraltet, daher sage ich mal lieber nichts zu '" + name + "'.")
|
|
|
return None
|
|
|
|
|
|
- node = ffpb_findnode(name)
|
|
|
+ node = ffpb_findnode(name, alfred_data)
|
|
|
if node is None:
|
|
|
if not bot is None: bot.say("Kein Plan wer oder was mit '" + name + "' gemeint ist :(")
|
|
|
|
|
@@ -454,7 +440,6 @@ def mac2ipv6(mac, prefix=None):
|
|
|
@willie.module.interval(30)
|
|
|
def ffpb_updatealfred(bot):
|
|
|
"""Aktualisiere ALFRED-Daten"""
|
|
|
- global alfred_data, alfred_update
|
|
|
|
|
|
if alfred_method is None or alfred_method == "None":
|
|
|
return
|
|
@@ -478,12 +463,14 @@ def ffpb_updatealfred(bot):
|
|
|
try:
|
|
|
alfred_data = json.load(rawdata)
|
|
|
#print("Fetched new ALFRED data:", len(alfred_data), "entries")
|
|
|
- alfred_update = updated
|
|
|
|
|
|
except ValueError as e:
|
|
|
print("Failed to parse ALFRED data: " + str(e))
|
|
|
return
|
|
|
|
|
|
+ bot.memory['alfred_data'] = alfred_data
|
|
|
+ bot.memory['alfred_update'] = updated
|
|
|
+
|
|
|
seen_nodes = bot.memory['seen_nodes'] if 'seen_nodes' in bot.memory else None
|
|
|
if not seen_nodes is None:
|
|
|
new = []
|
|
@@ -518,13 +505,23 @@ def ffpb_updatealfred(bot):
|
|
|
action_target = bot.config.ffpb.msg_target
|
|
|
bot.msg(action_target, '\x01ACTION %s\x01' % action_msg)
|
|
|
|
|
|
-def ffpb_alfred_data_outdated():
|
|
|
- """Check if the stored alfred_data has been updated more than 5 minutes ago."""
|
|
|
+def get_alfred_data(bot, ensure_not_outdated=True):
|
|
|
+ """Retrieves the stored alfred_data and optionally checks that it has been updated no more than 5 minutes ago."""
|
|
|
|
|
|
- timeout = datetime.datetime.now() - datetime.timedelta(minutes=5)
|
|
|
- is_outdated = timeout > alfred_update
|
|
|
- #print("ALFRED outdated? {0} (timeout={1} vs. lastupdate={2})".format(is_outdated, timeout, alfred_update))
|
|
|
- return is_outdated
|
|
|
+ alfred_data = bot.memory['alfred_data'] if 'alfred_data' in bot.memory else None
|
|
|
+ alfred_update = bot.memory['alfred_update'] if 'alfred_update' in bot.memory else 0
|
|
|
+
|
|
|
+ if alfred_data is None:
|
|
|
+ return None
|
|
|
+
|
|
|
+ if ensure_not_outdated:
|
|
|
+ timeout = datetime.datetime.now() - datetime.timedelta(minutes=5)
|
|
|
+ is_outdated = timeout > alfred_update
|
|
|
+ #print("ALFRED outdated? {0} (timeout={1} vs. lastupdate={2})".format(is_outdated, timeout, alfred_update))
|
|
|
+ if is_outdated:
|
|
|
+ return None
|
|
|
+
|
|
|
+ return alfred_data
|
|
|
|
|
|
def ffpb_get_batcave_nodefield(nodeid, field):
|
|
|
"""Query the given field for the given nodeid from the BATCAVE."""
|
|
@@ -552,141 +549,11 @@ def ffpb_debug_alfred(bot, trigger):
|
|
|
if not playitsafe(bot, trigger, botadmin=True, via_privmsg=True):
|
|
|
return
|
|
|
|
|
|
+ alfred_data = get_alfred_data(bot)
|
|
|
if alfred_data is None:
|
|
|
bot.say("Keine ALFRED-Daten vorhanden.")
|
|
|
else:
|
|
|
- bot.say("ALFRED Daten: count={0} lastupdate={1}".format(len(alfred_data), alfred_update))
|
|
|
-
|
|
|
-@willie.module.commands('alfred-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, need_op=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:
|
|
|
- if key in [ 'hostname' ]: continue
|
|
|
- bot.say("{0}.{1} = {2}".format(node['hostname'], key, str(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
|
|
|
-
|
|
|
- # read node information
|
|
|
- info_mac = node['network']['mac'] if 'network' in node and 'mac' in node['network'] else '??:??:??:??:??:??'
|
|
|
- info_id = node['node_id'] if 'node_id' in node else info_mac.replace(':','')
|
|
|
- info_name = node['hostname'] if 'hostname' in node else '?-' + info_id
|
|
|
-
|
|
|
- info_hw = ""
|
|
|
- if "hardware" in node:
|
|
|
- if "model" in node["hardware"]:
|
|
|
- model = node["hardware"]["model"]
|
|
|
- info_hw = " model='" + model + "'"
|
|
|
-
|
|
|
- info_fw = ""
|
|
|
- info_update = ""
|
|
|
- if "software" in node:
|
|
|
- if "firmware" in node["software"]:
|
|
|
- fwinfo = str(node["software"]["firmware"]["release"]) if "release" in node["software"]["firmware"] else "unknown"
|
|
|
- info_fw = " firmware=" + fwinfo
|
|
|
-
|
|
|
- if "autoupdater" in node["software"]:
|
|
|
- autoupdater = node["software"]["autoupdater"]["branch"] if node["software"]["autoupdater"]["enabled"] else "off"
|
|
|
- info_update = " (autoupdater="+autoupdater+")"
|
|
|
-
|
|
|
- info_uptime = ""
|
|
|
- u = -1
|
|
|
- if "statistics" in node and "uptime" in node["statistics"]:
|
|
|
- u = int(float(node["statistics"]["uptime"]))
|
|
|
- elif 'uptime' in node:
|
|
|
- u = int(float(node['uptime']))
|
|
|
-
|
|
|
- if u > 0:
|
|
|
- d, r1 = divmod(u, 86400)
|
|
|
- h, r2 = divmod(r1, 3600)
|
|
|
- m, s = divmod(r2, 60)
|
|
|
- if d > 0:
|
|
|
- info_uptime = ' up {0}d {1}h'.format(d,h)
|
|
|
- elif h > 0:
|
|
|
- info_uptime = ' up {0}h {1}m'.format(h,m)
|
|
|
- else:
|
|
|
- info_uptime = ' up {0}m'.format(m)
|
|
|
-
|
|
|
- info_clients = ""
|
|
|
- clientcount = ffpb_get_batcave_nodefield(info_id, 'clientcount')
|
|
|
- if not clientcount is None:
|
|
|
- clientcount = int(clientcount)
|
|
|
- info_clients = ' clients={0}'.format(clientcount)
|
|
|
-
|
|
|
- bot.say('[{1}]{2}{3}{4}{5}{6}'.format(info_mac, info_name, info_hw, info_fw, info_update, info_uptime, info_clients))
|
|
|
-
|
|
|
-@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:
|
|
|
- u = int(float(u_raw))
|
|
|
- d, r1 = divmod(u, 86400)
|
|
|
- h, r2 = divmod(r1, 3600)
|
|
|
- m, s = divmod(r2, 60)
|
|
|
- if d > 0:
|
|
|
- info_uptime += '{0}d '.format(d)
|
|
|
- if h > 0:
|
|
|
- info_uptime += '{0}h '.format(h)
|
|
|
- info_uptime += '{0}m'.format(m)
|
|
|
- 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["network"]["mac"]
|
|
|
- info_name = node["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))
|
|
|
+ bot.say("ALFRED Daten: count={0} lastupdate={1}".format(len(alfred_data), bot.memory['alfred_update']))
|
|
|
|
|
|
@willie.module.interval(60)
|
|
|
def ffpb_updatepeers(bot):
|
|
@@ -768,43 +635,6 @@ def ffpb_fetch_stats(bot, url, memoryid):
|
|
|
|
|
|
return (nodes_active, nodes_total, clients_count)
|
|
|
|
|
|
-@willie.module.interval(15)
|
|
|
-def ffpb_get_stats(bot):
|
|
|
- """Fetch current statistics, if the highscore changes signal this."""
|
|
|
-
|
|
|
- (nodes_active, nodes_total, clients_count) = ffpb_fetch_stats(bot, 'http://map.paderborn.freifunk.net/nodes.json', 'ffpb_stats')
|
|
|
-
|
|
|
- highscore_changed = False
|
|
|
- if nodes_active > highscores['nodes']:
|
|
|
- highscores['nodes'] = nodes_active
|
|
|
- highscores['nodes_ts'] = time.time()
|
|
|
- highscore_changed = True
|
|
|
-
|
|
|
- if clients_count > highscores['clients']:
|
|
|
- highscores['clients'] = clients_count
|
|
|
- highscores['clients_ts'] = time.time()
|
|
|
- highscore_changed = True
|
|
|
-
|
|
|
- if highscore_changed:
|
|
|
- print('HIGHSCORE changed: {0} nodes ({1}), {2} clients ({3})'.format(highscores['nodes'], highscores['nodes_ts'], highscores['clients'], highscores['clients_ts']))
|
|
|
- if not (bot.config.ffpb.msg_target is None):
|
|
|
- action_msg = 'notiert sich den neuen Highscore: {0} Knoten ({1}), {2} Clients ({3})'.format(highscores['nodes'], pretty_date(int(highscores['nodes_ts'])), highscores['clients'], pretty_date(int(highscores['clients_ts'])))
|
|
|
- action_target = bot.config.ffpb.msg_target
|
|
|
- if (not bot.config.ffpb.msg_target_public is None):
|
|
|
- action_target = bot.config.ffpb.msg_target_public
|
|
|
- bot.msg(action_target, '\x01ACTION %s\x01' % action_msg)
|
|
|
-
|
|
|
-@willie.module.commands('status')
|
|
|
-def ffpb_status(bot, trigger):
|
|
|
- """State of the network: count of nodes + clients"""
|
|
|
-
|
|
|
- stats = bot.memory['ffpb_stats'] if 'ffpb_stats' in bot.memory else None
|
|
|
- if stats is None:
|
|
|
- bot.say('Uff, kein Plan wo der Zettel ist. Fragst du später nochmal?')
|
|
|
- return
|
|
|
-
|
|
|
- bot.say('Es sind {0} Knoten und ca. {1} Clients online.'.format(stats["nodes_active"], stats["clients"]))
|
|
|
-
|
|
|
def pretty_date(time=False):
|
|
|
"""
|
|
|
Get a datetime object or a int() Epoch timestamp and return a
|
|
@@ -848,73 +678,6 @@ def pretty_date(time=False):
|
|
|
return "vor " + str(day_diff) + " Tagen"
|
|
|
return "am " + compare.strftime('%d.%m.%Y um %H:%M Uhr')
|
|
|
|
|
|
-@willie.module.commands('highscore')
|
|
|
-def ffpb_highscore(bot, trigger):
|
|
|
- bot.say('Highscore: {0} Knoten ({1}), {2} Clients ({3})'.format(
|
|
|
- highscores['nodes'], pretty_date(int(highscores['nodes_ts'])),
|
|
|
- highscores['clients'], pretty_date(int(highscores['clients_ts']))))
|
|
|
-
|
|
|
-@willie.module.commands('rollout-status')
|
|
|
-def ffpb_rolloutstatus(bot, trigger):
|
|
|
- """Display statistic on how many nodes have installed the given firmware version."""
|
|
|
-
|
|
|
- # initialize results dictionary
|
|
|
- result = { }
|
|
|
- skipped = 0
|
|
|
-
|
|
|
- # inform users about changed command parameters
|
|
|
- if not trigger.group(2) is None:
|
|
|
- bot.reply('Dieses Kommando nimmt keinen Parameter mehr an.')
|
|
|
- return
|
|
|
-
|
|
|
- # check each node in ALFRED data
|
|
|
- for nodeid in alfred_data:
|
|
|
- item = alfred_data[nodeid]
|
|
|
- if (not 'software' in item) or (not 'firmware' in item['software']) or (not 'autoupdater' in item['software']):
|
|
|
- skipped+=1
|
|
|
- continue
|
|
|
-
|
|
|
- release = item['software']['firmware']['release']
|
|
|
- branch = item['software']['autoupdater']['branch']
|
|
|
- enabled = item['software']['autoupdater']['enabled']
|
|
|
- if not release in result or result[release] is None:
|
|
|
- result[release] = { 'stable': None, 'testing': None }
|
|
|
- if not branch in result[release] or result[release][branch] is None:
|
|
|
- result[release][branch] = { 'auto': 0, 'manual': 0, 'total': 0 }
|
|
|
-
|
|
|
- result[release][branch]['total'] += 1
|
|
|
- mode = 'auto' if enabled else 'manual'
|
|
|
- result[release][branch][mode] += 1
|
|
|
-
|
|
|
- # respond to user
|
|
|
- releases = sorted([x for x in result])
|
|
|
- for release in releases:
|
|
|
- output = 'Rollout von \'{0}\':'.format(release)
|
|
|
- branches = sorted([x for x in result[release]])
|
|
|
- first = True
|
|
|
- for branch in branches:
|
|
|
- item = result[release][branch]
|
|
|
- if item is None: continue
|
|
|
-
|
|
|
- if not first:
|
|
|
- output += ','
|
|
|
- first = False
|
|
|
-
|
|
|
- total = item['total']
|
|
|
- auto_count = item['auto']
|
|
|
- manual_count = item['manual']
|
|
|
-
|
|
|
- output += ' {2} {0}'.format(branch, total, auto_count, manual_count)
|
|
|
- if manual_count > 0:
|
|
|
- output += ' (+{3} manuell)'.format(branch, total, auto_count, manual_count)
|
|
|
-
|
|
|
- bot.say(output)
|
|
|
-
|
|
|
- # output count of nodes for which the autoupdater's branch and/or
|
|
|
- # firmware version could not be retrieved
|
|
|
- if skipped > 0:
|
|
|
- bot.say('plus {0} Knoten deren Status gerade nicht abfragbar war'.format(skipped))
|
|
|
-
|
|
|
@willie.module.commands('ping')
|
|
|
def ffpb_ping(bot, trigger=None, target_name=None, reply_directly=True):
|
|
|
"""Ping the given node"""
|
|
@@ -944,14 +707,6 @@ def ffpb_ping(bot, trigger=None, target_name=None, reply_directly=True):
|
|
|
if reply_directly: bot.say('Uh oh, irgendwas ist kaputt. Chef, ping result = ' + str(result) + ' - darf ich das essen?')
|
|
|
return None
|
|
|
|
|
|
-@willie.module.commands('providers')
|
|
|
-def ffpb_providers(bot, trigger):
|
|
|
- """Fetch the top 5 providers from BATCAVE."""
|
|
|
-
|
|
|
- providers = json.load(urllib2.urlopen('http://[fdca:ffee:ff12:a255::253]:8888/providers?format=json'))
|
|
|
- providers.sort(key=lambda x: x['count'], reverse=True)
|
|
|
- bot.say('Unsere Top 5 Provider: ' + ', '.join(['{0} ({1:.0f}%)'.format(x['name'], x['percentage']) for x in providers[:5]]))
|
|
|
-
|
|
|
@willie.module.commands('mesh')
|
|
|
def ffpb_nodemesh(bot, trigger):
|
|
|
"""Display mesh partners of the given node."""
|