use timezone-aware datetimes everywhere

This commit is contained in:
leander committed 2026-10-24 18:14:43 +02:00
1 parent a2cc923f13
commit d6bdc4926c
12 files changed
+115 -49

No files matched your search

+3 -1
View File
@@ -6,6 +6,7 @@ from discord import app_commands
from discord.ext import commands from discord.ext import commands
from cogs.utils import embed_templates from cogs.utils import embed_templates
from cogs.utils import misc_utils
class Anime(commands.Cog): class Anime(commands.Cog):
@@ -300,7 +301,8 @@ class Anime(commands.Cog):
year, month, day = date.get("year"), date.get("month"), date.get("day") year, month, day = date.get("year"), date.get("month"), date.get("day")
if year and month and day: if year and month and day:
return discord.utils.format_dt(datetime(year, month, day), style="d") date = misc_utils.localize(datetime(year, month, day), self.bot.timezone)
return discord.utils.format_dt(date, style="d")
return f"{day or '?'}.{month or '?'}.{year or '?'}" return f"{day or '?'}.{month or '?'}.{year or '?'}"
def construct_release_schedule_string(self, start_date: dict, end_date: dict) -> str: def construct_release_schedule_string(self, start_date: dict, end_date: dict) -> str:
+4 -4
View File
@@ -21,7 +21,7 @@ class Aurora(commands.Cog):
self.bot = bot self.bot = bot
self.notified = datetime(2000, 9, 11) # Used to prevent spamming aurora alerts self.notified = datetime(2000, 9, 11, tzinfo=timezone.utc) # Used to prevent spamming aurora alerts
self.aurora_alarm.start() self.aurora_alarm.start()
def cog_unload(self): def cog_unload(self):
@@ -46,7 +46,7 @@ class Aurora(commands.Cog):
self.bot.logger.warning("Failed to get forecast data") self.bot.logger.warning("Failed to get forecast data")
return None return None
now = datetime.now(timezone.utc) now = discord.utils.utcnow()
valid_sightings = [] valid_sightings = []
for interval in data["shortIntervals"]: for interval in data["shortIntervals"]:
start = datetime.fromisoformat(interval["start"]) start = datetime.fromisoformat(interval["start"])
@@ -82,7 +82,7 @@ class Aurora(commands.Cog):
await self.bot.wait_until_ready() # Make sure we can fetch the #general channel await self.bot.wait_until_ready() # Make sure we can fetch the #general channel
if datetime.now() - self.notified < timedelta(hours=12): if discord.utils.utcnow() - self.notified < timedelta(hours=12):
self.bot.logger.info( self.bot.logger.info(
"aurora_alarm: Not sending aurora alert because it has been less than 12 hours since last alert" "aurora_alarm: Not sending aurora alert because it has been less than 12 hours since last alert"
) )
@@ -121,7 +121,7 @@ class Aurora(commands.Cog):
content="SJANSE FOR NORDLYS AKKURAT NÅ PÅ NEUF! Se ut vinduet istedenfor på den dumme skjermen din", content="SJANSE FOR NORDLYS AKKURAT NÅ PÅ NEUF! Se ut vinduet istedenfor på den dumme skjermen din",
embed=embed, embed=embed,
) )
self.notified = datetime.now() # Update the last notification time self.notified = discord.utils.utcnow() # Update the last notification time
async def setup(bot: commands.Bot): async def setup(bot: commands.Bot):
+42 -18
View File
@@ -61,19 +61,23 @@ class Birthday(commands.Cog):
self.bot.logger.info("Checking for birthdays") self.bot.logger.info("Checking for birthdays")
birthdays = await self.bot.db.fetchall(""" today = self.local_today()
birthdays = await self.bot.db.fetchall(
"""
SELECT * SELECT *
FROM birthdays FROM birthdays
WHERE ( WHERE (
EXTRACT(MONTH FROM birthday) = EXTRACT(MONTH FROM current_date) EXTRACT(MONTH FROM birthday) = EXTRACT(MONTH FROM %(today)s)
AND EXTRACT(DAY FROM birthday) = EXTRACT(DAY FROM current_date) AND EXTRACT(DAY FROM birthday) = EXTRACT(DAY FROM %(today)s)
) OR ( ) OR (
-- Celebrate 29 February birthdays on 28 February in years that aren't leap years -- Celebrate 29 February birthdays on 28 February in years that aren't leap years
to_char(birthday, 'MM-DD') = '02-29' to_char(birthday, 'MM-DD') = '02-29'
AND to_char(current_date, 'MM-DD') = '02-28' AND to_char(%(today)s, 'MM-DD') = '02-28'
AND to_char(current_date + 1, 'MM-DD') = '03-01' AND to_char(%(today)s + 1, 'MM-DD') = '03-01'
); );
""") """,
{"today": today.date()},
)
self.bot.logger.info(f"Found the following birthdays: {birthdays}") self.bot.logger.info(f"Found the following birthdays: {birthdays}")
@@ -93,7 +97,7 @@ class Birthday(commands.Cog):
continue continue
date = datetime(birthday[1].year, birthday[1].month, birthday[1].day) date = datetime(birthday[1].year, birthday[1].month, birthday[1].day)
years_old = relativedelta(datetime.now(), date).years years_old = relativedelta(today, date).years
# Is it inefficent to define a list of greetings per iteration? Yes # Is it inefficent to define a list of greetings per iteration? Yes
# Am I hoping python somehow will automatically optimize my code? Yes # Am I hoping python somehow will automatically optimize my code? Yes
@@ -144,6 +148,16 @@ class Birthday(commands.Cog):
self.bot.logger.info("Unloading cog") self.bot.logger.info("Unloading cog")
self.birthday_check.cancel() self.birthday_check.cancel()
def local_today(self) -> datetime:
"""
Returns
----------
(datetime): Midnight today in the bot's time zone, as a naive datetime to compare with birthdays
"""
now = discord.utils.utcnow().astimezone(self.bot.timezone)
return datetime(now.year, now.month, now.day)
async def fetch_user_birthday(self, user_id: int) -> datetime | None: async def fetch_user_birthday(self, user_id: int) -> datetime | None:
""" """
Fetch the birthday of a user in the database Fetch the birthday of a user in the database
@@ -177,18 +191,19 @@ class Birthday(commands.Cog):
results = await self.bot.db.fetchone( results = await self.bot.db.fetchone(
""" """
SELECT *, CAST(birthday + ((EXTRACT(YEAR FROM AGE(birthday)) + 1) * interval '1' YEAR) AS DATE) AS next_bday SELECT *,
CAST(birthday + ((EXTRACT(YEAR FROM AGE(%s, birthday)) + 1) * interval '1' YEAR) AS DATE) AS next_bday
FROM birthdays FROM birthdays
WHERE discord_id = %s WHERE discord_id = %s
""", """,
(user_id,), (self.local_today().date(), user_id),
) )
if results: if results:
birthday = results[2] birthday = results[2]
return datetime(birthday.year, birthday.month, birthday.day) return datetime(birthday.year, birthday.month, birthday.day)
else: else:
# This will never happen unless a database error occurs. Keeping the type checker happy # This will never happen unless a database error occurs. Keeping the type checker happy
return datetime.now() return self.local_today()
async def fetch_next_birthdays(self) -> list[tuple[int, datetime, datetime]]: async def fetch_next_birthdays(self) -> list[tuple[int, datetime, datetime]]:
""" """
@@ -199,11 +214,15 @@ class Birthday(commands.Cog):
(list[tuple[int, datetime, datetime]]): List of tuples containing the user ID, date of birth and next birthday (list[tuple[int, datetime, datetime]]): List of tuples containing the user ID, date of birth and next birthday
""" """
results = await self.bot.db.fetchall(""" results = await self.bot.db.fetchall(
SELECT *, CAST(birthday + ((EXTRACT(YEAR FROM AGE(birthday)) + 1) * interval '1' YEAR) AS DATE) AS next_bday """
SELECT *,
CAST(birthday + ((EXTRACT(YEAR FROM AGE(%s, birthday)) + 1) * interval '1' YEAR) AS DATE) AS next_bday
FROM birthdays FROM birthdays
ORDER BY next_bday ASC ORDER BY next_bday ASC
""") """,
(self.local_today().date(),),
)
# Convert date objects to datetime objects # Convert date objects to datetime objects
birthdays = [] birthdays = []
@@ -268,7 +287,7 @@ class Birthday(commands.Cog):
ephemeral=True, ephemeral=True,
) )
if date > datetime.now(): if date > self.local_today():
return await interaction.response.send_message( return await interaction.response.send_message(
embed=embed_templates.error_warning("Du kan ikke sette en fremtidig dato!"), embed=embed_templates.error_warning("Du kan ikke sette en fremtidig dato!"),
ephemeral=True, ephemeral=True,
@@ -276,6 +295,7 @@ class Birthday(commands.Cog):
await self.set_user_birthday(interaction.user.id, date) await self.set_user_birthday(interaction.user.id, date)
date = misc_utils.localize(date, self.bot.timezone)
embed = embed_templates.success(f"Bursdag satt til {discord.utils.format_dt(date, style='D')}") embed = embed_templates.success(f"Bursdag satt til {discord.utils.format_dt(date, style='D')}")
await interaction.response.send_message(embed=embed) await interaction.response.send_message(embed=embed)
@@ -322,13 +342,14 @@ class Birthday(commands.Cog):
) )
# Current age information # Current age information
today = self.local_today()
birthday = datetime(user.year, user.month, user.day) birthday = datetime(user.year, user.month, user.day)
days_old = (datetime.now() - birthday).days days_old = (today - birthday).days
years_old = relativedelta(datetime.now(), birthday).years years_old = relativedelta(today, birthday).years
# Next birthday information # Next birthday information
next_birthday = await self.fetch_user_next_birthday(bruker.id) next_birthday = await self.fetch_user_next_birthday(bruker.id)
next_birthday_days = (next_birthday.date() - datetime.now().date()).days next_birthday_days = (next_birthday - today).days
# Japanese era # Japanese era
japanese_era = EraDate.from_date(birthday).strftime("%-K%-y年") japanese_era = EraDate.from_date(birthday).strftime("%-K%-y年")
@@ -336,7 +357,9 @@ class Birthday(commands.Cog):
embed = discord.Embed(description=bruker.mention, color=bruker.color) embed = discord.Embed(description=bruker.mention, color=bruker.color)
embed.set_thumbnail(url=bruker.display_avatar) embed.set_thumbnail(url=bruker.display_avatar)
embed.set_author(name=bruker.name, icon_url=bruker.display_avatar) embed.set_author(name=bruker.name, icon_url=bruker.display_avatar)
embed.add_field(name="Bursdag", value=discord.utils.format_dt(birthday, style="D")) embed.add_field(
name="Bursdag", value=discord.utils.format_dt(misc_utils.localize(birthday, self.bot.timezone), style="D")
)
embed.add_field(name="Hvor gammel?", value=f"{years_old} år\n({days_old} dager)", inline=False) embed.add_field(name="Hvor gammel?", value=f"{years_old} år\n({days_old} dager)", inline=False)
embed.add_field(name="Weeb age", value=japanese_era, inline=False) embed.add_field(name="Weeb age", value=japanese_era, inline=False)
embed.add_field( embed.add_field(
@@ -378,6 +401,7 @@ class Birthday(commands.Cog):
except (discord.NotFound, discord.HTTPException): except (discord.NotFound, discord.HTTPException):
continue continue
next_birthday = misc_utils.localize(next_birthday, self.bot.timezone)
timestamp = discord.utils.format_dt(next_birthday, style="D") timestamp = discord.utils.format_dt(next_birthday, style="D")
relative_timestamp = discord.utils.format_dt(next_birthday, style="R") relative_timestamp = discord.utils.format_dt(next_birthday, style="R")
birthday_strings.append(f"* {discord_user.name} - {timestamp} ({relative_timestamp})") birthday_strings.append(f"* {discord_user.name} - {timestamp} ({relative_timestamp})")
+3 -4
View File
@@ -1,7 +1,6 @@
import asyncio import asyncio
import json import json
import random import random
from datetime import datetime
from datetime import timedelta from datetime import timedelta
from io import BytesIO from io import BytesIO
from typing import override from typing import override
@@ -46,7 +45,7 @@ class CS2Bingo(commands.Cog):
""" """
if lobby := self.active_lobbies.get(str(interaction.user.id), None): if lobby := self.active_lobbies.get(str(interaction.user.id), None):
if lobby.ends < datetime.now(): if lobby.ends < discord.utils.utcnow():
self.active_lobbies.pop(str(interaction.user.id)) self.active_lobbies.pop(str(interaction.user.id))
else: else:
return await interaction.response.send_message( return await interaction.response.send_message(
@@ -54,7 +53,7 @@ class CS2Bingo(commands.Cog):
) )
for lobby in self.active_lobbies.values(): for lobby in self.active_lobbies.values():
if lobby.ends > datetime.now() and any(p.id == interaction.user.id for p in lobby.players): if lobby.ends > discord.utils.utcnow() and any(p.id == interaction.user.id for p in lobby.players):
return await interaction.response.send_message( return await interaction.response.send_message(
embed=embed_templates.error_warning("Du er allerede i en lobby") embed=embed_templates.error_warning("Du er allerede i en lobby")
) )
@@ -62,7 +61,7 @@ class CS2Bingo(commands.Cog):
self.active_lobbies[str(interaction.user.id)] = Lobby( self.active_lobbies[str(interaction.user.id)] = Lobby(
host=interaction.user, host=interaction.user,
players=[interaction.user], players=[interaction.user],
ends=datetime.now() + timedelta(minutes=10), ends=discord.utils.utcnow() + timedelta(minutes=10),
kicked_players=[], kicked_players=[],
) )
+4 -3
View File
@@ -1,6 +1,7 @@
import random import random
import re import re
from datetime import datetime from datetime import datetime
from datetime import timezone
import discord import discord
from discord.ext import commands from discord.ext import commands
@@ -21,7 +22,7 @@ class FunReplies(commands.Cog):
# This is kind of a shitty way to do it but I'm too lazy to implement anything good right now # This is kind of a shitty way to do it but I'm too lazy to implement anything good right now
self.cooldown_seconds = 600 self.cooldown_seconds = 600
initial_datetime = datetime( initial_datetime = datetime(
2000, 9, 11 2000, 9, 11, tzinfo=timezone.utc
) # Set initial datetime far in the past to allow triggering right after boot ) # Set initial datetime far in the past to allow triggering right after boot
self.previous_invokations = { self.previous_invokations = {
"olof palme": initial_datetime, "olof palme": initial_datetime,
@@ -101,12 +102,12 @@ class FunReplies(commands.Cog):
bool: Whether or not the reply was triggered bool: Whether or not the reply was triggered
""" """
if (datetime.now() - self.previous_invokations[cooldown_key]).total_seconds() < self.cooldown_seconds: if (discord.utils.utcnow() - self.previous_invokations[cooldown_key]).total_seconds() < self.cooldown_seconds:
return False return False
if re.search(regex_match, message.content, flags=regex_flags) and random.randint(1, 100) <= trigger_chance: if re.search(regex_match, message.content, flags=regex_flags) and random.randint(1, 100) <= trigger_chance:
await message.reply(reply) await message.reply(reply)
self.previous_invokations[cooldown_key] = datetime.now() self.previous_invokations[cooldown_key] = discord.utils.utcnow()
return True return True
return False return False
+2
View File
@@ -5,6 +5,7 @@ from discord import app_commands
from discord.ext import commands from discord.ext import commands
from cogs.utils import embed_templates from cogs.utils import embed_templates
from cogs.utils import misc_utils
class Galtinn(commands.Cog): class Galtinn(commands.Cog):
@@ -113,6 +114,7 @@ class Galtinn(commands.Cog):
membership_status = "Ja" if last_membership["is_valid"] else "Nei" membership_status = "Ja" if last_membership["is_valid"] else "Nei"
if last_membership["membership_type"] != "lifelong": if last_membership["membership_type"] != "lifelong":
expiration_date = datetime.strptime(last_membership["end_date"], "%Y-%m-%d") expiration_date = datetime.strptime(last_membership["end_date"], "%Y-%m-%d")
expiration_date = misc_utils.localize(expiration_date, self.bot.timezone)
expires = discord.utils.format_dt(expiration_date, "D") expires = discord.utils.format_dt(expiration_date, "D")
time_left = discord.utils.format_dt(expiration_date, "R") time_left = discord.utils.format_dt(expiration_date, "R")
+8 -2
View File
@@ -14,6 +14,7 @@ from PIL import ImageFont
from cogs.utils import discord_utils from cogs.utils import discord_utils
from cogs.utils import embed_templates from cogs.utils import embed_templates
from cogs.utils import misc_utils
class Misc(commands.Cog): class Misc(commands.Cog):
@@ -214,7 +215,7 @@ class Misc(commands.Cog):
""" """
land = land.upper() land = land.upper()
år = datetime.now().year if not år else int(år) år = discord.utils.utcnow().astimezone(self.bot.timezone).year if not år else int(år)
async with self.bot.http_session.get(f"https://date.nager.at/api/v3/publicholidays/{år}/{land}") as response: async with self.bot.http_session.get(f"https://date.nager.at/api/v3/publicholidays/{år}/{land}") as response:
if response.status not in (200, 204): if response.status not in (200, 204):
@@ -231,7 +232,8 @@ class Misc(commands.Cog):
# Construct output # Construct output
holiday_str = "" holiday_str = ""
for day in data: for day in data:
date = discord.utils.format_dt(datetime.strptime(day["date"], "%Y-%m-%d"), style="D") date = datetime.strptime(day["date"], "%Y-%m-%d")
date = discord.utils.format_dt(misc_utils.localize(date, self.bot.timezone), style="D")
holiday_str += f'* **{date}**: {day["localName"]}\n' holiday_str += f'* **{date}**: {day["localName"]}\n'
embed = discord.Embed( embed = discord.Embed(
@@ -358,6 +360,10 @@ class Misc(commands.Cog):
parsed_time = dateparser.parse( parsed_time = dateparser.parse(
tekst, tekst,
languages=["nb", "nn", "en"], languages=["nb", "nn", "en"],
settings={
"TIMEZONE": str(self.bot.timezone) if self.bot.timezone else "local",
"RETURN_AS_TIMEZONE_AWARE": True,
},
) )
if not parsed_time: if not parsed_time:
embed = embed_templates.error_warning("Forstod ikke tidspunktet. Prøv å skrive det på en annen måte.") embed = embed_templates.error_warning("Forstod ikke tidspunktet. Prøv å skrive det på en annen måte.")
+4 -4
View File
@@ -1,5 +1,4 @@
import random import random
from datetime import datetime
import discord import discord
from discord.ext import commands from discord.ext import commands
@@ -41,7 +40,7 @@ class RepeatedMessages(commands.Cog):
Sends a message on Friday at 00:00 Sends a message on Friday at 00:00
""" """
if datetime.now().weekday() != 4: if discord.utils.utcnow().astimezone(self.bot.timezone).weekday() != 4:
return return
if not (channel := self.get_general_channel()): if not (channel := self.get_general_channel()):
@@ -73,7 +72,7 @@ class RepeatedMessages(commands.Cog):
""" """
Sends a message on Monday at 00:00 Sends a message on Monday at 00:00
""" """
if datetime.now().weekday() != 0: if discord.utils.utcnow().astimezone(self.bot.timezone).weekday() != 0:
return return
if not (channel := self.get_general_channel()): if not (channel := self.get_general_channel()):
return return
@@ -90,7 +89,8 @@ class RepeatedMessages(commands.Cog):
Sends a message on New Year's Day at 00:00 Sends a message on New Year's Day at 00:00
""" """
if datetime.now().month != 1 or datetime.now().day != 1: today = discord.utils.utcnow().astimezone(self.bot.timezone)
if today.month != 1 or today.day != 1:
return return
if not (channel := self.get_general_channel()): if not (channel := self.get_general_channel()):
+17 -1
View File
@@ -50,10 +50,26 @@ class StarboardScraper(commands.Cog):
CREATE TABLE IF NOT EXISTS starboard_scraper_state ( CREATE TABLE IF NOT EXISTS starboard_scraper_state (
id INTEGER PRIMARY KEY DEFAULT 1, id INTEGER PRIMARY KEY DEFAULT 1,
last_scraped_message_id BIGINT, last_scraped_message_id BIGINT,
last_scrape_time TIMESTAMP, last_scrape_time TIMESTAMPTZ,
CHECK (id = 1) CHECK (id = 1)
) )
""") """)
await self.bot.db.execute("""
DO $$
BEGIN
IF (
SELECT data_type
FROM information_schema.columns
WHERE table_schema = current_schema()
AND table_name = 'starboard_scraper_state'
AND column_name = 'last_scrape_time'
) = 'timestamp without time zone' THEN
ALTER TABLE starboard_scraper_state
ALTER COLUMN last_scrape_time TYPE TIMESTAMPTZ
USING last_scrape_time AT TIME ZONE 'Europe/Oslo';
END IF;
END $$;
""")
async def get_last_scraped_message_id(self): async def get_last_scraped_message_id(self):
""" """
+3 -4
View File
@@ -6,7 +6,6 @@ Below you will see a lot of stupid shit. Pls ignore
""" """
import random import random
from datetime import datetime
from datetime import timedelta from datetime import timedelta
from typing import override from typing import override
@@ -47,7 +46,7 @@ class TenMan(commands.Cog):
""" """
if lobby := self.active_lobbies.get(str(interaction.user.id), None): if lobby := self.active_lobbies.get(str(interaction.user.id), None):
if lobby.ends < datetime.now(): if lobby.ends < discord.utils.utcnow():
self.active_lobbies.pop(str(interaction.user.id)) self.active_lobbies.pop(str(interaction.user.id))
else: else:
return await interaction.response.send_message( return await interaction.response.send_message(
@@ -57,7 +56,7 @@ class TenMan(commands.Cog):
) )
for lobby in self.active_lobbies.values(): for lobby in self.active_lobbies.values():
if lobby.ends > datetime.now() and any(p.id == interaction.user.id for p in lobby.players): if lobby.ends > discord.utils.utcnow() and any(p.id == interaction.user.id for p in lobby.players):
return await interaction.response.send_message( return await interaction.response.send_message(
embed=embed_templates.error_warning( embed=embed_templates.error_warning(
"Du er allerede i en lobby", "Du er allerede i en lobby",
@@ -67,7 +66,7 @@ class TenMan(commands.Cog):
self.active_lobbies[str(interaction.user.id)] = Lobby( self.active_lobbies[str(interaction.user.id)] = Lobby(
host=interaction.user, host=interaction.user,
players=[interaction.user], players=[interaction.user],
ends=datetime.now() + timedelta(minutes=30), ends=discord.utils.utcnow() + timedelta(minutes=30),
kicked_players=[], kicked_players=[],
) )
+8 -8
View File
@@ -191,7 +191,7 @@ class Lobby:
class LobbyView(discord.ui.View): class LobbyView(discord.ui.View):
def __init__(self, lobby: Lobby, bot: commands.Bot): def __init__(self, lobby: Lobby, bot: commands.Bot):
lobby_end = (lobby.ends - datetime.now()).total_seconds() lobby_end = (lobby.ends - discord.utils.utcnow()).total_seconds()
super().__init__(timeout=lobby_end) super().__init__(timeout=lobby_end)
self.lobby = lobby self.lobby = lobby
@@ -210,7 +210,7 @@ class LobbyView(discord.ui.View):
pass pass
async def end_lobby(self): async def end_lobby(self):
self.lobby.ends = datetime.now() self.lobby.ends = discord.utils.utcnow()
for item in self.children: for item in self.children:
item.disabled = True item.disabled = True
@@ -225,7 +225,7 @@ class LobbyView(discord.ui.View):
@discord.ui.button(label="Bli med", style=discord.ButtonStyle.blurple) @discord.ui.button(label="Bli med", style=discord.ButtonStyle.blurple)
async def join_lobby(self, interaction: discord.Interaction, button: discord.ui.Button): async def join_lobby(self, interaction: discord.Interaction, button: discord.ui.Button):
if datetime.now() > self.lobby.ends: if discord.utils.utcnow() > self.lobby.ends:
embed = embed_templates.error_warning("Lobbyen har allerede startet") embed = embed_templates.error_warning("Lobbyen har allerede startet")
return await interaction.response.send_message(embed=embed, ephemeral=True, delete_after=10) return await interaction.response.send_message(embed=embed, ephemeral=True, delete_after=10)
@@ -289,7 +289,7 @@ class LobbyView(discord.ui.View):
embed = embed_templates.error_warning("Bare hosten kan slette lobbyen") embed = embed_templates.error_warning("Bare hosten kan slette lobbyen")
return await interaction.response.send_message(embed=embed, ephemeral=True, delete_after=10) return await interaction.response.send_message(embed=embed, ephemeral=True, delete_after=10)
self.lobby.ends = datetime.now() self.lobby.ends = discord.utils.utcnow()
await interaction.message.delete() await interaction.message.delete()
embed = embed_templates.success("Lobbyen har blitt slettet") embed = embed_templates.success("Lobbyen har blitt slettet")
@@ -418,7 +418,7 @@ class TempVoiceHelper:
continue continue
if len(channel.members) == 0: if len(channel.members) == 0:
self.temp_vc_channels[channel]["no_members_since"] = datetime.now() self.temp_vc_channels[channel]["no_members_since"] = discord.utils.utcnow()
self.bot.logger.info(f"Temporary voice channel {channel} has no members. Will be deleted in 1 minutes") self.bot.logger.info(f"Temporary voice channel {channel} has no members. Will be deleted in 1 minutes")
else: else:
self.temp_vc_channels[channel]["no_members_since"] = None self.temp_vc_channels[channel]["no_members_since"] = None
@@ -434,7 +434,7 @@ class TempVoiceHelper:
if not data["no_members_since"]: if not data["no_members_since"]:
continue continue
if (datetime.now() - data["no_members_since"]).total_seconds() >= 60: if (discord.utils.utcnow() - data["no_members_since"]).total_seconds() >= 60:
try: try:
await channel.delete(reason="tempvoice kanal inaktiv i 1 minutt") await channel.delete(reason="tempvoice kanal inaktiv i 1 minutt")
except discord.NotFound: except discord.NotFound:
@@ -470,7 +470,7 @@ class TempVoiceHelper:
await self.forget(channel_id) await self.forget(channel_id)
continue continue
now = datetime.now() now = discord.utils.utcnow()
self.temp_vc_channels[channel] = {"created": now, "no_members_since": None if channel.members else now} self.temp_vc_channels[channel] = {"created": now, "no_members_since": None if channel.members else now}
restored += 1 restored += 1
@@ -514,7 +514,7 @@ class TempVoiceHelper:
self.bot.logger.info(f"Created temporary voice channel {channel} in {interaction.guild}") self.bot.logger.info(f"Created temporary voice channel {channel} in {interaction.guild}")
now = datetime.now() now = discord.utils.utcnow()
self.temp_vc_channels[channel] = {"created": now, "no_members_since": now} self.temp_vc_channels[channel] = {"created": now, "no_members_since": now}
await self.remember(channel) await self.remember(channel)
+17
View File
@@ -16,6 +16,23 @@ from PIL import ImageFont
MIDNIGHT = datetime.time(hour=0, minute=0, tzinfo=ZoneInfo("Europe/Oslo")) MIDNIGHT = datetime.time(hour=0, minute=0, tzinfo=ZoneInfo("Europe/Oslo"))
def localize(dt: datetime.datetime, tz: datetime.tzinfo | None) -> datetime.datetime:
"""
Attach a time zone to a naive datetime without changing its wall time
Parameters
----------
dt (datetime.datetime): The naive datetime
tz (datetime.tzinfo | None): The time zone. None means the system time zone
Returns
----------
(datetime.datetime): The aware datetime
"""
return dt.replace(tzinfo=tz) if tz else dt.astimezone()
# The exceptions discord.py's tasks.loop retries instead of stopping on # The exceptions discord.py's tasks.loop retries instead of stopping on
RETRIED_TASK_EXCEPTIONS = ( RETRIED_TASK_EXCEPTIONS = (
OSError, OSError,