Show summary graph, by default every 30 days.
authorCMDR furrycat <elite@furrycat.net>
Wed, 11 Oct 2017 09:52:47 +0000 (10:52 +0100)
committerCMDR furrycat <elite@furrycat.net>
Wed, 11 Oct 2017 10:10:36 +0000 (11:10 +0100)
plugin/faction/faction.py

index f957ba5..42c9bce 100644 (file)
@@ -50,7 +50,7 @@ class Faction(DBConnection):
 
   def create_tables(self):
     self.open_db()
-    cursor = self.query('create table if not exists factions (id char(36) not null, bot_id varchar(32) not null, member_id varchar(32) not null, server_id varchar(32) not null, channel_id varchar(32), newsflash_channel_id varchar(32), faction_id int not null, name varchar(128) not null, state_id int not null, interval int not null default 86400, updated datetime)')
+    cursor = self.query('create table if not exists factions (id char(36) not null, bot_id varchar(32) not null, member_id varchar(32) not null, server_id varchar(32) not null, channel_id varchar(32), newsflash_channel_id varchar(32), faction_id int not null, name varchar(128) not null, state_id int not null, interval int not null default 86400, summary int default 30, updated datetime, last_spoke datetime)')
     cursor = self.query('create unique index if not exists factions_id on factions (id)')
     cursor = self.query('create index if not exists factions_bot_id on factions (bot_id)')
     cursor = self.query('create table if not exists faction_names (faction_id int not null, name varchar(128) not null)')
@@ -63,7 +63,7 @@ class Faction(DBConnection):
     cursor = self.query('create unique index if not exists faction_influence_checksum on faction_influence (checksum, eddb_id, faction_id)')
     cursor = self.query('create table if not exists faction_trend (checksum char(32) not null, eddb_id int not null, faction_id int not null, state_id int not null, trend int not null, pending boolean)')
     cursor = self.query('create unique index if not exists faction_trend_state on faction_trend (checksum, eddb_id, faction_id, pending)')
-    cursor = self.query('create table if not exists systems (id char(36) not null, bot_id varchar(32) not null, member_id varchar(32) not null, server_id varchar(32) not null, name varchar(128) not null, channel_id varchar(32), newsflash_channel_id varchar(32), eddb_id int not null, interval int not null default 86400, updated datetime)')
+    cursor = self.query('create table if not exists systems (id char(36) not null, bot_id varchar(32) not null, member_id varchar(32) not null, server_id varchar(32) not null, name varchar(128) not null, channel_id varchar(32), newsflash_channel_id varchar(32), eddb_id int not null, interval int not null default 86400, summary int default 30, updated datetime, last_spoke datetime)')
     cursor = self.query('create unique index if not exists systems_id on systems (id)')
     cursor = self.query('create index if not exists systems_bot_id on systems (bot_id)')
     self.dbh.commit()
@@ -79,7 +79,7 @@ class Faction(DBConnection):
 
   def get_tracked_factions(self):
     now = self.now()
-    cursor = self.query("select id, name, server_id, member_id, channel_id, newsflash_channel_id, interval, faction_id, name, state_id, updated from factions where updated is null or updated < ? - interval and bot_id=?", [now, client.user.id])
+    cursor = self.query("select id, name, server_id, member_id, channel_id, newsflash_channel_id, interval, summary, faction_id, name, state_id, updated, last_spoke from factions where updated is null or updated < ? - interval and bot_id=?", [now, client.user.id])
     for row in cursor.fetchall():
       yield TrackedFaction(row)
     self.close_db()
@@ -103,7 +103,7 @@ class Faction(DBConnection):
 
   def get_tracked_systems(self):
     now = self.now()
-    cursor = self.query("select id, name, server_id, member_id, channel_id, newsflash_channel_id, interval, eddb_id, name, updated from systems where updated is null or updated < ? - interval and bot_id=?", [now, client.user.id])
+    cursor = self.query("select id, name, server_id, member_id, channel_id, newsflash_channel_id, interval, summary, eddb_id, name, updated, last_spoke from systems where updated is null or updated < ? - interval and bot_id=?", [now, client.user.id])
     for row in cursor.fetchall():
       yield TrackedSystem(row)
     self.close_db()
