diff --git a/redbot/cogs/filter/filter.py b/redbot/cogs/filter/filter.py index 318aa1d94..b50e5f336 100644 --- a/redbot/cogs/filter/filter.py +++ b/redbot/cogs/filter/filter.py @@ -1,5 +1,6 @@ import discord import re +from datetime import timezone from typing import Union, Set, Literal from redbot.core import checks, Config, modlog, commands @@ -339,10 +340,11 @@ class Filter(commands.Cog): filter_time = guild_data["filterban_time"] user_count = member_data["filter_count"] next_reset_time = member_data["next_reset_time"] + created_at = message.created_at.replace(tzinfo=timezone.utc) if filter_count > 0 and filter_time > 0: - if message.created_at.timestamp() >= next_reset_time: - next_reset_time = message.created_at.timestamp() + filter_time + if created_at.timestamp() >= next_reset_time: + next_reset_time = created_at.timestamp() + filter_time async with self.config.member(author).all() as member_data: member_data["next_reset_time"] = next_reset_time if user_count > 0: @@ -361,10 +363,7 @@ class Filter(commands.Cog): if filter_count > 0 and filter_time > 0: user_count += 1 await self.config.member(author).filter_count.set(user_count) - if ( - user_count >= filter_count - and message.created_at.timestamp() < next_reset_time - ): + if user_count >= filter_count and created_at.timestamp() < next_reset_time: reason = _("Autoban (too many filtered messages.)") try: await guild.ban(author, reason=reason) @@ -374,7 +373,7 @@ class Filter(commands.Cog): await modlog.create_case( self.bot, guild, - message.created_at, + message.created_at.replace(tzinfo=timezone.utc), "filterban", author, guild.me, diff --git a/redbot/cogs/mod/events.py b/redbot/cogs/mod/events.py index a9803753a..ee56e582d 100644 --- a/redbot/cogs/mod/events.py +++ b/redbot/cogs/mod/events.py @@ -1,5 +1,5 @@ import logging -from datetime import datetime +from datetime import timezone from collections import defaultdict, deque import discord @@ -60,7 +60,7 @@ class Events(MixinMeta): await modlog.create_case( self.bot, guild, - message.created_at, + message.created_at.replace(tzinfo=timezone.utc), "ban", author, guild.me, @@ -84,7 +84,7 @@ class Events(MixinMeta): await modlog.create_case( self.bot, guild, - message.created_at, + message.created_at.replace(tzinfo=timezone.utc), "kick", author, guild.me, @@ -116,7 +116,7 @@ class Events(MixinMeta): await modlog.create_case( self.bot, guild, - message.created_at, + message.created_at.replace(tzinfo=timezone.utc), "warning", author, guild.me, diff --git a/redbot/cogs/mod/kickban.py b/redbot/cogs/mod/kickban.py index cfb7be308..4dcd135be 100644 --- a/redbot/cogs/mod/kickban.py +++ b/redbot/cogs/mod/kickban.py @@ -1,7 +1,7 @@ import asyncio import contextlib import logging -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from typing import Optional, Union import discord @@ -120,7 +120,7 @@ class KickBanMixin(MixinMeta): await modlog.create_case( self.bot, guild, - ctx.message.created_at, + ctx.message.created_at.replace(tzinfo=timezone.utc), "ban", user, author, @@ -142,10 +142,11 @@ class KickBanMixin(MixinMeta): async with self.config.guild(guild).current_tempbans() as guild_tempbans: for uid in guild_tempbans.copy(): - unban_time = datetime.utcfromtimestamp( - await self.config.member_from_ids(guild.id, uid).banned_until() + unban_time = datetime.fromtimestamp( + await self.config.member_from_ids(guild.id, uid).banned_until(), + timezone.utc, ) - if datetime.utcnow() > unban_time: # Time to unban the user + if datetime.now(timezone.utc) > unban_time: # Time to unban the user queue_entry = (guild.id, uid) try: await guild.unban( @@ -228,7 +229,7 @@ class KickBanMixin(MixinMeta): await modlog.create_case( self.bot, guild, - ctx.message.created_at, + ctx.message.created_at.replace(tzinfo=timezone.utc), "kick", user, author, @@ -410,7 +411,7 @@ class KickBanMixin(MixinMeta): await modlog.create_case( self.bot, guild, - ctx.message.created_at, + ctx.message.created_at.replace(tzinfo=timezone.utc), "hackban", user_id, author, @@ -436,7 +437,7 @@ class KickBanMixin(MixinMeta): """Temporarily ban a user from this server.""" guild = ctx.guild author = ctx.author - unban_time = datetime.utcnow() + duration + unban_time = datetime.now(timezone.utc) + duration if author == user: await ctx.send( @@ -491,7 +492,7 @@ class KickBanMixin(MixinMeta): await modlog.create_case( self.bot, guild, - ctx.message.created_at, + ctx.message.created_at.replace(tzinfo=timezone.utc), "tempban", user, author, @@ -574,7 +575,7 @@ class KickBanMixin(MixinMeta): await modlog.create_case( self.bot, guild, - ctx.message.created_at, + ctx.message.created_at.replace(tzinfo=timezone.utc), "softban", user, author, @@ -621,7 +622,7 @@ class KickBanMixin(MixinMeta): await modlog.create_case( self.bot, guild, - ctx.message.created_at, + ctx.message.created_at.replace(tzinfo=timezone.utc), "vkick", member, author, @@ -660,7 +661,7 @@ class KickBanMixin(MixinMeta): await modlog.create_case( self.bot, guild, - ctx.message.created_at, + ctx.message.created_at.replace(tzinfo=timezone.utc), "unban", user, author, diff --git a/redbot/cogs/mod/mutes.py b/redbot/cogs/mod/mutes.py index faaab3304..80c3df81d 100644 --- a/redbot/cogs/mod/mutes.py +++ b/redbot/cogs/mod/mutes.py @@ -1,4 +1,5 @@ import asyncio +from datetime import timezone from typing import cast, Optional import discord @@ -107,7 +108,7 @@ class MuteMixin(MixinMeta): await modlog.create_case( self.bot, guild, - ctx.message.created_at, + ctx.message.created_at.replace(tzinfo=timezone.utc), "voiceunban", user, author, @@ -148,7 +149,7 @@ class MuteMixin(MixinMeta): await modlog.create_case( self.bot, guild, - ctx.message.created_at, + ctx.message.created_at.replace(tzinfo=timezone.utc), "voiceban", user, author, @@ -188,7 +189,7 @@ class MuteMixin(MixinMeta): await modlog.create_case( self.bot, guild, - ctx.message.created_at, + ctx.message.created_at.replace(tzinfo=timezone.utc), "vmute", user, author, @@ -232,7 +233,7 @@ class MuteMixin(MixinMeta): await modlog.create_case( self.bot, guild, - ctx.message.created_at, + ctx.message.created_at.replace(tzinfo=timezone.utc), "cmute", user, author, @@ -262,7 +263,7 @@ class MuteMixin(MixinMeta): await modlog.create_case( self.bot, guild, - ctx.message.created_at, + ctx.message.created_at.replace(tzinfo=timezone.utc), "smute", user, author, @@ -305,7 +306,7 @@ class MuteMixin(MixinMeta): await modlog.create_case( self.bot, guild, - ctx.message.created_at, + ctx.message.created_at.replace(tzinfo=timezone.utc), "vunmute", user, author, @@ -349,7 +350,7 @@ class MuteMixin(MixinMeta): await modlog.create_case( self.bot, guild, - ctx.message.created_at, + ctx.message.created_at.replace(tzinfo=timezone.utc), "cunmute", user, author, @@ -383,7 +384,7 @@ class MuteMixin(MixinMeta): await modlog.create_case( self.bot, guild, - ctx.message.created_at, + ctx.message.created_at.replace(tzinfo=timezone.utc), "sunmute", user, author, diff --git a/redbot/cogs/modlog/modlog.py b/redbot/cogs/modlog/modlog.py index 0d1979b8e..845a63a69 100644 --- a/redbot/cogs/modlog/modlog.py +++ b/redbot/cogs/modlog/modlog.py @@ -1,3 +1,4 @@ +from datetime import timezone from typing import Optional, Union import discord @@ -181,7 +182,7 @@ class ModLog(commands.Cog): to_modify = {"reason": reason} if case_obj.moderator != author: to_modify["amended_by"] = author - to_modify["modified_at"] = ctx.message.created_at.timestamp() + to_modify["modified_at"] = ctx.message.created_at.replace(tzinfo=timezone.utc).timestamp() await case_obj.edit(to_modify) await ctx.send( _("Reason for case #{num} has been updated.").format(num=case_obj.case_number) diff --git a/redbot/cogs/warnings/warnings.py b/redbot/cogs/warnings/warnings.py index 9e73692ba..413fd7d76 100644 --- a/redbot/cogs/warnings/warnings.py +++ b/redbot/cogs/warnings/warnings.py @@ -1,5 +1,6 @@ import asyncio import contextlib +from datetime import timezone from collections import namedtuple from copy import copy from typing import Union, Optional, Literal @@ -494,7 +495,7 @@ class Warnings(commands.Cog): await modlog.create_case( self.bot, ctx.guild, - ctx.message.created_at, + ctx.message.created_at.replace(tzinfo=timezone.utc), "warning", user, ctx.message.author, @@ -616,7 +617,7 @@ class Warnings(commands.Cog): await modlog.create_case( self.bot, ctx.guild, - ctx.message.created_at, + ctx.message.created_at.replace(tzinfo=timezone.utc), "unwarned", member, ctx.message.author, diff --git a/redbot/core/bank.py b/redbot/core/bank.py index adee5b322..06c745330 100644 --- a/redbot/core/bank.py +++ b/redbot/core/bank.py @@ -1,8 +1,8 @@ from __future__ import annotations import asyncio -import datetime import logging +from datetime import datetime, timezone from typing import Union, List, Optional, TYPE_CHECKING, Literal from functools import wraps @@ -109,7 +109,7 @@ class Account: This class should ONLY be instantiated by the bank itself.""" - def __init__(self, name: str, balance: int, created_at: datetime.datetime): + def __init__(self, name: str, balance: int, created_at: datetime): self.name = name self.balance = balance self.created_at = created_at @@ -117,25 +117,25 @@ class Account: def _encoded_current_time() -> int: """Get the current UTC time as a timestamp. - + Returns ------- int The current UTC timestamp. """ - now = datetime.datetime.utcnow() + now = datetime.now(timezone.utc) return _encode_time(now) -def _encode_time(time: datetime.datetime) -> int: +def _encode_time(time: datetime) -> int: """Convert a datetime object to a serializable int. - + Parameters ---------- time : datetime.datetime The datetime to convert. - + Returns ------- int @@ -146,21 +146,21 @@ def _encode_time(time: datetime.datetime) -> int: return ret -def _decode_time(time: int) -> datetime.datetime: +def _decode_time(time: int) -> datetime: """Convert a timestamp to a datetime object. - + Parameters ---------- time : int The timestamp to decode. - + Returns ------- datetime.datetime The datetime object from the timestamp. """ - return datetime.datetime.utcfromtimestamp(time) + return datetime.utcfromtimestamp(time) async def get_balance(member: discord.Member) -> int: diff --git a/redbot/core/events.py b/redbot/core/events.py index fe9866567..9763f96b8 100644 --- a/redbot/core/events.py +++ b/redbot/core/events.py @@ -3,10 +3,9 @@ import contextlib import platform import sys import codecs -import datetime import logging import traceback -from datetime import timedelta +from datetime import datetime, timedelta import aiohttp import discord @@ -55,7 +54,7 @@ def init_events(bot, cli_flags): if bot._uptime is not None: return - bot._uptime = datetime.datetime.utcnow() + bot._uptime = datetime.utcnow() guilds = len(bot.guilds) users = len(set([m for m in bot.get_all_members()])) @@ -313,7 +312,7 @@ def init_events(bot, cli_flags): not bot._checked_time_accuracy or (discord_now - timedelta(minutes=60)) > bot._checked_time_accuracy ): - system_now = datetime.datetime.utcnow() + system_now = datetime.utcnow() diff = abs((discord_now - system_now).total_seconds()) if diff > 60: log.warning( diff --git a/redbot/core/modlog.py b/redbot/core/modlog.py index a25a3f1e6..0cf9af524 100644 --- a/redbot/core/modlog.py +++ b/redbot/core/modlog.py @@ -2,7 +2,7 @@ from __future__ import annotations import asyncio import logging -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from typing import List, Literal, Union, Optional, cast, TYPE_CHECKING import discord @@ -127,7 +127,8 @@ async def _init(bot: Red): if entry: if entry.user.id != guild.me.id: # Don't create modlog entires for the bot's own bans, cogs do this. - mod, reason, date = entry.user, entry.reason, entry.created_at + mod, reason = entry.user, entry.reason + date = entry.created_at.replace(tzinfo=timezone.utc) await create_case(_bot_ref, guild, date, "ban", member, mod, reason) return @@ -163,7 +164,8 @@ async def _init(bot: Red): if entry: if entry.user.id != guild.me.id: # Don't create modlog entires for the bot's own unbans, cogs do this. - mod, reason, date = entry.user, entry.reason, entry.created_at + mod, reason = entry.user, entry.reason + date = entry.created_at.replace(tzinfo=timezone.utc) await create_case(_bot_ref, guild, date, "unban", user, mod, reason) return @@ -351,9 +353,9 @@ class Case: until = None duration = None if self.until: - start = datetime.fromtimestamp(self.created_at) - end = datetime.fromtimestamp(self.until) - end_fmt = end.strftime("%Y-%m-%d %H:%M:%S") + start = datetime.utcfromtimestamp(self.created_at) + end = datetime.utcfromtimestamp(self.until) + end_fmt = end.strftime("%Y-%m-%d %H:%M:%S UTC") duration = end - start dur_fmt = _strfdelta(duration) until = end_fmt @@ -374,7 +376,7 @@ class Case: last_modified = None if self.modified_at: last_modified = "{}".format( - datetime.fromtimestamp(self.modified_at).strftime("%Y-%m-%d %H:%M:%S") + datetime.utcfromtimestamp(self.modified_at).strftime("%Y-%m-%d %H:%M:%S UTC") ) if isinstance(self.user, int): @@ -413,7 +415,7 @@ class Case: emb.add_field(name=_("Amended by"), value=amended_by) if last_modified: emb.add_field(name=_("Last modified at"), value=last_modified) - emb.timestamp = datetime.fromtimestamp(self.created_at) + emb.timestamp = datetime.utcfromtimestamp(self.created_at) return emb else: user = filter_mass_mentions(filter_urls(user)) # Further sanitization outside embeds diff --git a/tests/cogs/test_mod.py b/tests/cogs/test_mod.py index a82ed27c3..0d2908a4f 100644 --- a/tests/cogs/test_mod.py +++ b/tests/cogs/test_mod.py @@ -12,7 +12,7 @@ async def test_modlog_register_casetype(mod): @pytest.mark.asyncio async def test_modlog_case_create(mod, ctx, member_factory): - from datetime import datetime as dt + from datetime import datetime, timezone # Run casetype register test to register casetype in this test too await test_modlog_register_casetype(mod) @@ -23,7 +23,7 @@ async def test_modlog_case_create(mod, ctx, member_factory): case_type = "ban" moderator = ctx.author reason = "Test 12345" - created_at = dt.utcnow() + created_at = datetime.now(timezone.utc) case = await mod.create_case(bot, guild, created_at, case_type, usr, moderator, reason) assert case is not None assert case.user == usr