Issue orders periodically.
authorCMDR furrycat <elite@furrycat.net>
Fri, 30 Sep 2016 11:56:27 +0000 (12:56 +0100)
committerCMDR furrycat <elite@furrycat.net>
Fri, 30 Sep 2016 12:23:06 +0000 (13:23 +0100)
bot.py

diff --git a/bot.py b/bot.py
index 1b7c1d7..2ba63bf 100755 (executable)
--- a/bot.py
+++ b/bot.py
@@ -2,6 +2,7 @@
 
 import asyncio
 import bs4
+import datetime
 import discord
 import feedparser
 import hashlib
@@ -55,6 +56,9 @@ bots = {
     ],
     'greetings': [
       { 'channel': 222685317885329408, 'message': 'Welcome to Delta Squadron, take a look at #delta_rules and make yourself at home in the public lobby. If interested in joining please PM a member of the High Command or Council for assistance', 'voice': 222103336483028993, 'sound': 'meow.wav' }
+    ],
+    'orders': [
+      { 'channel': 222071904029114371, 'message': '**\\* DELTA SQUADRON GENERAL ORDERS \\***\n\\* 30 SEPT 3302 \\*\nNon-combat missions - TOMANI\nSave all Delta bounties until Sunday evening and then hand in at Tomani\n**\\* END TRANSMISSION \\***', 'seconds': 43200 }
     ]
   },
   # catbot beta
@@ -67,11 +71,15 @@ bots = {
     'greetings': [
       { 'channel': 225217541922881538, 'message': 'Welcome to Catbot', 'voice': 231296897938227201, 'sound': 'meow.wav' }
     ],
+    'orders': [
+      { 'channel': 231374099765657600, 'message': '**\\* DELTA SQUADRON GENERAL ORDERS \\***\n\\* 30 SEPT 3302 \\*\nNon-combat missions - TOMANI\nSave all Delta bounties until Sunday evening and then hand in at Tomani\n**\\* END TRANSMISSION \\***', 'seconds': 43200 }
+    ]
   }
 }
 
 feeds = []
 greetings = []
+orders = []
 
 def open_url(url):
   if sys.version_info >= (3, 0):
@@ -545,6 +553,52 @@ def do_feeds(feeds):
     yield from asyncio.sleep(rsstime.value)
 
 @asyncio.coroutine
+def give_order(order, digest = None):
+  channel = client.get_channel(str(order['channel']))
+  if channel is None:
+    log.warning("Can't get channel for order {}".format(order['message']))
+    return
+
+  # @everyone mention mangles the digest
+  text = order['message']
+  if digest is None:
+    digest = hashlib.sha224(text.encode('utf-8')).hexdigest()
+  text = '@everyone\n{}'.format(text)
+
+  cutoff = datetime.datetime.utcnow() - datetime.timedelta(0, order['seconds'])
+  logs = yield from client.logs_from(channel, after = cutoff)
+  for message in logs:
+    raw = re.sub(r'^@everyone\s', '', message.content).strip()
+    if hashlib.sha224(raw.encode('utf-8')).hexdigest() == digest:
+      log.debug('Saw previously posted order with digest {}'.format(digest))
+      return
+
+  try:
+    if dryrun:
+      log.info('Dryrun: Not posting to {}: {}'.format(channel, text))
+    else:
+      log.info('Posting to {}: {}'.format(channel, text))
+      yield from say(channel, text)
+  except:
+    pass
+
+@asyncio.coroutine
+def do_orders(orders):
+  while True:
+    waittime = None
+    given = {}
+    now = time.time()
+    for order in orders:
+      if waittime is None or waittime > order['seconds']:
+        waittime = order['seconds']
+      digest = hashlib.sha224(order['message'].encode('utf-8')).hexdigest()
+      when = given[digest] if digest in given else None
+      if when is None or when < now - order['seconds']:
+        yield from give_order(order, digest)
+        given[digest] = now
+    yield from asyncio.sleep(waittime)
+
+@asyncio.coroutine
 def maybe_sleep():
   while True:
     if status() != discord.Status.idle:
@@ -692,6 +746,7 @@ def on_ready():
   if bot is not None:
     feeds = bot.get('feeds', [])
     greetings = bot.get('greetings', [])
+    orders = bot.get('orders', [])
   print('Admins are: {}'.format(admins))
   yield from wake_up(True)
   channels = yield from channels_to_greet()
@@ -710,6 +765,8 @@ def on_ready():
     yield from set_unassigned(member)
   print('RSS feeds: {}'.format([feed['description'] for feed in feeds if 'description' in feed]))
   asyncio.async(do_feeds(feeds))
+  print('Orders in {}'.format([channel.name for channel in filter(None, [client.get_channel(str(order['channel'])) for order in orders])]))
+  asyncio.async(do_orders(orders))
   asyncio.async(maybe_sleep())
 
 def mentioned_in(message, explicit = True):