-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
142 lines (116 loc) · 4.37 KB
/
main.py
File metadata and controls
142 lines (116 loc) · 4.37 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
import asyncio
import datetime
from collections import namedtuple
from discord import utils, Embed, Colour, Intents
from discord.ext import commands
import pytz
from helper import to_local_time, format_time, local_now
import secret
# Bot setup
# We need permissions for sending messages, adding reactions, and managing messages
intents = Intents.all()
bot = commands.Bot(command_prefix=secret.CONTROL_PREFIX, intents=intents)
@bot.event
async def on_ready():
"""
Prints a message when the bot is ready and starts the event loop.
"""
print(f"Logged in as {bot.user}")
# Start the event loop
bot.loop.create_task(event_loop())
@bot.event
async def on_reaction_add(reaction, user):
"""
Handles reactions to the control channel messages.
"""
# Check if the reaction is to a control channel message
if reaction.message.channel.id != secret.CONTROL_CHANNEL:
return
# Check if the user has the control role
if not utils.get(user.roles, id=secret.CONTROL_ROLE):
return
# Check if the reaction is the cancel emoji
if reaction.emoji != "❌":
return
# Cancel the event
await cancel_event(reaction.message)
async def event_loop():
"""
The main event loop that sends reminders and messages at the scheduled times.
"""
# Get the current events
events = [e for e in sorted(secret.SCHEDULE) if e > local_now()]
# Get the next event
print("Processing events...")
next_event = events[0]
# Calculate the time until the event
delta = next_event.datetime - local_now()
hours, remainder = divmod(int(delta.total_seconds()), 3600)
minutes, seconds = divmod(remainder, 60)
# Wait until a few hours before the start
warning_window = datetime.timedelta(hours=secret.WARNING_WINDOW)
print(f"Waiting {delta - warning_window} until next event warning")
await asyncio.sleep((delta - warning_window).total_seconds())
# Send the reminder to the control channel
control_channel = bot.get_channel(secret.CONTROL_CHANNEL)
control_role = utils.get(control_channel.guild.roles, id=secret.CONTROL_ROLE)
embed = Embed(
title="Notice: Upcoming event",
description=next_event.message,
colour=Colour.orange()
)
embed.add_field(name="Day", value=next_event.datetime.strftime("%A"))
embed.add_field(name="Time", value=format_time(next_event.datetime.time()))
embed.add_field(name="Time until event", value=f"{hours} hours {minutes} minutes")
message = await control_channel.send(embed=embed)
await control_channel.send(f"{control_role.mention} Event starting soon!")
# Add the cancel emoji to the message
await message.add_reaction("❌")
# Wait until the event, or until it's cancelled
print("Waiting for event")
await asyncio.sleep((next_event.datetime - local_now()).total_seconds())
# If the event hasn't been cancelled, send the message
if message.channel:
await send_message(None, message=next_event.message)
else:
print("Event cancelled, nothing to do")
# Restart the event loop
bot.loop.create_task(event_loop())
async def cancel_event(message):
"""
Cancels an event and sends a message to the control channel.
"""
print("Trying to cancel event")
# Remove the original message
await message.delete()
# Send a message to the control channel
control_channel = bot.get_channel(secret.CONTROL_CHANNEL)
await control_channel.send("Event cancelled.")
@bot.command()
@commands.has_role(secret.CONTROL_ROLE)
async def list_events(ctx):
"""
lists the scheduled events.
"""
# Format the events as a string
event_str = "\n".join([f"- {event[1]}" for event in secret.SCHEDULE])
# Send the list of events to the channel
await ctx.send(f"Scheduled events:\n{event_str}")
@bot.command()
@commands.has_role(secret.CONTROL_ROLE)
async def send_message(ctx, *, message: str):
"""
Sends a message to the configured channel and role.
"""
# Get the channel and role
channel = bot.get_channel(secret.CHANNEL)
role = utils.get(channel.guild.roles, id=secret.ROLE)
# Send the message to the channel and role
await channel.send(f"{role.mention} {message}")
# Simple ping command
@bot.command()
async def ping(ctx):
await ctx.send("pong")
## Run the bot
if __name__ == "__main__":
bot.run(secret.TOKEN)