11from __future__ import annotations
22
3- import logging
43import re
54import typing as t
65from datetime import datetime
1918from bot .constants import URLs
2019from bot .errors import InvalidInfraction
2120from bot .exts .info .doc import _inventory_parser
21+ from bot .log import get_logger
2222from bot .utils .extensions import EXTENSIONS , unqualify
2323from bot .utils .regex import INVITE_RE
2424from bot .utils .time import parse_duration_string
25+
2526if t .TYPE_CHECKING :
2627 from bot .exts .info .source import SourceType
2728
28- log = logging . getLogger (__name__ )
29+ log = get_logger (__name__ )
2930
3031DISCORD_EPOCH_DT = datetime .utcfromtimestamp (DISCORD_EPOCH / 1000 )
3132RE_USER_MENTION = re .compile (r"<@!?([0-9]+)>$" )
@@ -70,10 +71,10 @@ class ValidDiscordServerInvite(Converter):
7071
7172 async def convert (self , ctx : Context , server_invite : str ) -> dict :
7273 """Check whether the string is a valid Discord server invite."""
73- invite_code = INVITE_RE .search (server_invite )
74+ invite_code = INVITE_RE .match (server_invite )
7475 if invite_code :
7576 response = await ctx .bot .http_session .get (
76- f"{ URLs .discord_invite_api } /{ invite_code [ 1 ] } "
77+ f"{ URLs .discord_invite_api } /{ invite_code . group ( 'invite' ) } "
7778 )
7879 if response .status != 404 :
7980 invite_data = await response .json ()
@@ -235,11 +236,16 @@ class Inventory(Converter):
235236 async def convert (ctx : Context , url : str ) -> t .Tuple [str , _inventory_parser .InventoryDict ]:
236237 """Convert url to Intersphinx inventory URL."""
237238 await ctx .trigger_typing ()
238- if (inventory := await _inventory_parser .fetch_inventory (url )) is None :
239- raise BadArgument (
240- f"Failed to fetch inventory file after { _inventory_parser .FAILED_REQUEST_ATTEMPTS } attempts."
241- )
242- return url , inventory
239+ try :
240+ inventory = await _inventory_parser .fetch_inventory (url )
241+ except _inventory_parser .InvalidHeaderError :
242+ raise BadArgument ("Unable to parse inventory because of invalid header, check if URL is correct." )
243+ else :
244+ if inventory is None :
245+ raise BadArgument (
246+ f"Failed to fetch inventory file after { _inventory_parser .FAILED_REQUEST_ATTEMPTS } attempts."
247+ )
248+ return url , inventory
243249
244250
245251class Snowflake (IDConverter ):
@@ -267,7 +273,7 @@ async def convert(self, ctx: Context, arg: str) -> int:
267273 snowflake = int (arg )
268274
269275 try :
270- time = snowflake_time (snowflake )
276+ time = snowflake_time (snowflake ). replace ( tzinfo = None )
271277 except (OverflowError , OSError ) as e :
272278 # Not sure if this can ever even happen, but let's be safe.
273279 raise BadArgument (f"{ error } : { e } " )
@@ -392,7 +398,8 @@ async def convert(self, ctx: Context, duration: str) -> datetime:
392398class OffTopicName (Converter ):
393399 """A converter that ensures an added off-topic name is valid."""
394400
395- ALLOWED_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ!?'`-"
401+ ALLOWED_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ!?'`-<>"
402+ TRANSLATED_CHARACTERS = "𝖠𝖡𝖢𝖣𝖤𝖥𝖦𝖧𝖨𝖩𝖪𝖫𝖬𝖭𝖮𝖯𝖰𝖱𝖲𝖳𝖴𝖵𝖶𝖷𝖸𝖹ǃ?’’-<>"
396403
397404 @classmethod
398405 def translate_name (cls , name : str , * , from_unicode : bool = True ) -> str :
@@ -402,9 +409,9 @@ def translate_name(cls, name: str, *, from_unicode: bool = True) -> str:
402409 If `from_unicode` is True, the name is translated from a discord-safe format, back to normalized text.
403410 """
404411 if from_unicode :
405- table = str .maketrans (cls .ALLOWED_CHARACTERS , '𝖠𝖡𝖢𝖣𝖤𝖥𝖦𝖧𝖨𝖩𝖪𝖫𝖬𝖭𝖮𝖯𝖰𝖱𝖲𝖳𝖴𝖵𝖶𝖷𝖸𝖹ǃ?’’-' )
412+ table = str .maketrans (cls .ALLOWED_CHARACTERS , cls . TRANSLATED_CHARACTERS )
406413 else :
407- table = str .maketrans ('𝖠𝖡𝖢𝖣𝖤𝖥𝖦𝖧𝖨𝖩𝖪𝖫𝖬𝖭𝖮𝖯𝖰𝖱𝖲𝖳𝖴𝖵𝖶𝖷𝖸𝖹ǃ?’’-' , cls .ALLOWED_CHARACTERS )
414+ table = str .maketrans (cls . TRANSLATED_CHARACTERS , cls .ALLOWED_CHARACTERS )
408415
409416 return name .translate (table )
410417
0 commit comments