diff --git a/components/admin.py b/components/admin.py index a753d36..2a39427 100644 --- a/components/admin.py +++ b/components/admin.py @@ -2,7 +2,7 @@ import sys from datetime import datetime from sys import exit -from typing import Any, Dict, List, Optional, Union +from typing import Any import hikari import tanjun @@ -48,10 +48,10 @@ @tanjun.as_slash_command("unban", "Unban a user from the current server.") async def CommandUnban( ctx: SlashContext, - user: Union[InteractionMember, UserImpl], + user: InteractionMember | UserImpl, reason: str, client: Client = tanjun.inject(type=Client), - config: Dict[str, Any] = tanjun.inject(type=Dict[str, Any]), + config: dict[str, Any] = tanjun.inject(type=dict[str, Any]), ) -> None: """Handler for the /unban slash command.""" @@ -100,9 +100,7 @@ async def CommandUnban( @tanjun.with_own_permission_check(Permissions.SEND_MESSAGES) @tanjun.with_user_slash_option("user", "Enter a user to fetch the profile of.") @tanjun.as_slash_command("profile", "Fetch detailed information about a Discord user.") -async def CommandProfile( - ctx: SlashContext, user: Union[InteractionMember, UserImpl] -) -> None: +async def CommandProfile(ctx: SlashContext, user: InteractionMember | UserImpl) -> None: """Handler for the /profile slash command.""" if hasattr(user, "user"): @@ -113,9 +111,9 @@ async def CommandProfile( f"Failed to fetch user {Responses.ExpandUser(user.id, False)}" ) - fields: List[Dict[str, Any]] = [] - altAvatar: Optional[str] = None - accent: Optional[str] = None + fields: list[dict[str, Any]] = [] + altAvatar: str | None = None + accent: str | None = None if hasattr(user, "nickname"): if (nickname := user.nickname) is not None: @@ -188,11 +186,11 @@ async def CommandProfile( ) @tanjun.as_slash_command("reboot", "Restart the active N31L instance.") async def CommandReboot( - ctx: SlashContext, delay: Optional[int], state: State = tanjun.inject(type=State) + ctx: SlashContext, delay: int | None, state: State = tanjun.inject(type=State) ) -> None: """Handler for the /reboot slash command.""" - started: Dict[str, Any] = { + started: dict[str, Any] = { "name": "Instance Started", "value": Timestamps.Relative(state.botStart), } @@ -240,9 +238,9 @@ async def CommandServer(ctx: SlashContext) -> None: """Handler for the /server slash command.""" server: Guild = await ctx.fetch_guild() - creators: Dict[int, int] = {136986169563938816: 132693143173857281} + creators: dict[int, int] = {136986169563938816: 132693143173857281} - fields: List[Dict[str, Any]] = [] + fields: list[dict[str, Any]] = [] if hasattr(server, "created_at"): if (created := server.created_at) is not None: @@ -285,7 +283,7 @@ async def CommandStatus( ) -> None: """Handler for the /status slash command.""" - stats: List[Dict[str, Any]] = [] + stats: list[dict[str, Any]] = [] # Make a request to Discord to determine the REST latency latStart: float = datetime.now().timestamp() @@ -354,8 +352,8 @@ async def CommandStatus( async def CommandSendDirectMessage( ctx: SlashContext, user: User, - content: Optional[str], - attachment: Optional[Attachment], + content: str | None, + attachment: Attachment | None, ) -> None: """Handler for the /send direct_message slash command.""" @@ -418,8 +416,8 @@ async def CommandSendDirectMessage( async def CommandSendMessage( ctx: SlashContext, channel: InteractionChannel, - content: Optional[str], - attachment: Optional[Attachment], + content: str | None, + attachment: Attachment | None, ) -> None: """Handler for the /send message slash command.""" @@ -485,7 +483,7 @@ async def CommandSetActivity( ctx: SlashContext, type: int, name: str, - url: Optional[str] = None, + url: str | None = None, bot: GatewayBot = tanjun.inject(type=GatewayBot), ) -> None: """Handler for the /set activity slash command.""" @@ -516,10 +514,10 @@ async def CommandSetActivity( "image", "Upload an image file or leave empty to use default avatar.", default=None ) @tanjun.as_slash_command("avatar", "Set the avatar for N31L.") -async def CommandSetAvatar(ctx: SlashContext, image: Optional[Attachment]) -> None: +async def CommandSetAvatar(ctx: SlashContext, image: Attachment | None) -> None: """Handler for the /set avatar slash command.""" - url: Optional[str] = None if image is None else image.url + url: str | None = None if image is None else image.url try: if image is not None: @@ -571,7 +569,7 @@ async def CommandSetStatus( ) -> None: """Handler for the /set status slash command.""" - color: Optional[str] = None + color: str | None = None if type == Status.DO_NOT_DISTURB: color = "ED4245" diff --git a/components/animals.py b/components/animals.py index 01fe43f..9e6c54b 100644 --- a/components/animals.py +++ b/components/animals.py @@ -1,6 +1,5 @@ import asyncio import random -from typing import List, Optional import tanjun from hikari import Permissions @@ -28,7 +27,7 @@ ) component: Component = Component(name="Animals") -animalTypes: List[str] = [ +animalTypes: list[str] = [ "Axolotl", "Bingus", "Bird", @@ -59,13 +58,13 @@ default=None, ) @tanjun.as_slash_command("animal", "Fetch a random picture of an animal.") -async def CommandAnimal(ctx: SlashContext, type: Optional[str]) -> None: +async def CommandAnimal(ctx: SlashContext, type: str | None) -> None: """Handler for the /animal command.""" if type is None: type = random.choice(animalTypes) - result: Optional[Embed] = None + result: Embed | None = None source: int = 1 retries: int = 0 diff --git a/components/food.py b/components/food.py index ee167d8..b657234 100644 --- a/components/food.py +++ b/components/food.py @@ -1,6 +1,5 @@ import asyncio import random -from typing import List, Optional import tanjun from hikari import Permissions @@ -12,7 +11,7 @@ from services import Burger, Dessert, HotDog, Pasta, Pizza, Salad, Sandwich, Sushi, Taco component: Component = Component(name="Food") -foodTypes: List[str] = [ +foodTypes: list[str] = [ "Burger", "Dessert", "Hot Dog", @@ -34,13 +33,13 @@ default=None, ) @tanjun.as_slash_command("food", "Fetch a random picture of food.") -async def CommandFood(ctx: SlashContext, type: Optional[str]) -> None: +async def CommandFood(ctx: SlashContext, type: str | None) -> None: """Handler for the /food command.""" if type is None: type = random.choice(foodTypes) - result: Optional[Embed] = None + result: Embed | None = None source: int = 1 retries: int = 0 diff --git a/components/logs.py b/components/logs.py index 3686dce..ea53d9d 100644 --- a/components/logs.py +++ b/components/logs.py @@ -1,5 +1,5 @@ from os import environ -from typing import Any, Dict, List, Optional +from typing import Any import tanjun from hikari.events.message_events import ( @@ -19,7 +19,7 @@ @component.with_listener(DMMessageCreateEvent) async def EventDirectMessage( ctx: DMMessageCreateEvent, - config: Dict[str, Any] = tanjun.inject(type=Dict[str, Any]), + config: dict[str, Any] = tanjun.inject(type=dict[str, Any]), ) -> None: """Handler for notifying of direct messages.""" @@ -28,13 +28,13 @@ async def EventDirectMessage( elif int(ctx.author.id) == config["users"]["owner"]: return - content: Optional[str] = None + content: str | None = None if hasattr(ctx.message, "content"): if ctx.message.content is not None: content = f">>> {Utility.Trim(ctx.message.content, 4000)}" - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "username": "N31L", "avatar_url": "https://i.imgur.com/cGtkGuI.png", "embeds": [ @@ -76,7 +76,7 @@ async def EventDirectMessage( @component.with_listener(GuildMessageCreateEvent) async def EventKeyword( ctx: GuildMessageCreateEvent, - config: Dict[str, Any] = tanjun.inject(type=Dict[str, Any]), + config: dict[str, Any] = tanjun.inject(type=dict[str, Any]), ) -> None: """Handler for notifying of keyword mentions.""" @@ -91,8 +91,8 @@ async def EventKeyword( elif ctx.message.content is None: return - words: List[str] = [word.lower() for word in ctx.message.content.split()] - found: List[str] = [] + words: list[str] = [word.lower() for word in ctx.message.content.split()] + found: list[str] = [] for keyword in config["logging"]["keywords"]: if keyword not in words: @@ -103,7 +103,7 @@ async def EventKeyword( if len(found) == 0: return - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "username": "N31L", "avatar_url": "https://i.imgur.com/cGtkGuI.png", "embeds": [ @@ -160,7 +160,7 @@ async def EventKeyword( @component.with_listener(GuildMessageCreateEvent) async def EventMention( ctx: GuildMessageCreateEvent, - config: Dict[str, Any] = tanjun.inject(type=Dict[str, Any]), + config: dict[str, Any] = tanjun.inject(type=dict[str, Any]), ) -> None: """Handler for notifying of mentions.""" @@ -173,7 +173,7 @@ async def EventMention( elif ctx.message.content is None: return - found: List[str] = [] + found: list[str] = [] for id in config["logging"]["mentions"]: if id not in ctx.message.user_mentions_ids: @@ -184,7 +184,7 @@ async def EventMention( if len(found) == 0: return - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "username": "N31L", "avatar_url": "https://i.imgur.com/cGtkGuI.png", "embeds": [ @@ -242,7 +242,7 @@ async def EventMention( async def EventMirror( ctx: GuildMessageCreateEvent, client: Client = tanjun.inject(type=Client), - config: Dict[str, Any] = tanjun.inject(type=Dict[str, Any]), + config: dict[str, Any] = tanjun.inject(type=dict[str, Any]), ) -> None: """Handler for automatically mirroring Zeppelin log archives.""" @@ -258,7 +258,7 @@ async def EventMirror( return content: str = ctx.message.content.lower() - urls: List[str] = [] + urls: list[str] = [] extractor: URLExtract = URLExtract() urls = extractor.find_urls(content, True) @@ -270,7 +270,7 @@ async def EventMirror( if not url.startswith("https://api.zeppelin.gg/archives/"): continue - data: Optional[str] = await Utility.GET(url) + data: str | None = await Utility.GET(url) if data is None: return diff --git a/components/messages.py b/components/messages.py index 4803fa1..163b23c 100644 --- a/components/messages.py +++ b/components/messages.py @@ -1,6 +1,6 @@ from datetime import datetime from os import environ -from typing import Any, Dict, List, Optional +from typing import Any import tanjun from hikari import ( @@ -32,7 +32,7 @@ @component.with_schedule @tanjun.as_interval(300) async def TaskArchiveThreads( - config: Dict[str, Any] = tanjun.inject(type=Dict[str, Any]), + config: dict[str, Any] = tanjun.inject(type=dict[str, Any]), bot: GatewayBot = tanjun.inject(type=GatewayBot), ) -> None: """Automatically archive threads in the configured channels.""" @@ -43,7 +43,7 @@ async def TaskArchiveThreads( logger.info("Beginning recurring task to archive threads...") lifetime: int = config["archiveThreads"]["lifetime"] - threads: List[GuildThreadChannel] = await bot.rest.fetch_active_threads( + threads: list[GuildThreadChannel] = await bot.rest.fetch_active_threads( int(environ.get("DISCORD_SERVER_ID")) ) @@ -80,7 +80,7 @@ async def TaskArchiveThreads( @component.with_listener(GuildMessageCreateEvent) async def EventShadowban( ctx: GuildMessageCreateEvent, - config: Dict[str, Any] = tanjun.inject(type=Dict[str, Any]), + config: dict[str, Any] = tanjun.inject(type=dict[str, Any]), ) -> None: """Silently delete user messages in the configured channels.""" @@ -111,7 +111,7 @@ async def EventShadowban( async def CommandReport( ctx: MenuContext, message: Message, - config: Dict[str, Any] = tanjun.inject(type=Dict[str, Any]), + config: dict[str, Any] = tanjun.inject(type=dict[str, Any]), ) -> None: """Handler for the Report to Moderators message command.""" @@ -128,8 +128,8 @@ async def CommandReport( return - imageUrl: Optional[str] = None - fields: List[Dict[str, Any]] = [ + imageUrl: str | None = None + fields: list[dict[str, Any]] = [ {"name": "Channel", "value": f"<#{message.channel_id}>"}, {"name": "Sent", "value": Timestamps.Relative(message.created_at)}, {"name": "Reported", "value": Timestamps.Relative(ctx.created_at)}, @@ -214,12 +214,12 @@ async def CommandPurge( ctx: SlashContext, channel: InteractionChannel, amount: int, - member: Optional[Member], + member: Member | None, ) -> None: """Handler for the /purge command.""" - messages: List[int] = [] - users: List[int] = [] + messages: list[int] = [] + users: list[int] = [] last: datetime = datetime.now() try: @@ -305,7 +305,7 @@ async def CommandParseUsers( ) -> None: """Handler for the /parse users command.""" - results: List[int] = [] + results: list[int] = [] # Minimum and maximum length of Discord snowflakes # https://discord.com/developers/docs/reference#snowflakes diff --git a/components/raid.py b/components/raid.py index fa5672d..d6870ba 100644 --- a/components/raid.py +++ b/components/raid.py @@ -1,5 +1,4 @@ from datetime import datetime -from typing import List, Optional, Union import tanjun from hikari import InteractionMember, MessageType, Permissions @@ -53,15 +52,15 @@ ) async def CommandRaidCollect( ctx: SlashContext, - amount: Optional[int], - max_created: Optional[int], - max_joined: Optional[int], - newest_join: Optional[Union[InteractionMember, UserImpl]], - oldest_join: Optional[Union[InteractionMember, UserImpl]], + amount: int | None, + max_created: int | None, + max_joined: int | None, + newest_join: InteractionMember | UserImpl | None, + oldest_join: InteractionMember | UserImpl | None, ) -> None: """Handler for the /raid collect command.""" - welcomes: Optional[int] = None + welcomes: int | None = None try: welcomes = (await ctx.fetch_guild()).system_channel_id @@ -79,7 +78,7 @@ async def CommandRaidCollect( return - users: List[int] = [] + users: list[int] = [] start: datetime = datetime.now() last: datetime = start collect: bool = True diff --git a/components/reddit.py b/components/reddit.py index 7103d0b..e7da467 100644 --- a/components/reddit.py +++ b/components/reddit.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Optional +from typing import Any import tanjun from asyncpraw.models.reddit.subreddit import Subreddit @@ -15,7 +15,7 @@ reddit: SlashCommandGroup = component.with_slash_command( tanjun.slash_command_group("reddit", "Slash Commands to manage Reddit communities.") ) -communities: Dict[str, str] = { +communities: dict[str, str] = { "r/ModernWarfareIII": "ModernWarfareIII", "r/ModernWarfareII": "ModernWarfareII", "r/CODVanguard": "CODVanguard", @@ -41,10 +41,10 @@ "queue", "Fetch the moderation and unmoderated queue counts for the specified Reddit community.", ) -async def CommandRedditQueue(ctx: SlashContext, community: Optional[str]) -> None: +async def CommandRedditQueue(ctx: SlashContext, community: str | None) -> None: """Handler for the /reddit queue command.""" - client: Optional[Reddit] = await Reddit.CreateClient() + client: Reddit | None = await Reddit.CreateClient() if client is None: await ctx.respond( @@ -56,10 +56,10 @@ async def CommandRedditQueue(ctx: SlashContext, community: Optional[str]) -> Non return if community is None: - results: List[Dict[str, Any]] = [] + results: list[dict[str, Any]] = [] for entry in communities: - subreddit: Optional[Subreddit] = await Reddit.GetSubreddit( + subreddit: Subreddit | None = await Reddit.GetSubreddit( client, communities[entry] ) diff --git a/components/roles.py b/components/roles.py index 08d3460..4f1452e 100644 --- a/components/roles.py +++ b/components/roles.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Sequence +from typing import Any, Sequence import tanjun from hikari.events.message_events import GuildMessageCreateEvent @@ -15,7 +15,7 @@ async def EventValidateRoles( ctx: GuildMessageCreateEvent, client: Client = tanjun.inject(type=Client), - config: Dict[str, Any] = tanjun.inject(type=Dict[str, Any]), + config: dict[str, Any] = tanjun.inject(type=dict[str, Any]), ) -> None: """ Validate that the configured role requirements are met for the @@ -27,11 +27,11 @@ async def EventValidateRoles( elif ctx.message.member is None: return - invalidated: List[int] = [] + invalidated: list[int] = [] equipped: Sequence[Snowflake] = ctx.message.member.role_ids if config["roles"]["limit"]: - matches: List[int] = [] + matches: list[int] = [] for role in equipped: if role in config["roles"]["allow"]: diff --git a/helpers/hooks.py b/helpers/hooks.py index 8a4b2cf..b745e0f 100644 --- a/helpers/hooks.py +++ b/helpers/hooks.py @@ -18,7 +18,7 @@ async def PreExecution(ctx: MenuContext) -> None: ) async def PostExecution( - ctx: MenuContext, config: Dict[str, Any] = tanjun.inject(type=Dict[str, Any]) + ctx: MenuContext, config: dict[str, Any] = tanjun.inject(type=dict[str, Any]) ) -> None: """Menu command pre-execution hook.""" @@ -52,7 +52,7 @@ async def PreExecution(ctx: SlashContext) -> None: ) async def PostExecution( - ctx: SlashContext, config: Dict[str, Any] = tanjun.inject(type=Dict[str, Any]) + ctx: SlashContext, config: dict[str, Any] = tanjun.inject(type=dict[str, Any]) ) -> None: """Slash command post-execution hook.""" diff --git a/helpers/responses.py b/helpers/responses.py index bb2443f..0bc52c3 100644 --- a/helpers/responses.py +++ b/helpers/responses.py @@ -1,6 +1,5 @@ import hashlib from datetime import datetime -from typing import Dict, List, Optional, Union from hikari import Guild, GuildChannel, GuildThreadChannel, Role, Snowflake, User from hikari.embeds import Embed @@ -69,7 +68,7 @@ def ExpandThread(thread: GuildThreadChannel, format: bool = True) -> str: return f"{thread.name} ({thread.id})" - def Log(emoji: str, message: str, timestamp: Optional[datetime] = None) -> str: + def Log(emoji: str, message: str, timestamp: datetime | None = None) -> str: """Build a reusable log message.""" if timestamp is None: @@ -78,19 +77,19 @@ def Log(emoji: str, message: str, timestamp: Optional[datetime] = None) -> str: return f"[{Timestamps.LongTime(timestamp)}] :{emoji}: {message}" def Success( - title: Optional[str] = None, - url: Optional[str] = None, + title: str | None = None, + url: str | None = None, color: str = "3BA55D", - description: Optional[str] = None, - fields: List[Dict[str, Union[str, bool]]] = [], - author: Optional[str] = None, - authorUrl: Optional[str] = None, - authorIcon: Optional[str] = None, - thumbnail: Optional[str] = None, - image: Optional[str] = None, - footer: Optional[str] = None, - footerIcon: Optional[str] = None, - timestamp: Optional[datetime] = None, + description: str | None = None, + fields: list[dict[str, str | bool]] = [], + author: str | None = None, + authorUrl: str | None = None, + authorIcon: str | None = None, + thumbnail: str | None = None, + image: str | None = None, + footer: str | None = None, + footerIcon: str | None = None, + timestamp: datetime | None = None, ) -> Embed: """Build a generic successful response Embed object.""" @@ -122,19 +121,19 @@ def Success( return result def Warning( - title: Optional[str] = None, - url: Optional[str] = None, + title: str | None = None, + url: str | None = None, color: str = "FAA81A", - description: Optional[str] = None, - fields: List[Dict[str, Union[str, bool]]] = [], - author: Optional[str] = None, - authorUrl: Optional[str] = None, - authorIcon: Optional[str] = None, - thumbnail: Optional[str] = None, - image: Optional[str] = None, - footer: Optional[str] = None, - footerIcon: Optional[str] = None, - timestamp: Optional[datetime] = None, + description: str | None = None, + fields: list[dict[str, str | bool]] = [], + author: str | None = None, + authorUrl: str | None = None, + authorIcon: str | None = None, + thumbnail: str | None = None, + image: str | None = None, + footer: str | None = None, + footerIcon: str | None = None, + timestamp: datetime | None = None, ) -> Embed: """Build a generic warning response Embed object.""" @@ -166,19 +165,19 @@ def Warning( return result def Fail( - title: Optional[str] = None, - url: Optional[str] = None, + title: str | None = None, + url: str | None = None, color: str = "ED4245", - description: Optional[str] = None, - fields: List[Dict[str, Union[str, bool]]] = [], - author: Optional[str] = None, - authorUrl: Optional[str] = None, - authorIcon: Optional[str] = None, - thumbnail: Optional[str] = None, - image: Optional[str] = None, - footer: Optional[str] = None, + description: str | None = None, + fields: list[dict[str, str | bool]] = [], + author: str | None = None, + authorUrl: str | None = None, + authorIcon: str | None = None, + thumbnail: str | None = None, + image: str | None = None, + footer: str | None = None, footerIcon: str = "https://i.imgur.com/IwCRM6v.png", - timestamp: Optional[datetime] = None, + timestamp: datetime | None = None, ) -> Embed: """Build a generic failed response Embed object.""" @@ -221,7 +220,7 @@ def Fail( class Timestamps: """Class containing markdown, timestamp formatting templates.""" - def LongDate(timestamp: Union[int, float, datetime]) -> str: + def LongDate(timestamp: int | float | datetime) -> str: """ Create a long date timestamp using markdown formatting. @@ -235,7 +234,7 @@ def LongDate(timestamp: Union[int, float, datetime]) -> str: return f"" - def ExtraLongDateShortTime(timestamp: Union[int, float, datetime]) -> str: + def ExtraLongDateShortTime(timestamp: int | float | datetime) -> str: """ Create an extra long date and short time timestamp using markdown formatting. @@ -249,7 +248,7 @@ def ExtraLongDateShortTime(timestamp: Union[int, float, datetime]) -> str: return f"" - def LongDateShortTime(timestamp: Union[int, float, datetime]) -> str: + def LongDateShortTime(timestamp: int | float | datetime) -> str: """ Create a long date and short time timestamp using markdown formatting. @@ -263,7 +262,7 @@ def LongDateShortTime(timestamp: Union[int, float, datetime]) -> str: return f"" - def LongTime(timestamp: Union[int, float, datetime]) -> str: + def LongTime(timestamp: int | float | datetime) -> str: """ Create a long time timestamp using markdown formatting. @@ -277,7 +276,7 @@ def LongTime(timestamp: Union[int, float, datetime]) -> str: return f"" - def Relative(timestamp: Union[int, float, datetime]) -> str: + def Relative(timestamp: int | float | datetime) -> str: """ Create a relative timestamp using markdown formatting. @@ -291,7 +290,7 @@ def Relative(timestamp: Union[int, float, datetime]) -> str: return f"" - def ShortDate(timestamp: Union[int, float, datetime]) -> str: + def ShortDate(timestamp: int | float | datetime) -> str: """ Create a short date timestamp using markdown formatting. @@ -305,7 +304,7 @@ def ShortDate(timestamp: Union[int, float, datetime]) -> str: return f"" - def ShortTime(timestamp: Union[int, float, datetime]) -> str: + def ShortTime(timestamp: int | float | datetime) -> str: """ Create a short time timestamp using markdown formatting. diff --git a/helpers/utils.py b/helpers/utils.py index fdb7eab..6111792 100644 --- a/helpers/utils.py +++ b/helpers/utils.py @@ -1,6 +1,6 @@ import re from datetime import datetime -from typing import Any, Dict, List, Optional, Union +from typing import Any import httpx from hikari import GatewayBot, Member, NotFoundError @@ -14,9 +14,7 @@ class Utility: """Utilitarian functions designed for N31L.""" - async def GET( - url: str, headers: Optional[Dict[str, str]] = None - ) -> Optional[Union[str, Dict[str, Any]]]: + async def GET(url: str, headers: dict[str, str] | None = None) -> str | dict[str, Any] | None: """Perform an HTTP GET request and return its response.""" logger.debug(f"GET {url}") @@ -42,7 +40,7 @@ async def GET( return res.text - async def POST(url: str, payload: Dict[str, Any]) -> bool: + async def POST(url: str, payload: dict[str, Any]) -> bool: """Perform an HTTP POST request and return its status.""" logger.debug(f"POST {url}") @@ -63,7 +61,7 @@ async def POST(url: str, payload: Dict[str, Any]) -> bool: return True - def Elapsed(a: Union[datetime, int, float], b: Union[datetime, int, float]) -> int: + def Elapsed(a: datetime | int | float, b: datetime | int | float) -> int: """Determine the elapsed seconds between the provided datetime objects.""" if type(a) is datetime: @@ -74,7 +72,7 @@ def Elapsed(a: Union[datetime, int, float], b: Union[datetime, int, float]) -> i return int(a - b) - def Trim(input: str, length: int, end: Optional[str] = "...") -> str: + def Trim(input: str, length: int, end: str | None = "...") -> str: """Trim a string using the provided parameters.""" if len(input) <= length: @@ -94,11 +92,11 @@ def Trim(input: str, length: int, end: Optional[str] = "...") -> str: return result def FindNumbers( - input: str, minLen: Optional[int] = None, maxLen: Optional[int] = None - ) -> List[int]: + input: str, minLen: int | None = None, maxLen: int | None = None + ) -> list[int]: """Return all number sequences found in the given string.""" - results: List[int] = [] + results: list[int] = [] try: for entry in re.findall("\\d+", input): @@ -119,9 +117,7 @@ def FindNumbers( return results - async def UserHasRole( - userId: int, roleIds: Union[int, List[int]], serverId: int, bot: GatewayBot - ) -> bool: + async def UserHasRole(userId: int, roleIds: int | list[int], serverId: int, bot: GatewayBot) -> bool: """ Return a boolean value indicating whether or not a server member has a specified role. @@ -130,7 +126,7 @@ async def UserHasRole( successful match. """ - user: Optional[Member] = None + user: Member | None = None # Accept both a singular int or array of integers. if isinstance(roleIds, int): diff --git a/n31l.py b/n31l.py index 7178d6d..e9bcbd8 100644 --- a/n31l.py +++ b/n31l.py @@ -4,7 +4,7 @@ from datetime import datetime from os import environ from sys import exit, stdout -from typing import Any, Dict +from typing import Any import dotenv import tanjun @@ -30,7 +30,7 @@ def Initialize() -> None: logger.success("Loaded environment variables") logger.trace(environ) - config: Dict[str, Any] = LoadConfig() + config: dict[str, Any] = LoadConfig() state: State = State(botStart=datetime.now()) # Reroute standard logging to Loguru @@ -79,7 +79,7 @@ def Initialize() -> None: bot, declare_global_commands=int(environ.get("DISCORD_SERVER_ID")) ) - client.set_type_dependency(Dict[str, Any], config) + client.set_type_dependency(dict[str, Any], config) client.set_type_dependency(State, state) client.set_type_dependency(GatewayBot, bot) client.set_type_dependency(Client, client) @@ -113,12 +113,12 @@ def Initialize() -> None: ) -def LoadConfig() -> Dict[str, Any]: +def LoadConfig() -> dict[str, Any]: """Load the configuration values specified in config.json""" try: with open("config.json", "r") as file: - config: Dict[str, Any] = json.loads(file.read()) + config: dict[str, Any] = json.loads(file.read()) except Exception as e: logger.opt(exception=e).critical("Failed to load configuration") diff --git a/services/animals.py b/services/animals.py index a496a42..b2a8459 100644 --- a/services/animals.py +++ b/services/animals.py @@ -1,5 +1,5 @@ from os import environ -from typing import Any, Dict, List, Optional, Union +from typing import Any from hikari.embeds import Embed from loguru import logger @@ -12,7 +12,7 @@ class Axolotl: """Class containing axolotl image sources.""" - async def RedditAxolotls() -> Optional[Embed]: + async def RedditAxolotls() -> Embed | None: """Fetch a random axolotl image from r/axolotls.""" return await Reddit.GetRandomImage("axolotls") @@ -21,10 +21,10 @@ async def RedditAxolotls() -> Optional[Embed]: class Bird: """Class containing bird image sources.""" - async def RandomDuk() -> Optional[Embed]: + async def RandomDuk() -> Embed | None: """Fetch a random bird image from RandomDuk.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://random-d.uk/api/v2/random" ) @@ -36,10 +36,10 @@ async def RandomDuk() -> Optional[Embed]: except Exception as e: logger.opt(exception=e).error("Failed to fetch from RandomDuk") - async def SomeRandomAPI() -> Optional[Embed]: + async def SomeRandomAPI() -> Embed | None: """Fetch a random bird image from SomeRandomAPI.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://some-random-api.com/animal/bird" ) @@ -51,12 +51,12 @@ async def SomeRandomAPI() -> Optional[Embed]: except Exception as e: logger.opt(exception=e).error("Failed to fetch from SomeRandomAPI") - async def RedditBirbs() -> Optional[Embed]: + async def RedditBirbs() -> Embed | None: """Fetch a random bird image from r/Birbs.""" return await Reddit.GetRandomImage("Birbs") - async def RedditBirdPics() -> Optional[Embed]: + async def RedditBirdPics() -> Embed | None: """Fetch a random bird image from r/birdpics.""" return await Reddit.GetRandomImage("birdpics") @@ -65,10 +65,10 @@ async def RedditBirdPics() -> Optional[Embed]: class Bunny: """Class containing bunny image sources.""" - async def BunniesIO() -> Optional[Embed]: + async def BunniesIO() -> Embed | None: """Fetch a random bunny image from BunniesIO.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://api.bunnies.io/v2/loop/random/?media=gif" ) @@ -80,12 +80,12 @@ async def BunniesIO() -> Optional[Embed]: except Exception as e: logger.opt(exception=e).error("Failed to fetch from BunniesIO") - async def RedditBunnies() -> Optional[Embed]: + async def RedditBunnies() -> Embed | None: """Fetch a random bird image from r/Bunnies.""" return await Reddit.GetRandomImage("Bunnies") - async def RedditRabbits() -> Optional[Embed]: + async def RedditRabbits() -> Embed | None: """Fetch a random bird image from r/Rabbits.""" return await Reddit.GetRandomImage("Rabbits") @@ -94,10 +94,10 @@ async def RedditRabbits() -> Optional[Embed]: class Cat: """Class containing cat image sources.""" - async def TheCatAPI() -> Optional[Embed]: + async def TheCatAPI() -> Embed | None: """Fetch a random cat image from TheCatAPI.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://api.thecatapi.com/v1/images/search", headers={"x-api-key": environ.get("CAT_API_KEY")}, ) @@ -106,16 +106,16 @@ async def TheCatAPI() -> Optional[Embed]: return try: - cat: Dict[str, Any] = data[0] + cat: dict[str, Any] = data[0] - name: Optional[str] = None - wiki: Optional[str] = None - info: Optional[str] = None - facts: List[Dict[str, Union[str, bool]]] = [] - tags: Optional[List[str]] = None + name: str | None = None + wiki: str | None = None + info: str | None = None + facts: list[dict[str, str | bool]] = [] + tags: list[str] | None = None if len((breeds := cat["breeds"])) > 0: - breed: Dict[str, Any] = breeds[0] + breed: dict[str, Any] = breeds[0] name = breed["name"] wiki = breed["wikipedia_url"] @@ -159,10 +159,10 @@ async def TheCatAPI() -> Optional[Embed]: except Exception as e: logger.opt(exception=e).error("Failed to fetch from TheCatAPI") - async def CATAAS() -> Optional[Embed]: + async def CATAAS() -> Embed | None: """Fetch a random cat image from CATAAS.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://cataas.com/cat?json=true" ) @@ -178,10 +178,10 @@ async def CATAAS() -> Optional[Embed]: except Exception as e: logger.opt(exception=e).error("Failed to fetch from CATAAS") - async def SomeRandomAPI() -> Optional[Embed]: + async def SomeRandomAPI() -> Embed | None: """Fetch a random cat image from SomeRandomAPI.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://some-random-api.com/animal/cat" ) @@ -193,37 +193,37 @@ async def SomeRandomAPI() -> Optional[Embed]: except Exception as e: logger.opt(exception=e).error("Failed to fetch from SomeRandomAPI") - async def RedditBlurryPicturesCats() -> Optional[Embed]: + async def RedditBlurryPicturesCats() -> Embed | None: """Fetch a random cat image from r/blurrypicturesofcats.""" return await Reddit.GetRandomImage("blurrypicturesofcats") - async def RedditCatPics() -> Optional[Embed]: + async def RedditCatPics() -> Embed | None: """Fetch a random cat image from r/catpics.""" return await Reddit.GetRandomImage("catpics") - async def RedditCatPictures() -> Optional[Embed]: + async def RedditCatPictures() -> Embed | None: """Fetch a random cat image from r/catpictures.""" return await Reddit.GetRandomImage("catpictures") - async def RedditCats() -> Optional[Embed]: + async def RedditCats() -> Embed | None: """Fetch a random cat image from r/cats.""" return await Reddit.GetRandomImage("cats") - async def RedditCatsStandingUp() -> Optional[Embed]: + async def RedditCatsStandingUp() -> Embed | None: """Fetch a random cat image from r/CatsStandingUp.""" return await Reddit.GetRandomImage("CatsStandingUp") - async def RedditCursedCats() -> Optional[Embed]: + async def RedditCursedCats() -> Embed | None: """Fetch a random cat image from r/cursedcats.""" return await Reddit.GetRandomImage("cursedcats") - async def RedditSphynx() -> Optional[Embed]: + async def RedditSphynx() -> Embed | None: """Fetch a random cat image from r/sphynx.""" return await Reddit.GetRandomImage("sphynx") @@ -232,12 +232,12 @@ async def RedditSphynx() -> Optional[Embed]: class Capybara: """Class containing capybara image sources.""" - async def RedditCapybara() -> Optional[Embed]: + async def RedditCapybara() -> Embed | None: """Fetch a random capybara image from r/capybara.""" return await Reddit.GetRandomImage("capybara") - async def RedditCrittersoncapybaras() -> Optional[Embed]: + async def RedditCrittersoncapybaras() -> Embed | None: """Fetch a random capybara image from r/Crittersoncapybaras.""" return await Reddit.GetRandomImage("Crittersoncapybaras") @@ -246,10 +246,10 @@ async def RedditCrittersoncapybaras() -> Optional[Embed]: class Dog: """Class containing dog image sources.""" - async def TheDogAPI() -> Optional[Embed]: + async def TheDogAPI() -> Embed | None: """Fetch a random dog image from TheDogAPI.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://api.thedogapi.com/v1/images/search", headers={"x-api-key": environ.get("DOG_API_KEY")}, ) @@ -258,13 +258,13 @@ async def TheDogAPI() -> Optional[Embed]: return try: - dog: Dict[str, Any] = data[0] + dog: dict[str, Any] = data[0] - name: Optional[str] = None - facts: List[Dict[str, Union[str, bool]]] = [] + name: str | None = None + facts: list[dict[str, str | bool]] = [] if len((breeds := dog["breeds"])) > 0: - breed: Dict[str, Any] = breeds[0] + breed: dict[str, Any] = breeds[0] name = breed["name"] @@ -277,10 +277,10 @@ async def TheDogAPI() -> Optional[Embed]: except Exception as e: logger.opt(exception=e).error("Failed to fetch from TheDogAPI") - async def DogCEO() -> Optional[Embed]: + async def DogCEO() -> Embed | None: """Fetch a random dog image from DogCEO.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://dog.ceo/api/breeds/image/random" ) @@ -300,10 +300,10 @@ async def DogCEO() -> Optional[Embed]: except Exception as e: logger.opt(exception=e).error("Failed to fetch from DogCEO") - async def RandomDog() -> Optional[Embed]: + async def RandomDog() -> Embed | None: """Fetch a random dog image from RandomDog.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://random.dog/woof.json" ) @@ -315,10 +315,10 @@ async def RandomDog() -> Optional[Embed]: except Exception as e: logger.opt(exception=e).error("Failed to fetch from RandomDog") - async def ShibeOnline() -> Optional[Embed]: + async def ShibeOnline() -> Embed | None: """Fetch a random dog image from ShibeOnline.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://shibe.online/api/shibes" ) @@ -330,10 +330,10 @@ async def ShibeOnline() -> Optional[Embed]: except Exception as e: logger.opt(exception=e).error("Failed to fetch from ShibeOnline") - async def SomeRandomAPI() -> Optional[Embed]: + async def SomeRandomAPI() -> Embed | None: """Fetch a random dog image from SomeRandomAPI.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://some-random-api.com/animal/dog" ) @@ -345,27 +345,27 @@ async def SomeRandomAPI() -> Optional[Embed]: except Exception as e: logger.opt(exception=e).error("Failed to fetch from SomeRandomAPI") - async def RedditBlurryPicturesDogs() -> Optional[Embed]: + async def RedditBlurryPicturesDogs() -> Embed | None: """Fetch a random dog image from r/blurrypicturesofdogs.""" return await Reddit.GetRandomImage("blurrypicturesofdogs") - async def RedditDogPictures() -> Optional[Embed]: + async def RedditDogPictures() -> Embed | None: """Fetch a random dog image from r/dogpictures.""" return await Reddit.GetRandomImage("dogpictures") - async def RedditLookMyDog() -> Optional[Embed]: + async def RedditLookMyDog() -> Embed | None: """Fetch a random dog image from r/lookatmydog.""" return await Reddit.GetRandomImage("lookatmydog") - async def RedditPuppies() -> Optional[Embed]: + async def RedditPuppies() -> Embed | None: """Fetch a random dog image from r/puppies.""" return await Reddit.GetRandomImage("puppies") - async def RedditShiba() -> Optional[Embed]: + async def RedditShiba() -> Embed | None: """Fetch a random dog image from r/shiba.""" return await Reddit.GetRandomImage("shiba") @@ -374,10 +374,10 @@ async def RedditShiba() -> Optional[Embed]: class Fox: """Class containing fox image sources.""" - async def RandomFox() -> Optional[Embed]: + async def RandomFox() -> Embed | None: """Fetch a random fox image from RandomFox.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://randomfox.ca/floof/" ) @@ -389,10 +389,10 @@ async def RandomFox() -> Optional[Embed]: except Exception as e: logger.opt(exception=e).error("Failed to fetch from RandomFox") - async def SomeRandomAPI() -> Optional[Embed]: + async def SomeRandomAPI() -> Embed | None: """Fetch a random fox image from SomeRandomAPI.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://some-random-api.com/animal/fox" ) @@ -404,7 +404,7 @@ async def SomeRandomAPI() -> Optional[Embed]: except Exception as e: logger.opt(exception=e).error("Failed to fetch from SomeRandomAPI") - async def RedditFoxes() -> Optional[Embed]: + async def RedditFoxes() -> Embed | None: """Fetch a random fox image from r/foxes.""" return await Reddit.GetRandomImage("foxes") @@ -413,10 +413,10 @@ async def RedditFoxes() -> Optional[Embed]: class Kangaroo: """Class containing kangaroo image sources.""" - async def SomeRandomAPI() -> Optional[Embed]: + async def SomeRandomAPI() -> Embed | None: """Fetch a random kangaroo image from SomeRandomAPI.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://some-random-api.com/animal/kangaroo" ) @@ -432,10 +432,10 @@ async def SomeRandomAPI() -> Optional[Embed]: class Koala: """Class containing koala image sources.""" - async def SomeRandomAPI() -> Optional[Embed]: + async def SomeRandomAPI() -> Embed | None: """Fetch a random koala image from SomeRandomAPI.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://some-random-api.com/animal/koala" ) @@ -447,7 +447,7 @@ async def SomeRandomAPI() -> Optional[Embed]: except Exception as e: logger.opt(exception=e).error("Failed to fetch from SomeRandomAPI") - async def RedditKoalas() -> Optional[Embed]: + async def RedditKoalas() -> Embed | None: """Fetch a random koala image from r/koalas.""" return await Reddit.GetRandomImage("koalas") @@ -456,10 +456,10 @@ async def RedditKoalas() -> Optional[Embed]: class Lizard: """Class containing lizard image sources.""" - async def NekosLife() -> Optional[Embed]: + async def NekosLife() -> Embed | None: """Fetch a random lizard image from NekosLife.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://nekos.life/api/v2/img/lizard" ) @@ -471,7 +471,7 @@ async def NekosLife() -> Optional[Embed]: except Exception as e: logger.opt(exception=e).error("Failed to fetch from NekosLife") - async def RedditLizards() -> Optional[Embed]: + async def RedditLizards() -> Embed | None: """Fetch a random lizard image from r/Lizards.""" return await Reddit.GetRandomImage("Lizards") @@ -480,7 +480,7 @@ async def RedditLizards() -> Optional[Embed]: class Otter: """Class containing otter image sources.""" - async def RedditOtterable() -> Optional[Embed]: + async def RedditOtterable() -> Embed | None: """Fetch a random otter image from r/Otterable.""" return await Reddit.GetRandomImage("Otterable") @@ -489,10 +489,10 @@ async def RedditOtterable() -> Optional[Embed]: class Panda: """Class containing panda image sources.""" - async def SomeRandomAPI() -> Optional[Embed]: + async def SomeRandomAPI() -> Embed | None: """Fetch a random panda image from SomeRandomAPI.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://some-random-api.com/animal/panda" ) @@ -508,10 +508,10 @@ async def SomeRandomAPI() -> Optional[Embed]: class Raccoon: """Class containing raccoon image sources.""" - async def SomeRandomAPI() -> Optional[Embed]: + async def SomeRandomAPI() -> Embed | None: """Fetch a random panda image from SomeRandomAPI.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://some-random-api.com/animal/raccoon" ) @@ -523,12 +523,12 @@ async def SomeRandomAPI() -> Optional[Embed]: except Exception as e: logger.opt(exception=e).error("Failed to fetch from SomeRandomAPI") - async def RedditRaccoons() -> Optional[Embed]: + async def RedditRaccoons() -> Embed | None: """Fetch a random raccoon image from r/Raccoons.""" return await Reddit.GetRandomImage("Raccoons") - async def RedditTrashPandas() -> Optional[Embed]: + async def RedditTrashPandas() -> Embed | None: """Fetch a random raccoon image from r/trashpandas.""" return await Reddit.GetRandomImage("trashpandas") @@ -537,7 +537,7 @@ async def RedditTrashPandas() -> Optional[Embed]: class Rat: """Class containing rat image sources.""" - async def RedditRats() -> Optional[Embed]: + async def RedditRats() -> Embed | None: """Fetch a random rat image from r/RATS.""" return await Reddit.GetRandomImage("RATS") @@ -546,10 +546,10 @@ async def RedditRats() -> Optional[Embed]: class RedPanda: """Class containing red panda image sources.""" - async def SomeRandomAPI() -> Optional[Embed]: + async def SomeRandomAPI() -> Embed | None: """Fetch a random panda image from SomeRandomAPI.""" - data: Optional[Dict[str, Any]] = await Utility.GET( + data: dict[str, Any] | None = await Utility.GET( "https://some-random-api.com/animal/red_panda" ) @@ -561,7 +561,7 @@ async def SomeRandomAPI() -> Optional[Embed]: except Exception as e: logger.opt(exception=e).error("Failed to fetch from SomeRandomAPI") - async def RedditRedPandas() -> Optional[Embed]: + async def RedditRedPandas() -> Embed | None: """Fetch a random red panda image from r/redpandas.""" return await Reddit.GetRandomImage("redpandas") diff --git a/services/food.py b/services/food.py index bee03d8..020880c 100644 --- a/services/food.py +++ b/services/food.py @@ -1,5 +1,3 @@ -from typing import Optional - from hikari.embeds import Embed from .reddit import Reddit @@ -8,7 +6,7 @@ class Burger: """Class containing burger image sources.""" - async def RedditBurgers() -> Optional[Embed]: + async def RedditBurgers() -> Embed | None: """Fetch a random burger image from r/burgers.""" return await Reddit.GetRandomImage("burgers") @@ -17,37 +15,37 @@ async def RedditBurgers() -> Optional[Embed]: class Dessert: """Class containing dessert image sources.""" - async def RedditCake() -> Optional[Embed]: + async def RedditCake() -> Embed | None: """Fetch a random dessert image from r/cake.""" return await Reddit.GetRandomImage("cake") - async def RedditCookies() -> Optional[Embed]: + async def RedditCookies() -> Embed | None: """Fetch a random dessert image from r/Cookies.""" return await Reddit.GetRandomImage("Cookies") - async def RedditCupcakes() -> Optional[Embed]: + async def RedditCupcakes() -> Embed | None: """Fetch a random dessert image from r/cupcakes.""" return await Reddit.GetRandomImage("cupcakes") - async def RedditDessert() -> Optional[Embed]: + async def RedditDessert() -> Embed | None: """Fetch a random dessert image from r/dessert.""" return await Reddit.GetRandomImage("dessert") - async def RedditDessertPorn() -> Optional[Embed]: + async def RedditDessertPorn() -> Embed | None: """Fetch a random dessert image from r/DessertPorn.""" return await Reddit.GetRandomImage("DessertPorn") - async def RedditIcecreamery() -> Optional[Embed]: + async def RedditIcecreamery() -> Embed | None: """Fetch a random dessert image from r/icecreamery.""" return await Reddit.GetRandomImage("icecreamery") - async def RedditPie() -> Optional[Embed]: + async def RedditPie() -> Embed | None: """Fetch a random dessert image from r/pie.""" return await Reddit.GetRandomImage("pie") @@ -56,7 +54,7 @@ async def RedditPie() -> Optional[Embed]: class HotDog: """Class containing hot dog image sources.""" - async def RedditHotDogs() -> Optional[Embed]: + async def RedditHotDogs() -> Embed | None: """Fetch a random hot dog image from r/hotdogs.""" return await Reddit.GetRandomImage("hotdogs") @@ -65,7 +63,7 @@ async def RedditHotDogs() -> Optional[Embed]: class Pasta: """Class containing pasta image sources.""" - async def RedditPasta() -> Optional[Embed]: + async def RedditPasta() -> Embed | None: """Fetch a random pasta image from r/pasta.""" return await Reddit.GetRandomImage("pasta") @@ -74,7 +72,7 @@ async def RedditPasta() -> Optional[Embed]: class Pizza: """Class containing pizza image sources.""" - async def RedditPizza() -> Optional[Embed]: + async def RedditPizza() -> Embed | None: """Fetch a random pizza image from r/Pizza.""" return await Reddit.GetRandomImage("Pizza") @@ -83,7 +81,7 @@ async def RedditPizza() -> Optional[Embed]: class Salad: """Class containing salad image sources.""" - async def RedditSalads() -> Optional[Embed]: + async def RedditSalads() -> Embed | None: """Fetch a random salad image from r/salads.""" return await Reddit.GetRandomImage("salads") @@ -92,17 +90,17 @@ async def RedditSalads() -> Optional[Embed]: class Sandwich: """Class containing sandwich image sources.""" - async def RedditEatSandwiches() -> Optional[Embed]: + async def RedditEatSandwiches() -> Embed | None: """Fetch a random sandwich image from r/eatsandwiches.""" return await Reddit.GetRandomImage("eatsandwiches") - async def RedditGrilledCheese() -> Optional[Embed]: + async def RedditGrilledCheese() -> Embed | None: """Fetch a random sandwich image from r/grilledcheese.""" return await Reddit.GetRandomImage("grilledcheese") - async def RedditSandwiches() -> Optional[Embed]: + async def RedditSandwiches() -> Embed | None: """Fetch a random sandwich image from r/sandwiches.""" return await Reddit.GetRandomImage("sandwiches") @@ -111,7 +109,7 @@ async def RedditSandwiches() -> Optional[Embed]: class Sushi: """Class containing sushi image sources.""" - async def RedditSushi() -> Optional[Embed]: + async def RedditSushi() -> Embed | None: """Fetch a random sushi image from r/sushi.""" return await Reddit.GetRandomImage("sushi") @@ -120,7 +118,7 @@ async def RedditSushi() -> Optional[Embed]: class Taco: """Class containing taco image sources.""" - async def RedditTacos() -> Optional[Embed]: + async def RedditTacos() -> Embed | None: """Fetch a random taco image from r/tacos.""" return await Reddit.GetRandomImage("tacos") diff --git a/services/reddit.py b/services/reddit.py index cca9007..c934755 100644 --- a/services/reddit.py +++ b/services/reddit.py @@ -1,6 +1,5 @@ import asyncio from os import environ -from typing import Optional import asyncpraw from asyncpraw.models.reddit.submission import Submission @@ -15,7 +14,7 @@ class Reddit: """Class containing generic Reddit functions.""" - async def CreateClient() -> Optional[Reddit]: + async def CreateClient() -> Reddit | None: """Create an authenticated Reddit client using the configured credentials.""" client: Reddit = asyncpraw.Reddit( @@ -41,7 +40,7 @@ async def DestroyClient(client: Reddit) -> None: except Exception as e: logger.opt(exception=e).warning("Failed to close Reddit session") - async def GetSubreddit(client: Reddit, community: str) -> Optional[Subreddit]: + async def GetSubreddit(client: Reddit, community: str) -> Subreddit | None: """Fetch the subreddit object for the specified Reddit community.""" try: @@ -99,16 +98,16 @@ async def CountUnmoderated(client: Reddit, community: Subreddit) -> int: return total - async def GetRandomImage(community: str) -> Optional[Embed]: + async def GetRandomImage(community: str) -> Embed | None: """Fetch a random image from the specified Reddit community.""" - client: Optional[Reddit] = await Reddit.CreateClient() + client: Reddit | None = await Reddit.CreateClient() if client is None: return - subreddit: Optional[Subreddit] = None - post: Optional[Submission] = None + subreddit: Subreddit | None = None + post: Submission | None = None valid: bool = False attempts: int = 0