Moved id command to developer plugin.
authorCMDR furrycat <elite@furrycat.net>
Thu, 10 Nov 2016 13:57:06 +0000 (13:57 +0000)
committerCMDR furrycat <elite@furrycat.net>
Thu, 10 Nov 2016 14:21:36 +0000 (14:21 +0000)
app.py
plugin/developer/developer.py [new file with mode: 0644]

diff --git a/app.py b/app.py
index cba7158..be8068b 100644 (file)
--- a/app.py
+++ b/app.py
@@ -14,28 +14,10 @@ import sys
 import time
 
 from db import DBConnection
-from enum import Enum
 from plugins import Plugins
 import bot
 import cat
 
-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:
-      if instance.type == discord.ChannelType.voice:
-        return 'Voice Channel ({}bps)'.format(instance.bitrate)
-      return 'Channel'
-
 db = DBConnection()
 plugins = Plugins()
 
@@ -75,83 +57,6 @@ def not_admin(message):
   yield from bot.maybe_say(message.channel, 'hiss!')
 
 @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:
-          parts = target.lower().split('#')
-          if member.name.lower() != parts[0]:
-            continue
-          if len(parts) > 1 and member.discriminator != parts[1]:
-            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.lower() != target.lower():
-            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.lower() != target.lower():
-          continue
-        results.append(channel)
-
-  yield from bot.say_many(destination, ['{} {} {}'.format(Identify.string(result), result.id, result.name) for result in set(results)])
-
-@asyncio.coroutine
 def show_help(message, *args):
   if len(args):
     command = args[0]
@@ -172,29 +77,6 @@ def show_help(message, *args):
     ]
   elif command == 'help':
     lines = ['grr!']
-  elif command == 'id':
-    lines = [
-      'Print the Discord IDs of member, roles or channels known to me.',
-      '```',
-      'id MEMBER',
-      'id ROLE',
-      'id CHANNEL',
-      '```',
-      'Prints the ID of the member, role or channel with the given name.',
-      "I can only identify someone or something if I share a server.",
-      'Useful for `announce create` to specify a `voice` channel, which must be done by ID.',
-      '',
-      '```',
-      'id --members',
-      'id --roles',
-      'id --channels',
-      'id',
-      '```',
-      'Identify all MEMBERs, ROLEs or CHANNELs known to me.',
-      "If you don't give any arguments I'll identify everyone and everything I know about.",
-      'Note that if I share more than one server with a member, that member will be listed twice with two IDs!',
-      "Also note that because of the Discord message length limit I'll probably have to split my reply into multiple posts."
-    ]
   elif command == 'time':
     lines = [
       'Print the time in UTC.',
@@ -260,15 +142,6 @@ def do_commands(message, command, raw, non_admin):
     yield from client.purge_from(message.channel, *args, limit = limit)
     return
 
-  elif command == 'id':
-    # id
-    m = re.match(r'\bid\s+(.*)', raw, re.IGNORECASE)
-    if m is not None:
-      target = m.group(1)
-    else:
-      target = None
-    yield from identify(message.channel, target)
-
   elif command == 'help':
     # help
     m = re.match(r'\bhelp\s+(.+)', raw, re.IGNORECASE)
@@ -360,7 +233,7 @@ modules = {
   'any': {
     'fn': do_commands,
     'args': [True],
-    'commands': ['fuss', 'help', 'id', 'stroke', 'time', 'treat', 'pat']
+    'commands': ['fuss', 'help', 'stroke', 'time', 'treat', 'pat']
   },
   'edi': {
     'fn': do_edi,
diff --git a/plugin/developer/developer.py b/plugin/developer/developer.py
new file mode 100644 (file)
index 0000000..14b5c78
--- /dev/null
@@ -0,0 +1,169 @@
+import asyncio
+import discord
+import shlex
+import re
+import sys
+
+from plugins import PluginCommand
+from enum import Enum
+from throwingargparse import ThrowingArgumentParser
+import bot
+import cat
+
+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:
+      if instance.type == discord.ChannelType.voice:
+        return 'Voice Channel ({}bps)'.format(instance.bitrate)
+      return 'Channel'
+
+class Developer(object):
+  def description(self):
+    return 'Helpful Discord developer tools.'
+
+  def valid_commands(self):
+    return ['id']
+
+  @asyncio.coroutine
+  def handle_command(self, message, command, raw):
+    if command not in self.valid_commands():
+      return PluginCommand.ignored
+    yield from self.run_command(message, shlex.split(raw))
+    return PluginCommand.exclusive
+
+  @asyncio.coroutine
+  def handle_help(self, message, command, *args):
+    yield from self.help_command(message, *args)
+
+  @asyncio.coroutine
+  def run_command(self, message, args):
+    command = args[0]
+    if command == 'id':
+      yield from self.handle_id(message, args[1:])
+
+  @asyncio.coroutine
+  def help_command(self, message, command):
+    if command == 'id':
+      lines = [
+        'Print the Discord IDs of member, roles or channels known to me.',
+        '```',
+        'id MEMBER',
+        'id ROLE',
+        'id CHANNEL',
+        '```',
+        'Prints the ID of the member, role or channel with the given name.',
+        "I can only identify someone or something if I share a server.",
+        'Useful for `announce create` to specify a `voice` channel, which must be done by ID.',
+        '',
+        '```',
+        'id --members',
+        'id --roles',
+        'id --channels',
+        'id',
+        '```',
+        'Identify all MEMBERs, ROLEs or CHANNELs known to me.',
+        "If you don't give any arguments I'll identify everyone and everything I know about.",
+        'Note that if I share more than one server with a member, that member will be listed twice with two IDs!',
+        "Also note that because of the Discord message length limit I'll probably have to split my reply into multiple posts."
+      ]
+    else:
+      lines = ['*shrugs*']
+    yield from bot.say_many(message.channel, lines)
+
+  @asyncio.coroutine
+  def handle_id(self, message, args):
+    do = Identify.member.value | Identify.role.value | Identify.channel.value
+    target = None
+    channel_id = None
+    role_id = None
+    member_id = None
+
+    ap = ThrowingArgumentParser()
+    ap.add_argument('--channel', '--channels', action='store_true')
+    ap.add_argument('--member', '--members', action='store_true')
+    ap.add_argument('--role', '--roles', action='store_true')
+    ap.add_argument('target', nargs='?')
+    try:
+      parsed = ap.parse_args(args)
+    except ArgumentParserError:
+      yield from cat.yelp(message.channel)
+      return
+
+    if parsed.target:
+      m = re.match(r'<?(@&?|#)(\d+)>?', parsed.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:
+        target = parsed.target
+    elif parsed.channel or parsed.member or parsed.role:
+      do = 0
+      if parsed.channel:
+        do |= Identify.channel.value
+      if parsed.member:
+        do |= Identify.member.value
+      if parsed.role:
+        do |= Identify.role.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:
+            parts = target.lower().split('#')
+            if member.name.lower() != parts[0]:
+              continue
+            if len(parts) > 1 and member.discriminator != parts[1]:
+              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.lower() != target.lower():
+              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.lower() != target.lower():
+            continue
+          results.append(channel)
+
+    yield from bot.say_many(message.channel, ['{} {} {}'.format(Identify.string(result), result.id, result.name) for result in set(results)])