feat: discord bot (#465)
This commit is contained in:
@@ -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:
|
||||
|
||||
- To setup your discord bot using docker, run the following command inside this folder using your terminal.
|
||||
```bash
|
||||
docker-compose up --build
|
||||
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
|
||||
|
||||
```bash
|
||||
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
embedchain/bots/discord.py
Normal file
117
embedchain/bots/discord.py
Normal file
@@ -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()
|
||||
@@ -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]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user