Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: discord bot #465

Merged
merged 27 commits into from
Sep 3, 2023
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6331d41
chore: added dependencies
cachho Aug 23, 2023
371dc27
feat: example implementation
cachho Aug 23, 2023
a4233f2
feat: command tree based discord bot
cachho Aug 23, 2023
e4c78d7
fix: remove unused import
cachho Aug 23, 2023
23d28cc
chore: linting
cachho Aug 23, 2023
00d55da
fix: remove args
cachho Aug 23, 2023
293a3b4
chore: added todo
cachho Aug 23, 2023
cf7a49f
fix: double declaration
cachho Aug 23, 2023
d54f70e
chore: added invite link example
cachho Aug 23, 2023
f00187d
fix: remove guild restriction
cachho Aug 23, 2023
c223076
Merge branch 'main' of https://github.com/cachho/embedchain into feat…
cachho Aug 24, 2023
cbf8357
chore: update version
cachho Aug 24, 2023
076fd74
fix: remove dotenv
cachho Aug 24, 2023
c84a034
fix: don't use debug
cachho Aug 24, 2023
a13b31f
docs: use comma
cachho Aug 24, 2023
855bfd7
Merge branch 'main' of https://github.com/cachho/embedchain into feat…
cachho Aug 25, 2023
a1cdb1e
fix: command signature
cachho Aug 25, 2023
bf52955
fix: return defer
cachho Aug 25, 2023
16e3030
chore: linting
cachho Aug 25, 2023
40c98fb
feat: include question
cachho Aug 25, 2023
5225564
fix: parameter
cachho Aug 25, 2023
8367b66
fix: invite link
cachho Aug 25, 2023
7b5be4c
docs: add bot
cachho Aug 25, 2023
cbc5b15
refactor: logging instead of print
cachho Aug 25, 2023
a7b9b30
Merge branch 'main' into feat/DiscordBot
cachho Aug 31, 2023
9533aaf
fix: update install command
cachho Sep 3, 2023
e760c97
Merge branch 'main' into feat/DiscordBot
cachho Sep 3, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions docs/examples/discord_bot.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,51 @@ 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
cachho marked this conversation as resolved.
Show resolved Hide resolved
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