|
@@ -0,0 +1,117 @@
|
|
|
+import logging
|
|
|
+import os
|
|
|
+import argparse
|
|
|
+
|
|
|
+import discord
|
|
|
+from discord import app_commands
|
|
|
+from discord.ext import commands
|
|
|
+
|
|
|
+from .base import BaseBot
|
|
|
+
|
|
|
+intents = discord.Intents.default()
|
|
|
+intents.message_content = True
|
|
|
+client = discord.Client(intents=intents)
|
|
|
+tree = app_commands.CommandTree(client)
|
|
|
+
|
|
|
+# Invite link example
|
|
|
+# https://discord.com/api/oauth2/authorize?client_id={DISCORD_CLIENT_ID}&permissions=2048&scope=bot
|
|
|
+
|
|
|
+
|
|
|
+class DiscordBot(BaseBot):
|
|
|
+ def __init__(self, *args, **kwargs):
|
|
|
+ BaseBot.__init__(self, *args, **kwargs)
|
|
|
+
|
|
|
+ def add_data(self, message):
|
|
|
+ data = message.split(" ")[-1]
|
|
|
+ try:
|
|
|
+ self.add(data)
|
|
|
+ response = f"Added data from: {data}"
|
|
|
+ except Exception:
|
|
|
+ logging.exception(f"Failed to add data {data}.")
|
|
|
+ response = "Some error occurred while adding data."
|
|
|
+ return response
|
|
|
+
|
|
|
+ def ask_bot(self, message):
|
|
|
+ try:
|
|
|
+ response = self.query(message)
|
|
|
+ except Exception:
|
|
|
+ logging.exception(f"Failed to query {message}.")
|
|
|
+ response = "An error occurred. Please try again!"
|
|
|
+ return response
|
|
|
+
|
|
|
+ def start(self):
|
|
|
+ client.run(os.environ["DISCORD_BOT_TOKEN"])
|
|
|
+
|
|
|
+
|
|
|
+# @tree decorator cannot be used in a class. A global discord_bot is used as a workaround.
|
|
|
+
|
|
|
+
|
|
|
+@tree.command(name="question", description="ask embedchain")
|
|
|
+async def query_command(interaction: discord.Interaction, question: str):
|
|
|
+ await interaction.response.defer()
|
|
|
+ member = client.guilds[0].get_member(client.user.id)
|
|
|
+ logging.info(f"User: {member}, Query: {question}")
|
|
|
+ try:
|
|
|
+ answer = discord_bot.ask_bot(question)
|
|
|
+ if args.include_question:
|
|
|
+ response = f"> {question}\n\n{answer}"
|
|
|
+ else:
|
|
|
+ response = answer
|
|
|
+ await interaction.followup.send(response)
|
|
|
+ except Exception as e:
|
|
|
+ await interaction.followup.send("An error occurred. Please try again!")
|
|
|
+ logging.error("Error occurred during 'query' command:", e)
|
|
|
+
|
|
|
+
|
|
|
+@tree.command(name="add", description="add new content to the embedchain database")
|
|
|
+async def add_command(interaction: discord.Interaction, url_or_text: str):
|
|
|
+ await interaction.response.defer()
|
|
|
+ member = client.guilds[0].get_member(client.user.id)
|
|
|
+ logging.info(f"User: {member}, Add: {url_or_text}")
|
|
|
+ try:
|
|
|
+ response = discord_bot.add_data(url_or_text)
|
|
|
+ await interaction.followup.send(response)
|
|
|
+ except Exception as e:
|
|
|
+ await interaction.followup.send("An error occurred. Please try again!")
|
|
|
+ logging.error("Error occurred during 'add' command:", e)
|
|
|
+
|
|
|
+
|
|
|
+@tree.command(name="ping", description="Simple ping pong command")
|
|
|
+async def ping(interaction: discord.Interaction):
|
|
|
+ await interaction.response.send_message("Pong", ephemeral=True)
|
|
|
+
|
|
|
+
|
|
|
+@tree.error
|
|
|
+async def on_app_command_error(interaction: discord.Interaction, error: discord.app_commands.AppCommandError) -> None:
|
|
|
+ if isinstance(error, commands.CommandNotFound):
|
|
|
+ await interaction.followup.send("Invalid command. Please refer to the documentation for correct syntax.")
|
|
|
+ else:
|
|
|
+ logging.error("Error occurred during command execution:", error)
|
|
|
+
|
|
|
+
|
|
|
+@client.event
|
|
|
+async def on_ready():
|
|
|
+ # TODO: Sync in admin command, to not hit rate limits.
|
|
|
+ # This might be overkill for most users, and it would require to set a guild or user id, where sync is allowed.
|
|
|
+ await tree.sync()
|
|
|
+ logging.debug("Command tree synced")
|
|
|
+ logging.info(f"Logged in as {client.user.name}")
|
|
|
+
|
|
|
+
|
|
|
+def start_command():
|
|
|
+ parser = argparse.ArgumentParser(description="EmbedChain DiscordBot command line interface")
|
|
|
+ parser.add_argument(
|
|
|
+ "--include-question",
|
|
|
+ help="include question in query reply, otherwise it is hidden behind the slash command.",
|
|
|
+ action="store_true",
|
|
|
+ )
|
|
|
+ global args
|
|
|
+ args = parser.parse_args()
|
|
|
+
|
|
|
+ global discord_bot
|
|
|
+ discord_bot = DiscordBot()
|
|
|
+ discord_bot.start()
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ start_command()
|