Check caller shares a server with the object we parse().
authorCMDR furrycat <elite@furrycat.net>
Thu, 2 Mar 2017 11:45:51 +0000 (11:45 +0000)
committerCMDR furrycat <elite@furrycat.net>
Thu, 2 Mar 2017 11:46:10 +0000 (11:46 +0000)
bot.py
plugin/admin/admin.py
plugin/announcements/announcements.py
plugin/developer/developer.py
plugin/faction/faction.py
plugin/feeds/feeds.py
plugin/greetings/greetings.py

diff --git a/bot.py b/bot.py
index 019515f..090fe20 100644 (file)
--- a/bot.py
+++ b/bot.py
@@ -103,8 +103,41 @@ def unparse_seconds(seconds):
     interval += '{}s'.format(seconds)
   return interval
 
-def parse_server(text):
+def shared_with(user, instance):
+  if user is None:
+    return True
+  if user.id == client.user.id:
+    return True
+  if is_admin(user):
+    return True
+
+  if type(instance) == discord.server.Server:
+    servers = [instance]
+  elif type(instance) == discord.user.User:
+    for server in client.servers:
+      if server.get_member(instance.id):
+        servers.append(server)
+  elif type(instance) == discord.channel.Channel:
+    servers = [instance.server]
+  elif type(instance) == discord.role.Role:
+    servers = [instance.server]
+  else:
+    log.warning("Don't know how to check if a {} is known to {}!".format(type(instance), user))
+    return True
+  log.debug("Checking if {} {} is known to {}".format(type(instance), instance, user))
+
+  for server in servers:
+    if server.get_member(user.id):
+      log.debug('Member {} found on server {}'.format(user, server.name))
+      return True
+    else:
+      log.debug('Member {} not on server {}!'.format(user, server.name))
+  return False
+
+def parse_server(text, *, author = None):
   log.debug("Parsing server {}".format(text))
+  if author is None:
+    log.warning('Called parse_server() with no author!')
 
   # id.
   m = re.match(r'^\d+$', text)
@@ -112,22 +145,31 @@ def parse_server(text):
     log.debug("Server ID {}".format(text))
     server = client.get_server(text)
     if server is not None:
-      return server
+      if shared_with(author, server):
+        return server
+      if author is not None:
+        log.warning("User {} isn't on parsed server {}!".format(author, server.name))
 
   for server in client.servers:
     if server.name.lower() == text.lower():
-      return server
+      if shared_with(author, server):
+        return server
+      if author is not None:
+        log.warning("User {} isn't on parsed server {}!".format(author, server.name))
 
   log.warning("Can't find server with name or ID {}".format(text))
   return None
 
-def parse_channel(text, *, text_ok = True, voice_ok = True):
+def parse_channel(text, *, author = None, text_ok = True, voice_ok = True):
   channel_type = '{}, {}'.format('text' if text_ok else 'non-text', 'voice' if voice_ok else 'non-voice')
   log.debug("Parsing {} channel {}".format(channel_type, text))
+  if author is None:
+    log.warning('Called parse_channel() with no author!')
 
   # Private message to user.
   if text == 'private':
     log.warning('Parsed private channel.  Caller should check for private!')
+
     if not text_ok:
       log.warning("Requested voice channel but private channels are text!")
       return None
@@ -150,7 +192,10 @@ def parse_channel(text, *, text_ok = True, voice_ok = True):
     if not voice_ok and channel.type == discord.ChannelType.voice:
       log.warning('Parsed channel {} of wrong type!'.format(channel_id))
       return None
-    return channel
+    if shared_with(author, channel):
+      return channel
+    if author is not None:
+      log.warning("User {} isn't on channel {} server {}!".format(author, channel.name, server.name))
 
   # #name or name.
   if text[0] == '#':
@@ -167,13 +212,18 @@ def parse_channel(text, *, text_ok = True, voice_ok = True):
       if not voice_ok and channel.type == discord.ChannelType.voice:
         log.warning('Parsed channel {} of wrong type!'.format(channel_id))
         continue
-      return channel
+      if shared_with(author, channel):
+        return channel
+      if author is not None:
+        log.warning("User {} isn't on channel {} server {}!".format(author, channel.name, server.name))
 
   log.warning("Can't find {} channel {}!".format(channel_type, text))
   return None
 
-def parse_mention(text, author = None):
+def parse_mention(text, *, author = None):
   log.debug("Parsing mention {}".format(text))
+  if author is None:
+    log.warning('Called parse_mention() with no author!')
 
   # Message author.
   if text == 'me':
@@ -202,7 +252,10 @@ def parse_mention(text, author = None):
       for role in server.roles:
         if role.id == role_id:
           log.info('Parsed role {} as {} on {}.'.format(role_id, role.name, server.name))
-          return '&{}'.format(role_id)
+          if shared_with(author, role):
+            return '&{}'.format(role_id)
+          if author is not None:
+            log.warning("User {} isn't on role {} server {}!".format(author, role.name, server.name))
     log.warning("Can't find role with ID {}!".format(role_id))
     return None
 
