freddyaboulton HF staff commited on
Commit
967ff9e
β€’
1 Parent(s): 53f00e9

Deploy Discord Bot

Browse files
Files changed (2) hide show
  1. app.py +205 -0
  2. requirements.txt +1 -0
app.py ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import os
3
+ import threading
4
+ from threading import Event
5
+ from typing import Optional
6
+
7
+ import discord
8
+ import gradio as gr
9
+ from discord import Permissions
10
+ from discord.ext import commands
11
+ from discord.utils import oauth_url
12
+
13
+ import gradio_client as grc
14
+ from gradio_client.utils import QueueError
15
+
16
+ event = Event()
17
+
18
+ DISCORD_TOKEN = os.getenv("DISCORD_TOKEN")
19
+
20
+
21
+ async def wait(job):
22
+ while not job.done():
23
+ await asyncio.sleep(0.2)
24
+
25
+
26
+ def get_client(session: Optional[str] = None) -> grc.Client:
27
+ client = grc.Client("https://freddyaboulton-gpt-35-turbo.hf.space", hf_token=os.getenv("HF_TOKEN"))
28
+ if session:
29
+ client.session_hash = session
30
+ return client
31
+
32
+
33
+ def truncate_response(response: str) -> str:
34
+ ending = "...\nTruncating response to 2000 characters due to discord api limits."
35
+ if len(response) > 2000:
36
+ return response[: 2000 - len(ending)] + ending
37
+ else:
38
+ return response
39
+
40
+
41
+ intents = discord.Intents.default()
42
+ intents.message_content = True
43
+ bot = commands.Bot(command_prefix="!", intents=intents)
44
+
45
+
46
+ @bot.event
47
+ async def on_ready():
48
+ print(f"Logged in as {bot.user} (ID: {bot.user.id})")
49
+ event.set()
50
+ print("------")
51
+
52
+
53
+ thread_to_client = {}
54
+ thread_to_user = {}
55
+
56
+
57
+ @bot.command()
58
+ @commands.is_owner()
59
+ async def sync(ctx) -> None:
60
+ synced = await bot.tree.sync()
61
+ await ctx.send(f"Synced commands: {', '.join([s.name for s in synced])}.")
62
+
63
+
64
+ @bot.hybrid_command(
65
+ name="chat",
66
+ description="Enter some text to chat with the bot! Like this: /chat Hello, how are you?",
67
+ )
68
+ async def chat(ctx, prompt: str):
69
+ if ctx.author.id == bot.user.id:
70
+ return
71
+ try:
72
+ message = await ctx.send("Creating thread...")
73
+
74
+ # User triggered bot via !chat
75
+ if ctx.message.content:
76
+ prompt = ctx.message.content.replace(
77
+ f"{bot.command_prefix}chat", ""
78
+ ).strip()
79
+
80
+ thread = await message.create_thread(name=prompt)
81
+ loop = asyncio.get_running_loop()
82
+ client = await loop.run_in_executor(None, get_client, None)
83
+ job = client.submit(prompt, api_name="/chat")
84
+ await wait(job)
85
+
86
+ try:
87
+ job.result()
88
+ response = job.outputs()[-1]
89
+ await thread.send(truncate_response(response))
90
+ thread_to_client[thread.id] = client
91
+ thread_to_user[thread.id] = ctx.author.id
92
+ except QueueError:
93
+ await thread.send(
94
+ "The gradio space powering this bot is really busy! Please try again later!"
95
+ )
96
+
97
+ except Exception as e:
98
+ print(f"{e}")
99
+
100
+
101
+ async def continue_chat(message):
102
+ """Continues a given conversation based on chathistory"""
103
+ try:
104
+ client = thread_to_client[message.channel.id]
105
+ prompt = message.content
106
+ job = client.submit(prompt, api_name="/chat")
107
+ await wait(job)
108
+ try:
109
+ job.result()
110
+ response = job.outputs()[-1]
111
+ await message.reply(truncate_response(response))
112
+ except QueueError:
113
+ await message.reply(
114
+ "The gradio space powering this bot is really busy! Please try again later!"
115
+ )
116
+
117
+ except Exception as e:
118
+ print(f"Error: {e}")
119
+
120
+
121
+ @bot.event
122
+ async def on_message(message):
123
+ """Continue the chat"""
124
+ try:
125
+ if not message.author.bot:
126
+ if message.channel.id in thread_to_user:
127
+ if thread_to_user[message.channel.id] == message.author.id:
128
+ await continue_chat(message)
129
+ else:
130
+ await bot.process_commands(message)
131
+
132
+ except Exception as e:
133
+ print(f"Error: {e}")
134
+
135
+
136
+ # running in thread
137
+ def run_bot():
138
+ if not DISCORD_TOKEN:
139
+ print("DISCORD_TOKEN NOT SET")
140
+ event.set()
141
+ else:
142
+ bot.run(DISCORD_TOKEN)
143
+
144
+
145
+ threading.Thread(target=run_bot).start()
146
+
147
+ event.wait()
148
+
149
+ if not DISCORD_TOKEN:
150
+ welcome_message = """
151
+
152
+ ## You have not specified a DISCORD_TOKEN, which means you have not created a bot account. Please follow these steps:
153
+
154
+ ### 1. Go to https://discord.com/developers/applications and click 'New Application'
155
+
156
+ ### 2. Give your bot a name πŸ€–
157
+
158
+ ![](https://gradio-builds.s3.amazonaws.com/demo-files/discordbots/BotName.png)
159
+
160
+ ## 3. In Settings > Bot, click the 'Reset Token' button to get a new token. Write it down and keep it safe πŸ”
161
+
162
+ ![](https://gradio-builds.s3.amazonaws.com/demo-files/discordbots/ResetToken.png)
163
+
164
+ ## 4. Optionally make the bot public if you want anyone to be able to add it to their servers
165
+
166
+ ## 5. Scroll down and enable 'Message Content Intent' under 'Priviledged Gateway Intents'
167
+
168
+ ![](https://gradio-builds.s3.amazonaws.com/demo-files/discordbots/MessageContentIntent.png)
169
+
170
+ ## 6. Save your changes!
171
+
172
+ ## 7. The token from step 3 is the DISCORD_TOKEN. Rerun the deploy_discord command, e.g client.deploy_discord(discord_bot_token=DISCORD_TOKEN, ...), or add the token as a space secret manually.
173
+ """
174
+ else:
175
+ permissions = Permissions(326417525824)
176
+ url = oauth_url(bot.user.id, permissions=permissions)
177
+ welcome_message = f"""
178
+ ## Add this bot to your server by clicking this link:
179
+
180
+ {url}
181
+
182
+ ## How to use it?
183
+
184
+ The bot can be triggered via `!chat` followed by your text prompt.
185
+
186
+ ## Enabling slash commands
187
+
188
+ If you are the owner of this bot, call the `!sync` command from your discord server.
189
+ This will allow anyone in your server to call the bot via `/chat`.
190
+ This is known as a slash command and is a nicer experience than calling the bot via `!chat`.
191
+
192
+ After calling `!sync`, it may take a few minutes for `/chat` to be recognized as a valid command
193
+ in your server.
194
+ """
195
+
196
+
197
+ with gr.Blocks() as demo:
198
+ gr.Markdown(
199
+ f"""
200
+ # Discord bot of https://freddyaboulton-gpt-35-turbo.hf.space
201
+ {welcome_message}
202
+ """
203
+ )
204
+
205
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ discord.py==2.3.1