cachho 1 рік тому
батько
коміт
8be8990507
3 змінених файлів з 142 додано та 13 видалено
  1. 23 13
      docs/examples/discord_bot.mdx
  2. 117 0
      embedchain/bots/discord.py
  3. 2 0
      pyproject.toml

+ 23 - 13
docs/examples/discord_bot.mdx

@@ -8,40 +8,50 @@ title: '🤖 Discord Bot'
 - Go to [https://discord.com/developers/applications/](https://discord.com/developers/applications/) and click on `New Application`.
 - Enter the name for your bot, accept the terms and click on `Create`. On the resulting page, enter the details of your bot as you like.
 - On the left sidebar, click on `Bot`. Under the heading `Privileged Gateway Intents`, toggle all 3 options to ON position. Save your changes.
-- Now click on `Reset Token` and copy the token value. Set it as `DISCORD_BOT_TOKEN` in variables.env file.
+- Now click on `Reset Token` and copy the token value. Set it as `DISCORD_BOT_TOKEN` in .env file.
 - On the left sidebar, click on `OAuth2` and go to `General`.
 - Set `Authorization Method` to `In-app Authorization`. Under `Scopes` select `bot`.
 - Under `Bot Permissions` allow the following and then click on `Save Changes`.
 ```text
-Read Messages/View Channel (under General Permissions)
 Send Messages (under Text Permissions)
-Read Message History (under Text Permissions)
-Mention everyone (under Text Permissions)
 ```
 - Now under `OAuth2` and go to `URL Generator`. Under `Scopes` select `bot`.
 - Under `Bot Permissions` set the same permissions as above.
 - Now scroll down and copy the `Generated URL`. Paste it in a browser window and select the Server where you want to add the bot.
 - Click on `Continue` and authorize the bot.
-- 🎉 The bot has been successfully added to your server.
+- 🎉 The bot has been successfully added to your server. But it's still offline.
 
-### 🐳 Docker Setup
+### Take the bot online
+
+1. Install embedchain python package:
+
+```bash
+pip install "embedchain[discord]"
+```
+
+2. Launch your Discord bot:
+
+
+```bash
+python -m embedchain.bots.discord
+```
+
+If you prefer to see the question and not only the answer, run it with
 
-- To setup your discord bot using docker, run the following command inside this folder using your terminal.
 ```bash
-docker-compose up --build
+python -m embedchain.bots.discord --include-question
 ```
-📝 Note: The build command might take a while to install all the packages depending on your system resources.
 
 ### 🚀 Usage Instructions
 
 - Go to the server where you have added your bot.
-- You can add data sources to the bot using the command:
+- You can add data sources to the bot using the slash command:
 ```text
-/ec add <data_type> <url_or_text>
+/add <data_type> <url_or_text>
 ```
-- You can ask your queries from the bot using the command:
+- You can ask your queries from the bot using the slash command:
 ```text
-/ec query <question>
+/query <question>
 ```
 📝 Note: To use the bot privately, you can message the bot directly by right clicking the bot and selecting `Message`.
 

+ 117 - 0
embedchain/bots/discord.py

@@ -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()

+ 2 - 0
pyproject.toml

@@ -100,6 +100,7 @@ elasticsearch = { version = "^8.9.0", optional = true }
 flask = "^2.3.3"
 twilio = "^8.5.0"
 fastapi-poe = { version = "0.0.16", optional = true }
+discord = { version = "^2.3.2", optional = true }
 
 
 
@@ -119,6 +120,7 @@ community = ["llama-index"]
 opensource = ["sentence-transformers", "torch", "gpt4all"]
 elasticsearch = ["elasticsearch"]
 poe = ["fastapi-poe"]
+discord = ["discord"]
 
 [tool.poetry.group.docs.dependencies]