ffpb_nodeinfo.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. # -*- coding: utf-8 -*-
  2. from __future__ import print_function
  3. import time
  4. import willie
  5. from ffpb import \
  6. ffpb_findnode_from_botparam, \
  7. mac2ipv6, playitsafe, pretty_date
  8. from batcave import BatcaveClient
  9. __batcave = None
  10. def setup(bot):
  11. """Called by willie upon loading this plugin."""
  12. global __batcave, highscores
  13. __batcave = BatcaveClient(bot.config.ffpb.batcave_url)
  14. pass
  15. def shutdown(bot):
  16. """Called by willie upon unloading this plugin."""
  17. pass
  18. @willie.module.commands('identify')
  19. def ffpb_identify(bot, trigger):
  20. """Identify node."""
  21. # query must be as OP in the channel
  22. if not playitsafe(bot, trigger, via_channel=True, need_op=True):
  23. # the check function already gives a bot reply, just exit here
  24. return
  25. ident = trigger.group(2)
  26. result = __batcave.identify(ident)
  27. if result is None:
  28. bot.say('Mist, ich erreiche den Detektiv nicht.')
  29. return
  30. if not ident in result:
  31. bot.say('Mein Detektiv hat getrunken und erzählt Blödsinn.')
  32. return
  33. if len(result[ident]) == 0:
  34. bot.say('Trotz intensivster Recherche habe ich zu "%s" nix gefunden :/' % ident)
  35. elif len(result[ident]) == 1:
  36. bot.say('Glasklar, "%s" wurde identifiziert: %s' % (ident, result[ident][0]))
  37. else:
  38. bot.say('Hm, zu "%s" gibt es mehrere Möglichkeiten: %s' % (ident, str.join(', ', result[ident])))
  39. @willie.module.commands('raw-data')
  40. def ffpb_peerdata(bot, trigger):
  41. """Show ALFRED data of the given node."""
  42. # identify node or bail out
  43. target_name = trigger.group(2)
  44. node = ffpb_findnode_from_botparam(bot, target_name)
  45. if node is None:
  46. return
  47. # query must be a PM or as OP in the channel
  48. if not playitsafe(bot, trigger, via_privmsg=True, node=node):
  49. # the check function already gives a bot reply, just exit here
  50. return
  51. # reply each key in the node's data
  52. for key in node:
  53. # skip some fields
  54. if key in ['hostname']:
  55. continue
  56. bot.say("{0}.{1} = {2}".format(
  57. node.get('hostname', '?-' + target_name),
  58. key, node[key]))
  59. @willie.module.commands('info')
  60. def ffpb_peerinfo(bot, trigger):
  61. """Show information of the given node."""
  62. # identify node or bail out
  63. target_name = trigger.group(2)
  64. node = ffpb_findnode_from_botparam(bot, target_name)
  65. if node is None:
  66. return
  67. output = []
  68. # read node information
  69. info_mac = node.get('network', {}).get('mac', '??:??:??:??:??:??')
  70. info_id = node.get('node_id', info_mac.replace(':', ''))
  71. info_name = node.get('hostname', '?-' + info_id)
  72. output.append("[" + info_name + "]")
  73. if "hardware" in node:
  74. model = node["hardware"]
  75. output.append("model='" + model + "'")
  76. if "software" in node:
  77. if "firmware" in node["software"]:
  78. output.append("firmware=" + str(node["software"]["firmware"]))
  79. if "autoupdater" in node["software"]:
  80. autoupdater = node["software"]["autoupdater"]
  81. output.append("(autoupdater="+autoupdater+")")
  82. uptime = node.get('uptime', -1)
  83. if uptime > 0:
  84. days, rem_d = divmod(uptime, 86400)
  85. hours, rem_h = divmod(rem_d, 3600)
  86. minutes, _ = divmod(rem_h, 60)
  87. if days > 0:
  88. output.append('up {0}d {1}h'.format(days, hours))
  89. elif hours > 0:
  90. output.append('up {0}h {1}m'.format(hours, minutes))
  91. else:
  92. output.append('up {0}m'.format(minutes))
  93. clientcount = node.get('clientcount')
  94. if not clientcount is None:
  95. clientcount = int(clientcount)
  96. output.append('clients={0}'.format(clientcount))
  97. nodestatus = node.get('status', 'unknown')
  98. if nodestatus != 'active':
  99. output.append("[" + nodestatus.upper() + "]")
  100. bot.say(str.join(" ", output))
  101. @willie.module.commands('last-seen')
  102. @willie.module.commands('last_seen')
  103. @willie.module.commands('lastseen')
  104. def ffpb_lastseen(bot, trigger):
  105. """Display when the given node has last been seen."""
  106. # identify node or bail out
  107. target_name = trigger.group(2)
  108. node = ffpb_findnode_from_botparam(bot, target_name)
  109. if node is None:
  110. return
  111. node_name = node.get('hostname')
  112. last_seen = node.get('__UPDATED__')
  113. if last_seen is not None:
  114. a_value = int(last_seen.get('alfred'))
  115. b_value = int(last_seen.get('batadv'))
  116. else:
  117. a_value = b_value = None
  118. a_delta = time.time() - a_value if a_value is not None else None
  119. b_delta = time.time() - b_value if b_value is not None else None
  120. if a_value is None and b_value is None:
  121. bot.say('{0} wurde offenbar noch gar nicht gesehen?'.format(node_name))
  122. return
  123. if a_delta < 30 and b_delta < 30:
  124. bot.say('{0} wurde gerade eben gesehen.'.format(node_name))
  125. return
  126. if a_value is not None and b_value is not None and \
  127. abs(a_value - b_value) < 60:
  128. bot.say('{0} wurde zuletzt gesehen: {1}'.format(
  129. node_name,
  130. pretty_date((a_value + b_value) / 2)))
  131. else:
  132. bot.say('{0} wurde zuletzt gesehen: {1} (ALFRED,) bzw. {2} (BATMAN)'.format(
  133. node_name,
  134. pretty_date(a_value) if not a_value is None else "nie",
  135. pretty_date(b_value) if not b_value is None else "nie"
  136. ))
  137. @willie.module.commands('uptime')
  138. def ffpb_peeruptime(bot, trigger):
  139. """Display the uptime of the given node."""
  140. # identify node or bail out
  141. target_name = trigger.group(2)
  142. node = ffpb_findnode_from_botparam(bot, target_name)
  143. if node is None:
  144. return
  145. # get name and raw uptime from node
  146. info_name = node["hostname"]
  147. info_uptime = ''
  148. u_raw = None
  149. if 'statistics' in node and 'uptime' in node['statistics']:
  150. u_raw = node['statistics']['uptime']
  151. elif 'uptime' in node:
  152. u_raw = node['uptime']
  153. # pretty print uptime
  154. if not u_raw is None:
  155. uptime = int(float(u_raw))
  156. days, rem_d = divmod(uptime, 86400)
  157. hours, rem_h = divmod(rem_d, 3600)
  158. minutes, _ = divmod(rem_h, 60)
  159. if days > 0:
  160. info_uptime += '{0}d '.format(days)
  161. if hours > 0:
  162. info_uptime += '{0}h '.format(hours)
  163. info_uptime += '{0}m'.format(minutes)
  164. info_uptime += ' # raw: \'{0}\''.format(u_raw)
  165. else:
  166. info_uptime += '?'
  167. # reply to user
  168. bot.say('uptime(\'{0}\') = {1}'.format(info_name, info_uptime))
  169. @willie.module.commands('link')
  170. def ffpb_peerlink(bot, trigger):
  171. """Display MAC and link to statuspage for the given node."""
  172. # identify node or bail out
  173. target_name = trigger.group(2)
  174. node = ffpb_findnode_from_botparam(bot, target_name)
  175. if node is None:
  176. return
  177. # get node's MAC
  178. info_mac = node.get('mac')
  179. info_name = node.get('hostname')
  180. # get node's v6 address in the mesh (derived from MAC address)
  181. info_v6 = mac2ipv6(info_mac, 'fdca:ffee:ff12:132:')
  182. # reply to user
  183. bot.say('[{1}] mac {0} -> http://[{2}]/'.format(
  184. info_mac, info_name, info_v6))