@@ -229,7 +282,10 @@ def parse_mention(text, author = None):
       for role in server.roles:
         if role.name.lower() == name:
           log.info('Parsed {} as {} on {}.'.format(name, role.name, server.name))
-          return '&{}'.format(role.id)
+          if shared_with(author, role):
+            return '&{}'.format(role.id)
+          if author is not None:
+            log.warning("User {} isn't on role{} server {}!".format(author, role.name, server.name))
     if m.group(1) != '&':
       log.debug('Member {}.'.format(name))
       parts = name.split('#')
index 9fa84f1..6fb9fc3 100644 (file)
@@ -141,7 +141,7 @@ class Admin(object):
     action, where, who, permission = args[0:4]
     if len(args) > 4:
       text = args[4]
-      channel = bot.parse_channel(text)
+      channel = bot.parse_channel(text, author = message.author)
       if channel is None:
         await bot.say(message.channel, '{}?'.format(text))
         return
@@ -162,12 +162,12 @@ class Admin(object):
       await bot.say(message.channel, '{}?'.format(permission))
       return
 
-    server = bot.parse_server(where)
+    server = bot.parse_server(where, author = message.author)
     if server is None:
       await bot.say(message.channel, '{}?'.format(where))
       return
 
-    parsed = bot.parse_mention(who, message.author)
+    parsed = bot.parse_mention(who, author = message.author)
     if parsed is None:
       await bot.say(message.channel, '{}?'.format(who))
       return
index 3881f4c..baffd89 100644 (file)
@@ -497,7 +497,7 @@ class Announcements(DBConnection):
           parsed['mention'] = None
           ok = True
         elif param:
-          mention = bot.parse_mention(param, message.author)
+          mention = bot.parse_mention(param, author = message.author)
           if mention:
             parsed['mention'] = mention
             ok = True
@@ -523,7 +523,7 @@ class Announcements(DBConnection):
           parsed[k] = 'private'
           ok = True
         elif param:
-          parse = {}
+          parse = { 'author': message.author }
           if arg == 'in':
             parse['voice_ok'] = False
           channel = bot.parse_channel(param, **parse)
@@ -576,17 +576,17 @@ class Announcements(DBConnection):
       else:
         if 'voice_id' in parsed and parsed['voice_id'] == parsed['channel_id']:
           # Voice only.
-          channel = bot.parse_channel(parsed['channel_id'], text_ok = False)
+          channel = bot.parse_channel(parsed['channel_id'], author = message.author, text_ok = False)
         else:
           # Text only.
-          channel = bot.parse_channel(parsed['channel_id'], voice_ok = False)
+          channel = bot.parse_channel(parsed['channel_id'], author = message.author, voice_ok = False)
         if not channel:
           await bot.say(message.channel, 'Invalid channel!')
           return None
         server = channel.server
         parsed['server_id'] = server.id
     elif 'voice_id' in parsed:
-      voice = bot.parse_channel(parsed['voice_id'], text_ok = False)
+      voice = bot.parse_channel(parsed['voice_id'], author = message.author, text_ok = False)
       if not voice:
         await bot.say(message.channel, 'Invalid voice channel!')
         return None
index 3d23072..9f1a45f 100644 (file)
@@ -91,7 +91,7 @@ class Developer(object):
 
   @asyncio.coroutine
   def get_message(self, message, channel_id, message_id):
-    channel = bot.parse_channel(channel_id, voice_ok = False)
+    channel = bot.parse_channel(channel_id, author = message.author, voice_ok = False)
     if not channel:
       yield from bot.say(message.channel, 'Channel?')
       return None
index 001cc6f..7fdeebb 100644 (file)
@@ -449,7 +449,7 @@ class Faction(DBConnection):
           parsed['server_id'] = 'private'
           ok = True
         elif param:
-          channel = bot.parse_channel(param, voice_ok = False)
+          channel = bot.parse_channel(param, author = message.author, voice_ok = False)
           if channel is not None:
             parsed[k] = channel.id
             parsed['server_id'] = channel.server.id
index 5aa717e..5546344 100644 (file)
@@ -425,7 +425,7 @@ class Feeds(DBConnection):
           parsed['mention'] = None
           ok = True
         elif param:
-          mention = bot.parse_mention(param, message.author)
+          mention = bot.parse_mention(param, author = message.author)
           if mention:
             parsed['mention'] = mention
             ok = True
@@ -440,7 +440,7 @@ class Feeds(DBConnection):
               log.warning('Requested feed to private channel!')
               break
           else:
-            channel = bot.parse_channel(param, voice_ok = False)
+            channel = bot.parse_channel(param, author = message.author, voice_ok = False)
           if channel is not None:
             parsed[k] = channel.id
             ok = True
index 4833900..b7cdd94 100644 (file)
@@ -239,10 +239,10 @@ class Greetings(DBConnection):
           log.warning("Can't greet in private channel.")
           break
         elif param:
-          args = {}
+          parse = { 'author': message.author }
           if arg == 'in':
-            args['voice_ok'] = False
-          channel = bot.parse_channel(param, **args)
+            parse['voice_ok'] = False
+          channel = bot.parse_channel(param, **parse)
           if channel is not None:
             parsed[k] = channel.id
             ok = True