123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- # -*- coding: utf-8 -*-
- from __future__ import print_function
- import willie
- import json
- import shelve
- import time
- import urllib2
- from ffpb import pretty_date
- from batcave import BatcaveClient
- __batcave = None
- highscores = None
- def setup(bot):
- """Called by willie upon loading this plugin."""
- global __batcave, highscores
- __batcave = BatcaveClient(bot.config.ffpb.batcave_url)
- # 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()
- def shutdown(bot):
- """Called by willie upon loading this plugin."""
- global highscores
- # store highscores
- if not highscores is None:
- highscores.sync()
- highscores.close()
- highscores = None
- @willie.module.interval(5)
- def ffpb_get_stats(bot):
- """Fetch current statistics, if the highscore changes signal this."""
- status = __batcave.get_status()
- if status is None:
- print('Failed to fetch BATCAVE status.')
- return
- bot.memory['ffpb_stats'] = status
- (nodes_active, clients_count) = \
- (status['nodes_active'], status['clients_unique'])
- nodes_active += status.get('gateways_active', 0)
- 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})'
- 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.format(
- highscores['nodes'], pretty_date(int(highscores['nodes_ts'])),
- highscores['clients'], pretty_date(int(highscores['clients_ts'])),
- ))
- @willie.module.commands('status')
- def ffpb_status(bot, trigger):
- """State of the network: count of nodes + clients"""
- stats = bot.memory.get('ffpb_stats')
- if stats is None:
- bot.say('Uff, kein Plan wo der Zettel ist. Fragst du später nochmal?')
- return
- gwactive = stats.get('gateways_active', 0)
- bot.say('Es sind {0} Knoten (inkl. {1} Gateways) und ca. {2} Clients online.'.format(
- stats["nodes_active"] + gwactive,
- gwactive,
- stats["clients_unique"]))
- @willie.module.commands('raw-status')
- def ffpb_batcave_status(bot, trigger):
- """State as given by BATCAVE."""
- status = __batcave.get_status()
- bot.say('Status: ' + str(json.dumps(status))[1:-1])
- @willie.module.commands('highscore')
- def ffpb_highscore(bot, trigger):
- """Print current highscores (nodes + clients)."""
- 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 which firmware."""
- # initialize results dictionary
- result = {}
- skipped = 0
- arg = trigger.group(2)
- # inform users about changed command parameters
- if arg is not None and arg != 'all':
- bot.reply('Dieses Kommando nimmt keinen Parameter außer \'all\' mehr an.')
- return
- # get all nodes
- nodes = __batcave.get_nodes()
- if nodes is None:
- bot.reply('Hmpf, ich kriege gerade keine Infos. Das ist doch Mist so.')
- return
- offlinenodes = 0
- count_offline = (arg == "all")
- # check each node in ALFRED data
- for item in nodes:
- if (not count_offline) and (item.get('status') not in ['active','stale']):
- offlinenodes += 1
- continue
- release = item.get('firmware')
- branch = item.get('autoupdater')
- enabled = branch != 'off'
- if release is None or branch is None:
- skipped += 1
- continue
- 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
- auto_count = item['auto']
- manual_count = item['manual']
- output += ' {1} {0}'.format(branch, auto_count)
- if manual_count > 0:
- output += ' (+{0} manuell)'.format(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 mit unklarem Status'.format(skipped))
- if not count_offline and offlinenodes > 0:
- bot.say('zudem wurden {0} Knoten ignoriert da sie nicht online sind'.format(offlinenodes))
- @willie.module.commands('providers')
- def ffpb_providers(bot, trigger):
- """Fetch the top 5 providers from BATCAVE."""
- providers = __batcave.get_providers()
- providers.sort(key=lambda x: x['count'], reverse=True)
- top5 = providers[:5]
- top5 = ['{0} ({1:.0f}%)'.format(x['name'], x['percentage']) for x in top5]
- bot.say('Unsere Top 5 Provider: ' + ', '.join(top5))
|