id command to print details of users, roles and channels.
authorCMDR furrycat <elite@furrycat.net>
Tue, 4 Oct 2016 10:16:42 +0000 (11:16 +0100)
committerCMDR furrycat <elite@furrycat.net>
Tue, 4 Oct 2016 10:26:13 +0000 (11:26 +0100)
bot.py

diff --git a/bot.py b/bot.py
index 05f844b..25dde13 100755 (executable)
--- a/bot.py
+++ b/bot.py
@@ -18,6 +18,22 @@ import sys
 import time
 from PIL import Image
 from db import DBConnection
+from enum import Enum
+
+class Identify(Enum):
+  member = 1
+  role = 2
+  channel = 4
+
+  def string(instance):
+    if type(instance) == discord.member.Member:
+      return 'Member'
+    if type(instance) == discord.member.User:
+      return 'User'
+    elif type(instance) == discord.role.Role:
+      return 'Role'
+    elif type(instance) == discord.channel.Channel:
+      return 'Channel'
 
 dryrun = os.getenv('DRYRUN') is not None
 debug = os.getenv('DEBUG') is not None
@@ -264,6 +280,84 @@ def delta_avatar(url):
   return b.getvalue()
 
 @asyncio.coroutine
+def identify(destination, target):
+  do = Identify.member.value | Identify.role.value | Identify.channel.value
+  channel_id = None
+  role_id = None
+  member_id = None
+
+  if target:
+    m = re.match(r'<(@&?|#)(\d+)>', target)
+    if m is not None:
+      target = None
+      prefix = m.group(1)
+      id = m.group(2)
+      if prefix == '@':
+        member_id = str(id)
+        do = Identify.member.value
+      elif prefix == '@&':
+        role_id = str(id)
+        do = Identify.role.value
+      elif prefix == '#':
+        channel_id = str(id)
+        do = Identify.channel.value
+    else:
+      m = re.match(r'--(member|role|channel)s?', target)
+      if m is not None:
+        target = None
+        suffix = m.group(1)
+        if suffix == 'member':
+          do = Identify.member.value
+        elif suffix == 'role':
+          do = Identify.role.value
+        elif suffix == 'channel':
+          do = Identify.channel.value
+
+  results = []
+  if do & Identify.member.value:
+    if member_id:
+      for server in client.servers:
+        member = server.get_member(member_id)
+        if member is not None:
+          results.append(member)
+          break
+    else:
+      for member in client.get_all_members():
+        if target and member.name != target:
+          continue
+        results.append(member)
+  if do & Identify.role.value:
+    if role_id:
+      for server in client.servers:
+        for role in server.roles:
+          if role.id == role_id:
+            results.append(role)
+            break
+    else:
+      for server in client.servers:
+        for role in server.roles:
+          if target and role.name != target:
+            continue
+          results.append(role)
+  if do & Identify.channel.value:
+    if channel_id:
+      channel = client.get_channel(channel_id)
+      if channel is not None:
+        results.append(channel)
+    else:
+      for channel in client.get_all_channels():
+        if target and channel.name != target:
+          continue
+        results.append(channel)
+
+  while len(results):
+    # We can't print too big a message.
+    subset = results[:25]
+    results = results[len(subset):]
+    message = '\n'.join(['{} {} {}'.format(Identify.string(result), result.id, result.name) for result in subset])
+    yield from say(destination, message)
+
+@asyncio.coroutine
 def do_commands(message, command, raw, non_admin):
   if not non_admin:
     result = yield from is_admin(message.server, message.author)
@@ -375,6 +469,15 @@ def do_commands(message, command, raw, non_admin):
       log.info('Live mode')
       dryrun = False
 
+  elif command == 'id':
+    # id
+    m = re.match(r'\b[Ii][Dd]\s+(.*)', raw)
+    if m is not None:
+      target = m.group(1)
+    else:
+      target = None
+    yield from identify(message.channel, target)
+
   elif command == 'idle':
     # idle
     m = re.match(r'\bidle\s+(\d+)\b', raw.lower())
@@ -625,9 +728,9 @@ def announce(announcement):
     else:
       announce = random.random() <= announcement['probability']
       if announce:
-      log.info('Posting to {}: {}'.format(channel, text))
-      message = yield from say(channel, text)
-      digest = hashlib.sha224(message.content.encode('utf-8')).hexdigest()
+        log.info('Posting to {}: {}'.format(channel, text))
+        message = yield from say(channel, text)
+        digest = hashlib.sha224(message.content.encode('utf-8')).hexdigest()
       else:
         log.info("Didn't bother with announcement {}".format(announcement['id']))
       # Set last_spoke even if we chose not to announce.
@@ -673,7 +776,7 @@ modules = {
   'admin': {
     'fn': do_commands,
     'args': [False],
-    'commands': ['avatar', 'debug', 'delete', 'dryrun', 'idle', 'rss']
+    'commands': ['avatar', 'debug', 'delete', 'dryrun', 'id', 'idle', 'rss']
   },
   'any': {
     'fn': do_commands,