-
Notifications
You must be signed in to change notification settings - Fork 710
/
Copy pathbot.py
137 lines (118 loc) · 6.08 KB
/
bot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import discord
from discord.ext import commands
from src import responses
from src import log
logger = log.setup_logger(__name__)
data = responses.get_config()
isPrivate = False
async def send_message(message, user_message):
await message.response.defer(ephemeral=isPrivate)
try:
response = '> **' + user_message + '** - <@' + \
str(message.user.id) + '>\n\n'
response += await responses.handle_response(user_message)
if len(response) > 1900:
# Split the response into smaller chunks of no more than 1900 characters each(Discord limit is 2000 per chunk)
if "```" in response:
# Split the response if the code block exists
parts = response.split("```")
# Send the first message
await message.followup.send(parts[0])
# Send the code block in a seperate message
code_block = parts[1].split("\n")
formatted_code_block = ""
for line in code_block:
while len(line) > 1900:
# Split the line at the 50th character
formatted_code_block += line[:1900] + "\n"
line = line[1900:]
formatted_code_block += line + "\n" # Add the line and seperate with new line
# Send the code block in a separate message
if (len(formatted_code_block) > 2000):
code_block_chunks = [formatted_code_block[i:i+1900] for i in range(0, len(formatted_code_block), 1900)]
for chunk in code_block_chunks:
await message.followup.send("```" + chunk + "```")
else:
await message.followup.send("```" + formatted_code_block + "```")
# Send the remaining of the response in another message
if len(parts) >= 3:
await message.followup.send(parts[2])
else:
response_chunks = [response[i:i+1900]
for i in range(0, len(response), 1900)]
for chunk in response_chunks:
await message.followup.send(chunk)
else:
await message.followup.send(response)
except Exception as e:
await message.followup.send("> **Error: Something went wrong, please try again later!**")
logger.exception(f"Error while sending message: {e}")
async def send_start_prompt() :
import os
import os.path
config_dir = os.path.abspath(__file__ + "/../../")
prompt_name = 'starting-prompt.txt'
prompt_path = os.path.join(config_dir, prompt_name)
try:
if os.path.isfile(prompt_path) and os.path.getsize(prompt_path) > 0:
with open(prompt_path, "r") as f:
prompt = f.read()
logger.info(f"Send starting prompt with size {len(prompt)}")
responseMessage = await responses.handle_response(prompt)
logger.info(f"Starting prompt response: {responseMessage}")
else:
logger.info(f"No {prompt_name}. Skip sending starting prompt.")
except Exception as e:
logger.exception(f"Error while sending starting prompt: {e}")
def run_discord_bot():
intents = discord.Intents.default()
intents.message_content = True
activity = discord.Activity(type=discord.ActivityType.watching, name="/chat | /private | /public | /reset")
client = commands.Bot(command_prefix='!', intents=intents, activity=activity)
@client.event
async def on_ready():
await send_start_prompt()
await client.tree.sync()
logger.info(f'{client.user} is now running!')
@client.tree.command(name="chat", description="Have a chat with ChatGPT")
async def chat(interaction: discord.Interaction, *, message: str):
if interaction.user == client.user:
return
username = str(interaction.user)
user_message = message
channel = str(interaction.channel)
logger.info(
f"\x1b[31m{username}\x1b[0m : '{user_message}' ({channel})")
await send_message(interaction, user_message)
@client.tree.command(name="private", description="Toggle private access")
async def private(interaction: discord.Interaction):
global isPrivate
await interaction.response.defer(ephemeral=False)
if not isPrivate:
isPrivate = not isPrivate
logger.warning("\x1b[31mSwitch to private mode\x1b[0m")
await interaction.followup.send("> **Info: Next, the response will be sent via private message. If you want to switch back to public mode, use `/public`**")
else:
logger.info("You already on private mode!")
await interaction.followup.send("> **Warn: You already on private mode. If you want to switch to public mode, use `/public`**")
@client.tree.command(name="public", description="Toggle public access")
async def public(interaction: discord.Interaction):
global isPrivate
await interaction.response.defer(ephemeral=False)
if isPrivate:
isPrivate = not isPrivate
await interaction.followup.send("> **Info: Next, the response will be sent to the channel directly. If you want to switch back to private mode, use `/private`**")
logger.warning("\x1b[31mSwitch to public mode\x1b[0m")
else:
await interaction.followup.send("> **Warn: You already on public mode. If you want to switch to private mode, use `/private`**")
logger.info("You already on public mode!")
@client.tree.command(name="reset", description="Complete reset ChatGPT conversation history")
async def reset(interaction: discord.Interaction):
responses.chatbot.reset_chat()
await interaction.response.defer(ephemeral=False)
await interaction.followup.send("> **Info: I have forgotten everything.**")
logger.warning(
"\x1b[31mChatGPT bot has been successfully reset\x1b[0m")
await send_start_prompt()
TOKEN = data['discord_bot_token']
client.run(TOKEN)