Skip to content

Commit

Permalink
feat: discord bot (mem0ai#465)
Browse files Browse the repository at this point in the history
  • Loading branch information
cachho committed Sep 3, 2023
1 parent 2cfeb5e commit 8be8990
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 13 deletions.
36 changes: 23 additions & 13 deletions docs/examples/discord_bot.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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`.

Expand Down
117 changes: 117 additions & 0 deletions embedchain/bots/discord.py
Original file line number Diff line number Diff line change
@@ -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 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }



Expand All @@ -119,6 +120,7 @@ community = ["llama-index"]
opensource = ["sentence-transformers", "torch", "gpt4all"]
elasticsearch = ["elasticsearch"]
poe = ["fastapi-poe"]
discord = ["discord"]

[tool.poetry.group.docs.dependencies]

Expand Down

0 comments on commit 8be8990

Please sign in to comment.