@@ -228,8 +228,10 @@ class Faction(DBConnection):
       # Convert to list because we will be sharing the cursor.
       for faction in list(self.get_tracked_factions()):
         await self.report_tracked_faction(faction)
+        await self.show_tracked_faction_summary(faction)
       for system in list(self.get_tracked_systems()):
         await self.report_tracked_system(system)
+        await self.show_tracked_system_summary(system)
 
       await asyncio.sleep(waittime)
 
@@ -469,6 +471,8 @@ class Faction(DBConnection):
     text = '{} track'.format(what)
     if tracked.interval:
       text += ' every {}'.format(bot.unparse_seconds(int(tracked.interval)))
+    if tracked.summary:
+      text += ' summary {}'.format(tracked.summary)
     if tracked.is_private:
       text += ' in private'
     elif tracked.channel_id is not None:
@@ -623,6 +627,62 @@ class Faction(DBConnection):
     await self.report_faction_influence(channel, system_id = tracked.eddb_id, yelp_if_no_data = False)
     await self.report_stale_system_influence(channel, id = tracked.eddb_id)
 
+  async def show_tracked_faction_or_system_summary(self, tracked, what):
+    if what not in ['faction', 'system']:
+      log.error('Can only report faction or system.')
+      return
+
+    if tracked.summary is None:
+      return
+
+    now = self.now()
+    if tracked.last_spoke is not None and (now - tracked.last_spoke) / 86400 < tracked.summary:
+      return
+
+    channel = None
+    channel_id = tracked.newsflash_channel_id if tracked.channel_id is None else tracked.channel_id
+    if tracked.is_private:
+      for server in client.servers:
+        try:
+          member = server.get_member(tracked.member_id)
+          channel = await client.start_private_message(member)
+          break
+        except:
+          log.exception('report_tracked_{}'.format(what))
+    else:
+      channel = client.get_channel(channel_id)
+
+    if channel is None:
+      log.warning("Can't get channel for {} {}".format(what, tracked.id))
+      return
+
+    then = now - 86400 * tracked.summary
+    sql = 'select distinct s.name as system_name from faction_systems s, faction_influence i where s.eddb_id=i.eddb_id and timestamp>=?'
+    params = [then]
+    if what == 'faction':
+      sql += ' and i.faction_id=?'
+      params.append(tracked.faction_id)
+    else:
+      sql += ' and i.eddb_id=?'
+      params.append(tracked.eddb_id)
+    cursor = self.query(sql, params)
+    system_names = [row['system_name'] for row in cursor.fetchall()]
+    self.close_db()
+    if len(system_names):
+      result = await self.graph_faction_history(channel, systems = system_names, start_date = then)
+      if not result:
+        log.warning('Failed summary graph for faction {}'.format(tracked.id))
+        return
+    else:
+      log.info('No systems updated since {} for faction {}'.format(bot.iso8601(then), tracked.name))
+    await self.update_tracked_faction(tracked.id, last_spoke = now)
+
+  async def show_tracked_faction_summary(self, tracked):
+    await self.show_tracked_faction_or_system_summary(tracked, 'faction')
+
+  async def show_tracked_system_summary(self, tracked):
+    await self.show_tracked_system_or_system_summary(tracked, 'system')
+
   async def get_faction(self, destination, name):
     factions = eddb.find_faction(name)
     if not len(factions):
@@ -812,6 +872,13 @@ class Faction(DBConnection):
             break
         else:
           break
+      elif arg == 'summary':
+        if param:
+          try:
+            parsed[arg] = int(param)
+            ok = True
+          except ValueError:
+            log.error('Invalid summary {}'.format(param))
       else:
         if editing and self.is_uuid(arg):
           # UUID missing 'id'.
@@ -888,6 +955,7 @@ class Faction(DBConnection):
     create = await self.parse_faction(message, args)
     if create is None:
       return
+    create['last_spoke'] = self.now()
 
     faction = await self.can_manage_factions(message.author, message.channel, 'create', create = TrackedFaction(create))
     if not faction:
@@ -958,6 +1026,7 @@ class Faction(DBConnection):
     create = await self.parse_system(message, args)
     if create is None:
       return
+    create['last_spoke'] = self.now()
 
     system = await self.can_manage_systems(message.author, message.channel, 'create', create = TrackedSystem(create))
     if not system: