summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorlatex <latex@disroot.org>2023-03-31 02:05:25 +0200
committerlatex <latex@disroot.org>2023-03-31 02:05:25 +0200
commit472b5b0e46dcadbc769b8b415aa6807297467e59 (patch)
tree37e5c0967ac7811867837ff6ffb829452b651184
parent9ed06f53fd8db5bf920a315f480e923eb2c6620f (diff)
downloadmumblecord-472b5b0e46dcadbc769b8b415aa6807297467e59.tar.gz
add commands: guilds, vc, activevc
-rw-r--r--src/commands.py64
-rw-r--r--src/main.py6
-rw-r--r--src/mumblecord.py74
3 files changed, 136 insertions, 8 deletions
diff --git a/src/commands.py b/src/commands.py
new file mode 100644
index 0000000..8a49e73
--- /dev/null
+++ b/src/commands.py
@@ -0,0 +1,64 @@
+import discord
+
+def register_all_commands(bot):
+    bot.register_command("guilds", cmd_guilds)
+    bot.register_command("vc", cmd_vc)
+    bot.register_command("activevc", cmd_activevc)
+
+def cmd_guilds(bot, text, user, arg, argv):
+    """
+    Show all guilds
+    """
+    response = ""
+    for guild in bot.discord.guilds:
+        response += f"{guild.id}: {guild.name}\n"
+
+    user.send_text_message(response)
+
+def cmd_vc(bot, text, user, arg, argv):
+    """
+    Show voice channels in all guilds,
+    or in a specific guild if the ID or name of guild has been given
+    """
+    if not argv:
+        response = ""
+        for guild in bot.discord.guilds:
+            response += f"{guild.id}: {guild.name}\n"
+            for vc in guild.voice_channels:
+                response += f">{vc.id}: {vc.name}\n"
+    else:
+        guild = None
+        try:
+            guild = discord.utils.find(lambda g: g.id == int(argv[0]), bot.discord.guilds)
+        except ValueError:
+            pass
+        if not guild:
+            guild = discord.utils.find(lambda g: g.name == arg, bot.discord.guilds)
+        if not guild:
+            user.send_text_message("no guild found")
+            return
+
+        response = f"{guild.name}: \n"
+        for vc in guild.voice_channels:
+            response += f">{vc.id}: {vc.name}\n"
+
+    user.send_text_message(response)
+
+def cmd_activevc(bot, text, user, arg, argv):
+    """
+    Show all voice channels with users inside
+    """
+    if not argv:
+        response = ""
+        for guild in bot.discord.guilds:
+            vcs_with_active_members = []
+            for vc in guild.voice_channels:
+                if len(vc.members) > 0:
+                    vcs_with_active_members.append(vc)
+            if len(vcs_with_active_members) > 0:
+                response += f"{guild.id}: {guild.name}\n"
+                for vc in vcs_with_active_members:
+                    response += f">{vc.id}: {vc.name} ({len(vc.members)})\n"
+                user.send_text_message(response)
+            else:
+                user.send_text_message("no active voice channels found")
diff --git a/src/main.py b/src/main.py
index 69f6a57..99ec97d 100644
--- a/src/main.py
+++ b/src/main.py
@@ -2,6 +2,7 @@ import asyncio
 import argparse
 import configparser
 import mumblecord
+import commands
 
 parser = argparse.ArgumentParser(
         prog="mumblecord",
@@ -17,6 +18,7 @@ conf_mumble = conf["mumble"]
 conf_discord = conf["discord"]
 
 bot = mumblecord.Mumblecord(conf_mumble, conf_discord)
+commands.register_all_commands(bot)
+
+asyncio.run(bot.run())
 
-while True:
-    pass
diff --git a/src/mumblecord.py b/src/mumblecord.py
index 914265f..1972508 100644
--- a/src/mumblecord.py
+++ b/src/mumblecord.py
@@ -1,6 +1,8 @@
 import asyncio
 import pymumble_py3
 import discord
+import shlex
+import html
 
 class Discord(discord.Client):
     def __init__(self, mumblecord):
@@ -9,7 +11,11 @@ class Discord(discord.Client):
 
     async def on_ready(self):
         print(f"Discord: logged in as {self.user}")
-        self.mumblecord.mumble.users.myself.comment(f"{self.user}")
+        self.mumblecord.update_mumble_comment()
+
+class ChannelLink:
+    def __init__(self, discord_voice_client):
+        self.discord_voice_client = discord_voice_client
 
 class Mumblecord:
     def __init__(self, conf_mumble, conf_discord):
@@ -19,17 +25,73 @@ class Mumblecord:
         self.mumble_password = conf_mumble.get("password", "")
         self.mumble_cert = conf_mumble.get("cert", None)
         self.mumble_key = conf_mumble.get("key", None)
-        
+        self.mumble_prefix = conf_mumble.get("prefix", "$")
+        self.mumble_trusted_user = conf_mumble.get("trusted_user", None)
+
+        self.commands = {}
+        self.voicelink = None
+
         self.discord_token = conf_discord["token"]
 
         self.mumble = pymumble_py3.Mumble(self.mumble_host, self.mumble_user,
                                 password=self.mumble_password,
                                 certfile=self.mumble_cert, keyfile=self.mumble_key, stereo=True)
-        self.mumble.start()
-        self.mumble.is_ready()
+        self.mumble.callbacks.set_callback(pymumble_py3.constants.PYMUMBLE_CLBK_SOUNDRECEIVED,
+                                           self._mumble_sound_received)
+        self.mumble.callbacks.set_callback(pymumble_py3.constants.PYMUMBLE_CLBK_TEXTMESSAGERECEIVED,
+                                           self._mumble_text_message_received)
+        self.mumble.set_receive_sound(1)
 
-        asyncio.run(self._init_discord())
+        self.discord = None
 
-    async def _init_discord(self):
+    async def run(self):
         self.discord = Discord(self)
+        await asyncio.gather(
+                asyncio.to_thread(self.mumble.start))
         await self.discord.start(self.discord_token)
+
+    def register_command(self, cmd, callback):
+        """
+        Register a command.
+        When the command is ran, the callback will be called with the following arguments:
+
+        bot: the Mumblecord class the callback is ran under
+        text: the text object from the pymumble TEXTMESSAGERECEIVED callback
+        user: the User who sent the message
+        arg: everything typed after the command. Useful if you just need one big argument
+        argv: an array of arguments, split for your convenience
+        """
+
+        self.commands[cmd] = {"callback": callback}
+
+    def update_mumble_comment(self):
+        self.mumble.users.myself.comment(f"{self.discord.user}")
+
+    def _mumble_text_message_received(self, text):
+        if not text.message.startswith(self.mumble_prefix):
+            return
+        if text.actor == 0:
+            # Some server will send a welcome message to the bot once connected.
+            # It doesn't have a valid "actor". Simply ignore it here.
+            return
+
+        user = self.mumble.users[text.actor]
+
+        message = html.unescape(text.message)
+        cmd = message[1:].split(" ", 1)[0]
+
+        if not self.commands[cmd]:
+            return
+
+        try:
+            arg = message[1:].split(" ", 1)[1]
+            argv = shlex.split(arg)
+        except IndexError:
+            arg = None
+            argv = None
+
+        self.commands[cmd]["callback"](self, text, user, arg, argv)
+
+    def _mumble_sound_received(self, user, soundchunk):
+        if self.voicelink is None:
+            return