-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
330 lines (284 loc) · 12.6 KB
/
main.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
import json
from discord import Intents, Client, app_commands
from discord.ext import commands, tasks # pip install discord-ext-bot
import discord # pip install discord
import openai # pip install openai
import os
# Used for retrieving BOT_KEY from .env
from decouple import config
# ========================================
# Response Features
# ========================================
import functions.responses as responses
import functions.steam as steam
import functions.fortnite as fortnite
import functions.playmusic as playmusic
import functions.events as events
import functions.qr_generator as qr
import functions.get_gif as gifs
import functions.sport_details as sport_details
import functions.currency_conversion as currency
# Fetch Credentials from local .env variables
# Constants
BOT_KEY = config('BOT_KEY')
# OPENAI_API_KEY = config('OPENAI_API_KEY')
knowledge: dict = responses.load_knowledge('./resources/knowledge.json')
# Bot Constants
intents = Intents.default()
intents.message_content = True
intents.reactions = True
bot = commands.Bot(command_prefix="!", intents=intents, help_command=None) # Initialize bot
# gptClient = openai.OpenAI(api_key=OPENAI_API_KEY)
# Start bot
@bot.event
async def on_ready():
load_wishlist()
await steam_sale.start() # Enable/disable Steam sale notification
await bot.tree.sync()
print(f"{bot.user} is now running!")
# ========================================
# FUNCTIONS
# ========================================
def save_wishlist():
global server_wishlists
# Relative path to the file
file_path = os.path.join('resources', 'wishlist.json')
with open(file_path, 'w') as f:
json.dump(server_wishlists, f)
print("[ SAVED ] Wishlist saved successfully")
def save_default_channel():
'''Set the server's default text channel based on where the !addwishlist command was run.'''
global default_channel
# Relative path to the file
file_path = os.path.join('resources', 'default_channel.json')
with open(file_path, 'w') as f:
json.dump(default_channel, f)
print("[ SAVED ] Default wishlist channel saved successfully")
def load_wishlist():
'''Load wishlist if existing, create a new one if none available.'''
global server_wishlists
global default_channel
try:
print("[ LOG ] Loading Server Wishlist...")
# Relative path to the file
file_path = os.path.join('resources', 'wishlist.json')
with open(file_path, 'r') as f:
server_wishlists = json.load(f)
print("[ LOG ] LOADED existing Wishlist")
print("[ LOG ] Loading Default Wishlist channel data...")
# Relative path to the file
file_path = os.path.join('resources', 'default_channel.json')
with open(file_path, 'r') as f:
default_channel = json.load(f)
print("[ LOG ] LOADED Default Wishlist channel")
except FileNotFoundError:
print("[ LOG ] wishlist.json or default_channel.json not found, starting with an empty wishlist.")
server_wishlists = {}
default_channel = {}
@tasks.loop(hours=12)
async def steam_sale():
print("[ LOG ] Loop-task: checking for server steam wishlist sale")
await steam.check_sale(bot, server_wishlists, default_channel)
@steam_sale.before_loop
async def before_check_sales():
'''Ensure the bot is ready before starting the steam_sale loop'''
await bot.wait_until_ready()
# ========================================
# ! COMMANDS
# ========================================
# Simple example command
@bot.command(name='hello', description='Example command for easy copying and pasting.')
async def hello_command(ctx):
await ctx.send(f'Hello, {ctx.author.name}!')
# #####################
@bot.command(name='help')
async def help_command(ctx):
embed = discord.Embed(
# title='Cpt. Bot Commands',
color=discord.Color.red()
)
# Add fields to the embed (optional)
embed.set_author(name="King Bob's Commands", url="https://github.com/GabeDiniz", icon_url="https://imgur.com/nH32raP.png")
embed.set_thumbnail(url="https://i.imgur.com/nH32raP.png")
embed.add_field(name='See Music Commands', value='`!help-music`', inline=False)
embed.add_field(name='Search for a Game', value='`!steamgame <name>`', inline=True)
embed.add_field(name='Steam Server Wishlist', value='`!wishlist` `!addwishlist <game-name>` `!removewishlist <game-name>`', inline=False)
embed.add_field(name='CS2 Stats', value='`!cs2 <name>`', inline=True)
embed.add_field(name='Today\'s Fortnite Shop', value='`!fn-shop`', inline=True)
embed.add_field(name='Create a QR', value='Color-code should be in Hex format (#FFFFFF)\n`!qr <link> <optional: fg-color> <optional: bg-color>`', inline=False)
embed.add_field(name='Random GIF', value='`!gif`', inline=True)
embed.add_field(name='Currency Converter', value='`!convert <amount> <from-currency> <to-currency>`', inline=False)
embed.add_field(name='Create events!', value='`/event`', inline=True)
# Send the embed message to the same channel where the command was issued
await ctx.channel.send(embed=embed)
# #####################
@bot.command(name='help-music')
async def help_command(ctx):
embed = discord.Embed(
color=discord.Color.red()
)
embed.set_author(name="Music Commands", url="https://github.com/GabeDiniz", icon_url="https://imgur.com/nH32raP.png")
embed.set_thumbnail(url="https://i.imgur.com/nH32raP.png")
embed.add_field(name='Play or queue a song', value='`!play <song-query>`', inline=False)
embed.add_field(name='Skip current song', value='`!skip`', inline=False)
embed.add_field(name='Kick bot from VC', value='`!leave`', inline=False)
# Send the embed message to the same channel where the command was issued
await ctx.channel.send(embed=embed)
# #####################
@bot.command(name='cs2', description='Display Counter-strike 2 stats (only setup for some players).')
async def steam_command(ctx, *, message: str):
embed = steam.get_user_stats(ctx, message)
await ctx.channel.send(embed=embed)
# #####################
@bot.command(name='fn-shop')
async def play_command(ctx):
embed = fortnite.get_shop_items()
await ctx.channel.send(embed=embed)
# #####################
@bot.command(name='qr', description="Generate QR image based on given prompt")
async def play_command(ctx, *, message: str):
qr_code_file = qr.generate(message) # Returns QR file
if qr_code_file:
with open(qr_code_file, 'rb') as f: # Open in Binary format
image = discord.File(f)
embed = discord.Embed(
title='Created New QR',
color=discord.Color.red()
)
embed.set_image(url=f"attachment://{qr_code_file}")
await ctx.channel.send(file=image, embed=embed)
else:
await ctx.channel.send("Failed to generate QR code.")
os.remove("qr.png")
# #####################
@bot.command(name='gif', description="Send a random GIF in the chat")
async def play_command(ctx):
gif = gifs.random_gif()
await ctx.channel.send(gif)
# #####################
@bot.command(name="steamgame", description="Search for a Steam game and return game details")
async def steamgame(ctx, *, game_name: str):
await ctx.send("Searching for game on Steam...")
game_details = steam.search_steam_game(game_name)
if isinstance(game_details, str):
await ctx.send(game_details)
else:
formatted_game_id = steam.reformat_game_id(game_details['name'])
print(f"[ LOG ] Formatted SteamGame ID: {formatted_game_id}")
game_url = f"https://store.steampowered.com/app/{game_details['steam_appid']}/{formatted_game_id}/"
discount = game_details.get('price_overview', {}).get('discount_percent', 0)
embed = discord.Embed(
title=game_details['name'] + f' (ON SALE - {discount}% OFF)' if discount != 0 else game_details['name'],
description=game_details.get('description', 'No description available.'),
color=discord.Color.red() if discount != 0 else discord.Color.purple())
embed.add_field(name="Price", value=f"{game_details['price_overview']['final_formatted']}" if 'price_overview' in game_details else "Free or Price Not Available")
embed.add_field(name="Genres", value=', '.join([genre['description'] for genre in game_details['genres']]))
embed.add_field(name="App ID", value=f"{game_details['steam_appid']}")
embed.add_field(name="Steam Store", value=f"{game_url}", inline=False)
embed.set_thumbnail(url=game_details['header_image'])
await ctx.send(embed=embed)
# #####################
@bot.command(name="addwishlist", description="Add a Steam game to the server wishlist and set default wishlist channel")
async def add_wishlist(ctx, *, game_name: str):
await steam.add_to_wishlist(ctx, game_name, server_wishlists, default_channel)
save_wishlist()
print(default_channel)
save_default_channel()
@bot.command(name="removewishlist", description="Remove a Steam game from the servers wishlist.")
async def remove_wishlist(ctx, *, game_name: str):
await steam.remove_from_wishlist(ctx, game_name, server_wishlists)
save_wishlist()
@bot.command(name="wishlist", description="Display the servers communal wishlist, if it exists.")
async def show_wishlist(ctx):
await steam.show_wishlist(ctx, server_wishlists)
# #####################
@bot.command(name="nfl_matchups", description="Displays information about an NFL league from Sleeper.")
async def nfl_league_info(ctx):
embed = sport_details.fetch_matchup()
await ctx.channel.send(embed=embed)
# #####################
@bot.command(name="nfl_week", description="Displays information about the current weeks NFL matchups from ESPN.")
async def nfl_weekly_matchup(ctx):
embed = sport_details.get_weekly_games()
await ctx.channel.send(embed=embed)
# #####################
@bot.command(name="convert", description="Converts the amount entered from currency A to currency B.")
async def current_converter(ctx, *, args: str):
try:
# Split the input into components
components = args.split()
if len(components) != 3:
await ctx.send("Error: Please provide the correct format: `!convert <amount> <from_currency> <to_currency>`")
return
amount, from_currency, to_currency = components
# Validate and convert the amount
try:
amount = float(amount)
except ValueError:
await ctx.send("Error: Amount must be a valid number.")
return
# Call the currency conversion function
await currency.convert_currency(ctx, amount, from_currency, to_currency)
except Exception as e:
await ctx.send(f"An unexpected error occurred: {e}")
# #####################
# WIP: NOT FUNCTIONING AS IT COSTS MONEY
# @bot.command(name='gpt')
# async def chatgpt(ctx, *, query: str):
# await ctx.typing() # Show typing indicator while processing
# try:
# response = gptClient.chat.completions.create(
# model="gpt-3.5-turbo",
# messages=[
# {"role": "user", "content": query}
# ]
# )
# print(response)
# answer = response.choices[0].message
# await ctx.send(answer)
# except Exception as e:
# await ctx.send(f"An error occurred: {e}")
# ========================================
# SLASH COMMANDS
# ========================================
# #####################
@bot.tree.command(name="event", description="Create an event", guild=None)
@app_commands.describe(date="Date of the event (YYYY-MM-DD)", time="Event time (HH:MM, 24-hour format)", description="Description of event")
async def create_event(interaction: discord.Interaction, date: str, time: str, description: str):
await events.create_event(interaction, date, time, description)
# ========================================
# PLAY MUSIC
# ========================================
@bot.command(name='play')
async def play_command(ctx, *, message: str):
print(ctx)
embed = await playmusic.play_music(ctx, message, bot)
await ctx.channel.send(embed=embed)
@bot.command(name='leave')
async def leave_command(ctx):
embed = await playmusic.leave_channel(ctx)
await ctx.channel.send(embed=embed)
@bot.command(name='skip')
async def skip_command(ctx):
await playmusic.skip_song(ctx, bot)
# ========================================
# CHAT RESPONSES
# ========================================
@bot.event
async def on_message(ctx):
# [TESTING] Check for messages sent by a specific user
# if str(ctx.author) == "emili03x":
# response: str = "msg here"
# elif str(ctx.author) == "<@206888163875094528>" or str(ctx.author) == "@206888163875094528" or str(ctx.author) == "rickeydickey":
# response: str = "msg here"
if ctx.content and ctx.author != bot.user:
print(f'[ {ctx.channel} ] {ctx.author}: "{ctx.content}"')
response = responses.get_response(ctx.content, knowledge=knowledge)
if response:
await ctx.channel.send(response)
# Process commands if they are present
await bot.process_commands(ctx)
# ========================================
# RUN BOT
# ========================================
bot.run(token=BOT_KEY)