-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbot.py
More file actions
178 lines (137 loc) · 4.89 KB
/
bot.py
File metadata and controls
178 lines (137 loc) · 4.89 KB
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
from datetime import datetime, time
import json
import os
from zoneinfo import ZoneInfo
import discord
from discord import app_commands
from discord.ext import commands, tasks
from dotenv import load_dotenv
load_dotenv()
TOKEN = os.getenv("DISCORD_BOT_TOKEN")
COMPS_FILE = "comps.json"
SHOP_STATUS_FILE = "shop_status.json" # Shop status
SHOP_STATUS_CHANNEL_ID = 1329876584534118441 # Shop status channel ID
# load competitions from file
def load_comps():
try:
with open(COMPS_FILE, "r") as f:
return json.load(f)
except FileNotFoundError:
return []
# save competitions to file
def save_comps(comps):
with open(COMPS_FILE, "w") as f:
json.dump(comps, f, indent=2)
# bot setup
intents = discord.Intents.default()
bot = commands.Bot(command_prefix="!", intents=intents)
tree = bot.tree
# Shop status variables
bot.status_msg = None
bot.last_status_msg = None
@tree.command(name="comp", description="List upcoming competitions")
async def comp(interaction: discord.Interaction):
comps = load_comps()
if not comps:
await interaction.response.send_message("No competitions added yet")
return
now = datetime.now(ZoneInfo("America/New_York"))
embed = discord.Embed(
title="Upcoming Competitions 🗓️",
color=discord.Color.blue(),
)
for comp in comps:
comp_time = datetime.strptime(comp["date"], "%Y-%m-%dT%H:%M:%S")
comp_time = comp_time.replace(tzinfo=ZoneInfo("America/New_York"))
remaining = comp_time - now
if remaining.total_seconds() > 0:
embed.add_field(
name=comp["name"],
value=f"**{str(remaining).split('.')[0]}** remaining\n `{comp['date']}`",
inline=False,
)
else:
embed.add_field(
name=comp["name"],
value=f"Already passed\n `{comp['date']}`",
inline=False,
)
await interaction.response.send_message(embed=embed)
@tree.command(name="comp_add", description="Add a new competition")
@app_commands.describe(name="Name of the competition", date="ISO date (e.g. 2025-08-01T18:00:00)")
async def comp_add(interaction: discord.Interaction, name: str, date: str):
try:
datetime.datetime.fromisoformat(date)
except ValueError:
await interaction.response.send_message(
"Invalid date format. Use ISO 8601, e.g., `2025-08-01T18:00:00`", ephemeral=True
)
return
comps = load_comps()
comps.append({"name": name, "date": date})
save_comps(comps)
await interaction.response.send_message(f"Competition **{name}** added for {date}")
@bot.event
async def on_ready():
print(f"Logged in as {bot.user}")
try:
synced = await tree.sync()
print(f"Synced {len(synced)} commands")
channel = await bot.fetch_channel(SHOP_STATUS_CHANNEL_ID)
print(f"Fetched channel: {channel}")
await init_shop_status()
check_updates.start()
except Exception as e:
print(f"Error syncing commands: {e}")
# Load shop status from JSON
async def load_shop_status():
status = ""
try:
with open(SHOP_STATUS_FILE, "r") as f:
data = json.load(f)
return data.get("shop-status", "UNKNOWN")
except json.JSONDecodeError:
# Try not read the json when esp32 writing the json
print("Skipping check")
return bot.last_status_msg or "UNKNOWN"
async def current_shop_status():
now = datetime.now(ZoneInfo("America/New_York")).time()
close = time(23, 0)
open = time(8, 30)
if now >= close or now < open:
return "CLOSED, SWITCH WAS NOT CLOSED"
status = await load_shop_status()
return status
# Embed message for shop status (make it look nice)
async def shop_status_embed(status: str):
if status == "OPEN":
color = discord.Color.green()
else:
color = discord.Color.red()
embed = discord.Embed(
title="Shop Status 🏎",
description=status,
color=color
)
return embed
# Init shop status message
async def init_shop_status():
channel = await bot.fetch_channel(SHOP_STATUS_CHANNEL_ID)
status = await current_shop_status()
embed = await shop_status_embed(status)
bot.last_status_msg = status
bot.status_msg = await channel.send(embed=embed)
# Update shop status message if changed
async def update_shop_status():
channel = await bot.fetch_channel(SHOP_STATUS_CHANNEL_ID)
if bot.status_msg:
status = await current_shop_status()
if status != bot.last_status_msg:
await bot.status_msg.delete()
embed= await shop_status_embed(status)
bot.status_msg = await channel.send(embed=embed)
bot.last_status_msg = status
@tasks.loop(seconds=5) # check every 5 seconds
async def check_updates():
await update_shop_status()
bot.run(TOKEN)