diff --git a/common.py b/common.py index a741063..c45e6c2 100644 --- a/common.py +++ b/common.py @@ -34,24 +34,24 @@ colours = SimpleNamespace(good=0x43B581, neutral=0x7289DA, bad=0xF04747) # meow -cat = SimpleNamespace(lookup='Information Lookup', - fun='Fun', - maps='Mapping', - ref='Reference', - study='Exam Study', - weather='Land and Space Weather', - admin='Bot Control') +cat = SimpleNamespace(lookup="Information Lookup", + fun="Fun", + maps="Mapping", + ref="Reference", + study="Exam Study", + weather="Land and Space Weather", + admin="Bot Control") -emojis = SimpleNamespace(check_mark='✅', - x='❌', - warning='⚠️', - question='❓', - no_entry='⛔', - bangbang='‼️', - a='🇦', - b='🇧', - c='🇨', - d='🇩') +emojis = SimpleNamespace(check_mark="✅", + x="❌", + warning="⚠️", + question="❓", + no_entry="⛔", + bangbang="‼️", + a="🇦", + b="🇧", + c="🇨", + d="🇩") paths = SimpleNamespace(data=Path("./data/"), resources=Path("./resources/"), @@ -117,7 +117,7 @@ class GlobalChannelConverter(commands.IDConverter): async def convert(self, ctx: commands.Context, argument: str): bot = ctx.bot guild = ctx.guild - match = self._get_id_match(argument) or re.match(r'<#([0-9]+)>$', argument) + match = self._get_id_match(argument) or re.match(r"<#([0-9]+)>$", argument) result = None if match is None: # not a mention/ID @@ -150,7 +150,7 @@ def error_embed_factory(ctx: commands.Context, exception: Exception, debug_mode: fmtd_ex = traceback.format_exception_only(exception.__class__, exception) embed = embed_factory(ctx) embed.title = "⚠️ Error" - embed.description = "```\n" + '\n'.join(fmtd_ex) + "```" + embed.description = "```\n" + "\n".join(fmtd_ex) + "```" embed.colour = colours.bad return embed diff --git a/exts/ae7q.py b/exts/ae7q.py index 51b3c6c..f85b898 100644 --- a/exts/ae7q.py +++ b/exts/ae7q.py @@ -29,16 +29,16 @@ class AE7QCog(commands.Cog): @commands.group(name="ae7q", aliases=["ae"], category=cmn.cat.lookup) async def _ae7q_lookup(self, ctx: commands.Context): - '''Look up a callsign, FRN, or Licensee ID on [ae7q.com](http://ae7q.com/).''' + """Look up a callsign, FRN, or Licensee ID on [ae7q.com](http://ae7q.com/).""" if ctx.invoked_subcommand is None: await ctx.send_help(ctx.command) @_ae7q_lookup.command(name="call", aliases=["c"], category=cmn.cat.lookup) async def _ae7q_call(self, ctx: commands.Context, callsign: str): - '''Look up the history of a callsign on [ae7q.com](http://ae7q.com/).''' + """Look up the history of a callsign on [ae7q.com](http://ae7q.com/).""" with ctx.typing(): callsign = callsign.upper() - desc = '' + desc = "" base_url = "http://ae7q.com/query/data/CallHistory.php?CALL=" embed = cmn.embed_factory(ctx) @@ -56,20 +56,20 @@ class AE7QCog(commands.Cog): if len(table[0]) == 1: for row in table: desc += " ".join(row.getText().split()) - desc += '\n' - desc = desc.replace(callsign, f'`{callsign}`') + desc += "\n" + desc = desc.replace(callsign, f"`{callsign}`") table = tables[1] table_headers = table[0].find_all("th") - first_header = ''.join(table_headers[0].strings) if len(table_headers) > 0 else None + first_header = "".join(table_headers[0].strings) if len(table_headers) > 0 else None # catch if the wrong table was selected - if first_header is None or first_header != 'Entity Name': + if first_header is None or first_header != "Entity Name": embed.title = f"AE7Q History for {callsign}" embed.colour = cmn.colours.bad embed.url = base_url + callsign embed.description = desc - embed.description += f'\nNo records found for `{callsign}`' + embed.description += f"\nNo records found for `{callsign}`" await ctx.send(embed=embed) return @@ -82,18 +82,18 @@ class AE7QCog(commands.Cog): # add the first three rows of the table to the embed for row in table[0:3]: - header = f'**{row[0]}** ({row[1]})' # **Name** (Applicant Type) - body = (f'Class: *{row[2]}*\n' - f'Region: *{row[3]}*\n' - f'Status: *{row[4]}*\n' - f'Granted: *{row[5]}*\n' - f'Effective: *{row[6]}*\n' - f'Cancelled: *{row[7]}*\n' - f'Expires: *{row[8]}*') + header = f"**{row[0]}** ({row[1]})" # **Name** (Applicant Type) + body = (f"Class: *{row[2]}*\n" + f"Region: *{row[3]}*\n" + f"Status: *{row[4]}*\n" + f"Granted: *{row[5]}*\n" + f"Effective: *{row[6]}*\n" + f"Cancelled: *{row[7]}*\n" + f"Expires: *{row[8]}*") embed.add_field(name=header, value=body, inline=False) if len(table) > 3: - desc += f'\nRecords 1 to 3 of {len(table)}. See ae7q.com for more...' + desc += f"\nRecords 1 to 3 of {len(table)}. See ae7q.com for more..." embed.description = desc @@ -101,10 +101,10 @@ class AE7QCog(commands.Cog): @_ae7q_lookup.command(name="trustee", aliases=["t"], category=cmn.cat.lookup) async def _ae7q_trustee(self, ctx: commands.Context, callsign: str): - '''Look up the licenses for which a licensee is trustee on [ae7q.com](http://ae7q.com/).''' + """Look up the licenses for which a licensee is trustee on [ae7q.com](http://ae7q.com/).""" with ctx.typing(): callsign = callsign.upper() - desc = '' + desc = "" base_url = "http://ae7q.com/query/data/CallHistory.php?CALL=" embed = cmn.embed_factory(ctx) @@ -123,12 +123,12 @@ class AE7QCog(commands.Cog): embed.colour = cmn.colours.bad embed.url = base_url + callsign embed.description = desc - embed.description += f'\nNo records found for `{callsign}`' + embed.description += f"\nNo records found for `{callsign}`" await ctx.send(embed=embed) return table_headers = table[0].find_all("th") - first_header = ''.join(table_headers[0].strings) if len(table_headers) > 0 else None + first_header = "".join(table_headers[0].strings) if len(table_headers) > 0 else None # catch if the wrong table was selected if first_header is None or not first_header.startswith("With"): @@ -136,7 +136,7 @@ class AE7QCog(commands.Cog): embed.colour = cmn.colours.bad embed.url = base_url + callsign embed.description = desc - embed.description += f'\nNo records found for `{callsign}`' + embed.description += f"\nNo records found for `{callsign}`" await ctx.send(embed=embed) return @@ -149,18 +149,18 @@ class AE7QCog(commands.Cog): # add the first three rows of the table to the embed for row in table[0:3]: - header = f'**{row[0]}** ({row[3]})' # **Name** (Applicant Type) - body = (f'Name: *{row[2]}*\n' - f'Region: *{row[1]}*\n' - f'Status: *{row[4]}*\n' - f'Granted: *{row[5]}*\n' - f'Effective: *{row[6]}*\n' - f'Cancelled: *{row[7]}*\n' - f'Expires: *{row[8]}*') + header = f"**{row[0]}** ({row[3]})" # **Name** (Applicant Type) + body = (f"Name: *{row[2]}*\n" + f"Region: *{row[1]}*\n" + f"Status: *{row[4]}*\n" + f"Granted: *{row[5]}*\n" + f"Effective: *{row[6]}*\n" + f"Cancelled: *{row[7]}*\n" + f"Expires: *{row[8]}*") embed.add_field(name=header, value=body, inline=False) if len(table) > 3: - desc += f'\nRecords 1 to 3 of {len(table)}. See ae7q.com for more...' + desc += f"\nRecords 1 to 3 of {len(table)}. See ae7q.com for more..." embed.description = desc @@ -168,11 +168,11 @@ class AE7QCog(commands.Cog): @_ae7q_lookup.command(name="applications", aliases=["a"], category=cmn.cat.lookup) async def _ae7q_applications(self, ctx: commands.Context, callsign: str): - '''Look up the application history for a callsign on [ae7q.com](http://ae7q.com/).''' + """Look up the application history for a callsign on [ae7q.com](http://ae7q.com/).""" """ with ctx.typing(): callsign = callsign.upper() - desc = '' + desc = "" base_url = "http://ae7q.com/query/data/CallHistory.php?CALL=" embed = cmn.embed_factory(ctx) @@ -190,14 +190,14 @@ class AE7QCog(commands.Cog): if len(table[0]) == 1: for row in table: desc += " ".join(row.getText().split()) - desc += '\n' - desc = desc.replace(callsign, f'`{callsign}`') + desc += "\n" + desc = desc.replace(callsign, f"`{callsign}`") # select the last table to get applications table = tables[-1] table_headers = table[0].find_all("th") - first_header = ''.join(table_headers[0].strings) if len(table_headers) > 0 else None + first_header = "".join(table_headers[0].strings) if len(table_headers) > 0 else None # catch if the wrong table was selected if first_header is None or not first_header.startswith("Receipt"): @@ -205,7 +205,7 @@ class AE7QCog(commands.Cog): embed.colour = cmn.colours.bad embed.url = base_url + callsign embed.description = desc - embed.description += f'\nNo records found for `{callsign}`' + embed.description += f"\nNo records found for `{callsign}`" await ctx.send(embed=embed) return @@ -218,16 +218,16 @@ class AE7QCog(commands.Cog): # add the first three rows of the table to the embed for row in table[0:3]: - header = f'**{row[1]}** ({row[3]})' # **Name** (Callsign) - body = (f'Received: *{row[0]}*\n' - f'Region: *{row[2]}*\n' - f'Purpose: *{row[5]}*\n' - f'Last Action: *{row[7]}*\n' - f'Application Status: *{row[8]}*\n') + header = f"**{row[1]}** ({row[3]})" # **Name** (Callsign) + body = (f"Received: *{row[0]}*\n" + f"Region: *{row[2]}*\n" + f"Purpose: *{row[5]}*\n" + f"Last Action: *{row[7]}*\n" + f"Application Status: *{row[8]}*\n") embed.add_field(name=header, value=body, inline=False) if len(table) > 3: - desc += f'\nRecords 1 to 3 of {len(table)}. See ae7q.com for more...' + desc += f"\nRecords 1 to 3 of {len(table)}. See ae7q.com for more..." embed.description = desc @@ -238,7 +238,7 @@ class AE7QCog(commands.Cog): @_ae7q_lookup.command(name="frn", aliases=["f"], category=cmn.cat.lookup) async def _ae7q_frn(self, ctx: commands.Context, frn: str): - '''Look up the history of an FRN on [ae7q.com](http://ae7q.com/).''' + """Look up the history of an FRN on [ae7q.com](http://ae7q.com/).""" """ NOTES: - 2 tables: callsign history and application history @@ -260,21 +260,21 @@ class AE7QCog(commands.Cog): embed.title = f"AE7Q History for FRN {frn}" embed.colour = cmn.colours.bad embed.url = base_url + frn - embed.description = f'No records found for FRN `{frn}`' + embed.description = f"No records found for FRN `{frn}`" await ctx.send(embed=embed) return table = tables[0] table_headers = table[0].find_all("th") - first_header = ''.join(table_headers[0].strings) if len(table_headers) > 0 else None + first_header = "".join(table_headers[0].strings) if len(table_headers) > 0 else None # catch if the wrong table was selected - if first_header is None or not first_header.startswith('With Licensee'): + if first_header is None or not first_header.startswith("With Licensee"): embed.title = f"AE7Q History for FRN {frn}" embed.colour = cmn.colours.bad embed.url = base_url + frn - embed.description = f'No records found for FRN `{frn}`' + embed.description = f"No records found for FRN `{frn}`" await ctx.send(embed=embed) return @@ -287,25 +287,25 @@ class AE7QCog(commands.Cog): # add the first three rows of the table to the embed for row in table[0:3]: - header = f'**{row[0]}** ({row[3]})' # **Callsign** (Applicant Type) - body = (f'Name: *{row[2]}*\n' - f'Class: *{row[4]}*\n' - f'Region: *{row[1]}*\n' - f'Status: *{row[5]}*\n' - f'Granted: *{row[6]}*\n' - f'Effective: *{row[7]}*\n' - f'Cancelled: *{row[8]}*\n' - f'Expires: *{row[9]}*') + header = f"**{row[0]}** ({row[3]})" # **Callsign** (Applicant Type) + body = (f"Name: *{row[2]}*\n" + f"Class: *{row[4]}*\n" + f"Region: *{row[1]}*\n" + f"Status: *{row[5]}*\n" + f"Granted: *{row[6]}*\n" + f"Effective: *{row[7]}*\n" + f"Cancelled: *{row[8]}*\n" + f"Expires: *{row[9]}*") embed.add_field(name=header, value=body, inline=False) if len(table) > 3: - embed.description = f'Records 1 to 3 of {len(table)}. See ae7q.com for more...' + embed.description = f"Records 1 to 3 of {len(table)}. See ae7q.com for more..." await ctx.send(embed=embed) @_ae7q_lookup.command(name="licensee", aliases=["l"], category=cmn.cat.lookup) async def _ae7q_licensee(self, ctx: commands.Context, licensee_id: str): - '''Look up the history of a licensee ID on [ae7q.com](http://ae7q.com/).''' + """Look up the history of a licensee ID on [ae7q.com](http://ae7q.com/).""" with ctx.typing(): licensee_id = licensee_id.upper() base_url = "http://ae7q.com/query/data/LicenseeIdHistory.php?ID=" @@ -323,21 +323,21 @@ class AE7QCog(commands.Cog): embed.title = f"AE7Q History for Licensee {licensee_id}" embed.colour = cmn.colours.bad embed.url = base_url + licensee_id - embed.description = f'No records found for Licensee `{licensee_id}`' + embed.description = f"No records found for Licensee `{licensee_id}`" await ctx.send(embed=embed) return table = tables[0] table_headers = table[0].find_all("th") - first_header = ''.join(table_headers[0].strings) if len(table_headers) > 0 else None + first_header = "".join(table_headers[0].strings) if len(table_headers) > 0 else None # catch if the wrong table was selected - if first_header is None or not first_header.startswith('With FCC'): + if first_header is None or not first_header.startswith("With FCC"): embed.title = f"AE7Q History for Licensee {licensee_id}" embed.colour = cmn.colours.bad embed.url = base_url + licensee_id - embed.description = f'No records found for Licensee `{licensee_id}`' + embed.description = f"No records found for Licensee `{licensee_id}`" await ctx.send(embed=embed) return @@ -350,19 +350,19 @@ class AE7QCog(commands.Cog): # add the first three rows of the table to the embed for row in table[0:3]: - header = f'**{row[0]}** ({row[3]})' # **Callsign** (Applicant Type) - body = (f'Name: *{row[2]}*\n' - f'Class: *{row[4]}*\n' - f'Region: *{row[1]}*\n' - f'Status: *{row[5]}*\n' - f'Granted: *{row[6]}*\n' - f'Effective: *{row[7]}*\n' - f'Cancelled: *{row[8]}*\n' - f'Expires: *{row[9]}*') + header = f"**{row[0]}** ({row[3]})" # **Callsign** (Applicant Type) + body = (f"Name: *{row[2]}*\n" + f"Class: *{row[4]}*\n" + f"Region: *{row[1]}*\n" + f"Status: *{row[5]}*\n" + f"Granted: *{row[6]}*\n" + f"Effective: *{row[7]}*\n" + f"Cancelled: *{row[8]}*\n" + f"Expires: *{row[9]}*") embed.add_field(name=header, value=body, inline=False) if len(table) > 3: - embed.description = f'Records 1 to 3 of {len(table)}. See ae7q.com for more...' + embed.description = f"Records 1 to 3 of {len(table)}. See ae7q.com for more..." await ctx.send(embed=embed) @@ -372,13 +372,13 @@ async def process_table(table: list): table_contents = [] for tr in table: row = [] - for td in tr.find_all('td'): + for td in tr.find_all("td"): cell_val = td.getText().strip() - row.append(cell_val if cell_val else '-') + row.append(cell_val if cell_val else "-") # take care of columns that span multiple rows by copying the contents rightward - if 'colspan' in td.attrs and int(td.attrs['colspan']) > 1: - for i in range(int(td.attrs['colspan']) - 1): + if "colspan" in td.attrs and int(td.attrs["colspan"]) > 1: + for i in range(int(td.attrs["colspan"]) - 1): row.append(row[-1]) # get rid of ditto marks by copying the contents from the previous row diff --git a/exts/base.py b/exts/base.py index 15b20b2..2d04845 100644 --- a/exts/base.py +++ b/exts/base.py @@ -24,7 +24,7 @@ import data.options as opt class QrmHelpCommand(commands.HelpCommand): def __init__(self): - super().__init__(command_attrs={'help': 'Shows help about qrm or a command', 'aliases': ['h']}) + super().__init__(command_attrs={"help": "Shows help about qrm or a command", "aliases": ["h"]}) self.verify_checks = True async def get_bot_mapping(self): @@ -32,7 +32,7 @@ class QrmHelpCommand(commands.HelpCommand): mapping = {} for cmd in await self.filter_commands(bot.commands, sort=True): - cat = cmd.__original_kwargs__.get('category', None) + cat = cmd.__original_kwargs__.get("category", None) if cat in mapping: mapping[cat].append(cmd) else: @@ -42,27 +42,27 @@ class QrmHelpCommand(commands.HelpCommand): async def get_command_signature(self, command): parent = command.full_parent_name if command.aliases != []: - aliases = ', '.join(command.aliases) + aliases = ", ".join(command.aliases) fmt = command.name if parent: - fmt = f'{parent} {fmt}' + fmt = f"{parent} {fmt}" alias = fmt - return f'{opt.prefix}{alias} {command.signature}\n *Aliases:* {aliases}' - alias = command.name if not parent else f'{parent} {command.name}' - return f'{opt.prefix}{alias} {command.signature}' + return f"{opt.prefix}{alias} {command.signature}\n *Aliases:* {aliases}" + alias = command.name if not parent else f"{parent} {command.name}" + return f"{opt.prefix}{alias} {command.signature}" async def send_error_message(self, error): embed = cmn.embed_factory(self.context) - embed.title = 'qrm Help Error' + embed.title = "qrm Help Error" embed.description = error embed.colour = cmn.colours.bad await self.context.send(embed=embed) async def send_bot_help(self, mapping): embed = cmn.embed_factory(self.context) - embed.title = 'qrm Help' - embed.description = (f'For command-specific help and usage, use `{opt.prefix}help [command name]`' - '. Many commands have shorter aliases.') + embed.title = "qrm Help" + embed.description = (f"For command-specific help and usage, use `{opt.prefix}help [command name]`." + " Many commands have shorter aliases.") mapping = await mapping for cat, cmds in mapping.items(): @@ -70,9 +70,9 @@ class QrmHelpCommand(commands.HelpCommand): continue names = sorted([cmd.name for cmd in cmds]) if cat is not None: - embed.add_field(name=cat.title(), value=', '.join(names), inline=False) + embed.add_field(name=cat.title(), value=", ".join(names), inline=False) else: - embed.add_field(name='Other', value=', '.join(names), inline=False) + embed.add_field(name="Other", value=", ".join(names), inline=False) await self.context.send(embed=embed) async def send_command_help(self, command): @@ -112,27 +112,27 @@ class BaseCog(commands.Cog): embed.add_field(name="Authors", value=", ".join(info.authors)) embed.add_field(name="License", value=info.license) - embed.add_field(name="Version", value=f'v{info.release}') + embed.add_field(name="Version", value=f"v{info.release}") embed.add_field(name="Contributing", value=info.contributing, inline=False) embed.add_field(name="Official Server", value=info.bot_server, inline=False) embed.set_thumbnail(url=str(self.bot.user.avatar_url)) await ctx.send(embed=embed) - @commands.command(name="ping", aliases=['beep']) + @commands.command(name="ping", aliases=["beep"]) async def _ping(self, ctx: commands.Context): """Show the current latency to the discord endpoint.""" embed = cmn.embed_factory(ctx) - content = '' + content = "" if ctx.invoked_with == "beep": embed.title = "**Boop!**" else: - content = ctx.message.author.mention if random.random() < 0.05 else '' + content = ctx.message.author.mention if random.random() < 0.05 else "" embed.title = "🏓 **Pong!**" - embed.description = f'Current ping is {self.bot.latency*1000:.1f} ms' + embed.description = f"Current ping is {self.bot.latency*1000:.1f} ms" await ctx.send(content, embed=embed) @commands.command(name="changelog", aliases=["clog"]) - async def _changelog(self, ctx: commands.Context, version: str = 'latest'): + async def _changelog(self, ctx: commands.Context, version: str = "latest"): """Show what has changed in a bot version.""" embed = cmn.embed_factory(ctx) embed.title = "qrm Changelog" @@ -144,25 +144,25 @@ class BaseCog(commands.Cog): version = version.lower() - if version == 'latest': + if version == "latest": version = info.release - if version == 'unreleased': - version = 'Unreleased' + if version == "unreleased": + version = "Unreleased" try: log = changelog[version] except KeyError: embed.title += ": Version Not Found" - embed.description += '\n\n**Valid versions:** latest, ' - embed.description += ', '.join(vers) + embed.description += "\n\n**Valid versions:** latest, " + embed.description += ", ".join(vers) embed.colour = cmn.colours.bad await ctx.send(embed=embed) return - if 'date' in log: - embed.description += f'\n\n**v{version}** ({log["date"]})' + if "date" in log: + embed.description += f"\n\n**v{version}** ({log['date']})" else: - embed.description += f'\n\n**v{version}**' + embed.description += f"\n\n**v{version}**" embed = await format_changelog(log, embed) await ctx.send(embed=embed) @@ -190,36 +190,36 @@ class BaseCog(commands.Cog): def parse_changelog(): changelog = OrderedDict() - ver = '' - heading = '' + ver = "" + heading = "" - with open('CHANGELOG.md') as changelog_file: + with open("CHANGELOG.md") as changelog_file: for line in changelog_file.readlines(): - if line.strip() == '': + if line.strip() == "": continue - if re.match(r'##[^#]', line): - ver_match = re.match(r'\[(.+)\](?: - )?(\d{4}-\d{2}-\d{2})?', line.lstrip('#').strip()) + if re.match(r"##[^#]", line): + ver_match = re.match(r"\[(.+)\](?: - )?(\d{4}-\d{2}-\d{2})?", line.lstrip("#").strip()) if ver_match is not None: ver = ver_match.group(1) changelog[ver] = dict() if ver_match.group(2): - changelog[ver]['date'] = ver_match.group(2) - elif re.match(r'###[^#]', line): - heading = line.lstrip('#').strip() + changelog[ver]["date"] = ver_match.group(2) + elif re.match(r"###[^#]", line): + heading = line.lstrip("#").strip() changelog[ver][heading] = [] - elif ver != '' and heading != '': - if line.startswith('-'): - changelog[ver][heading].append(line.lstrip('-').strip()) + elif ver != "" and heading != "": + if line.startswith("-"): + changelog[ver][heading].append(line.lstrip("-").strip()) return changelog async def format_changelog(log: dict, embed: discord.Embed): for header, lines in log.items(): - formatted = '' - if header != 'date': + formatted = "" + if header != "date": for line in lines: - formatted += f'- {line}\n' - embed.add_field(name=f'**{header}**', value=formatted, inline=False) + formatted += f"- {line}\n" + embed.add_field(name=f"**{header}**", value=formatted, inline=False) return embed diff --git a/exts/fun.py b/exts/fun.py index d84f513..dddd480 100644 --- a/exts/fun.py +++ b/exts/fun.py @@ -17,37 +17,37 @@ import common as cmn class FunCog(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot - with open('resources/words') as words_file: + with open("resources/words") as words_file: self.words = words_file.read().lower().splitlines() - @commands.command(name="xkcd", aliases=['x'], category=cmn.cat.fun) + @commands.command(name="xkcd", aliases=["x"], category=cmn.cat.fun) async def _xkcd(self, ctx: commands.Context, number: str): - '''Look up an xkcd by number.''' - await ctx.send('http://xkcd.com/' + number) + """Look up an xkcd by number.""" + await ctx.send("http://xkcd.com/" + number) @commands.command(name="tar", category=cmn.cat.fun) async def _tar(self, ctx: commands.Context): - '''Returns an xkcd about tar.''' - await ctx.send('http://xkcd.com/1168') + """Returns an xkcd about tar.""" + await ctx.send("http://xkcd.com/1168") @commands.command(name="xd", hidden=True, category=cmn.cat.fun) async def _xd(self, ctx: commands.Context): - '''ecks dee''' - await ctx.send('ECKS DEE :smirk:') + """ecks dee""" + await ctx.send("ECKS DEE :smirk:") - @commands.command(name="funetics", aliases=['fun'], category=cmn.cat.fun) + @commands.command(name="funetics", aliases=["fun"], category=cmn.cat.fun) async def _funetics_lookup(self, ctx: commands.Context, *, msg: str): - '''Get fun phonetics for a word or phrase.''' + """Get fun phonetics for a word or phrase.""" with ctx.typing(): - result = '' + result = "" for char in msg.lower(): if char.isalpha(): result += random.choice([word for word in self.words if word[0] == char]) else: result += char - result += ' ' + result += " " embed = cmn.embed_factory(ctx) - embed.title = f'Funetics for {msg}' + embed.title = f"Funetics for {msg}" embed.description = result.title() embed.colour = cmn.colours.good await ctx.send(embed=embed) diff --git a/exts/grid.py b/exts/grid.py index 3abd6ef..a851b42 100644 --- a/exts/grid.py +++ b/exts/grid.py @@ -20,27 +20,27 @@ class GridCog(commands.Cog): @commands.command(name="grid", category=cmn.cat.maps) async def _grid_sq_lookup(self, ctx: commands.Context, lat: str, lon: str): - '''Calculates the grid square for latitude and longitude coordinates, -with negative being latitude South and longitude West.''' + """Calculates the grid square for latitude and longitude coordinates, +with negative being latitude South and longitude West.""" with ctx.typing(): grid = "**" latf = float(lat) + 90 lonf = float(lon) + 180 if 0 <= latf <= 180 and 0 <= lonf <= 360: - grid += chr(ord('A') + int(lonf / 20)) - grid += chr(ord('A') + int(latf / 10)) - grid += chr(ord('0') + int((lonf % 20)/2)) - grid += chr(ord('0') + int((latf % 10)/1)) - grid += chr(ord('a') + int((lonf - (int(lonf/2)*2)) / (5/60))) - grid += chr(ord('a') + int((latf - (int(latf/1)*1)) / (2.5/60))) + grid += chr(ord("A") + int(lonf / 20)) + grid += chr(ord("A") + int(latf / 10)) + grid += chr(ord("0") + int((lonf % 20)/2)) + grid += chr(ord("0") + int((latf % 10)/1)) + grid += chr(ord("a") + int((lonf - (int(lonf/2)*2)) / (5/60))) + grid += chr(ord("a") + int((latf - (int(latf/1)*1)) / (2.5/60))) grid += "**" embed = cmn.embed_factory(ctx) - embed.title = f'Maidenhead Grid Locator for {float(lat):.6f}, {float(lon):.6f}' + embed.title = f"Maidenhead Grid Locator for {float(lat):.6f}, {float(lon):.6f}" embed.description = grid embed.colour = cmn.colours.good else: embed = cmn.embed_factory(ctx) - embed.title = f'Error generating grid square for {lat}, {lon}.' + embed.title = f"Error generating grid square for {lat}, {lon}." embed.description = ("Coordinates out of range.\n" "The valid ranges are:\n" "- Latitude: `-90` to `+90`\n" @@ -48,29 +48,29 @@ with negative being latitude South and longitude West.''' embed.colour = cmn.colours.bad await ctx.send(embed=embed) - @commands.command(name="ungrid", aliases=['loc'], category=cmn.cat.maps) + @commands.command(name="ungrid", aliases=["loc"], category=cmn.cat.maps) async def _location_lookup(self, ctx: commands.Context, grid: str, grid2: str = None): - '''Calculates the latitude and longitude for the center of a grid square. -If two grid squares are given, the distance and azimuth between them is calculated.''' + """Calculates the latitude and longitude for the center of a grid square. +If two grid squares are given, the distance and azimuth between them is calculated.""" with ctx.typing(): - if grid2 is None or grid2 == '': + if grid2 is None or grid2 == "": try: grid = grid.upper() loc = get_coords(grid) embed = cmn.embed_factory(ctx) - embed.title = f'Latitude and Longitude for {grid}' + embed.title = f"Latitude and Longitude for {grid}" embed.colour = cmn.colours.good if len(grid) >= 6: - embed.description = f'**{loc[0]:.5f}, {loc[1]:.5f}**' - embed.url = f'https://www.openstreetmap.org/#map=13/{loc[0]:.5f}/{loc[1]:.5f}' + embed.description = f"**{loc[0]:.5f}, {loc[1]:.5f}**" + embed.url = f"https://www.openstreetmap.org/#map=13/{loc[0]:.5f}/{loc[1]:.5f}" else: - embed.description = f'**{loc[0]:.1f}, {loc[1]:.1f}**' - embed.url = f'https://www.openstreetmap.org/#map=10/{loc[0]:.1f}/{loc[1]:.1f}' + embed.description = f"**{loc[0]:.1f}, {loc[1]:.1f}**" + embed.url = f"https://www.openstreetmap.org/#map=10/{loc[0]:.1f}/{loc[1]:.1f}" except Exception as e: embed = cmn.embed_factory(ctx) - embed.title = f'Error generating latitude and longitude for grid {grid}.' + embed.title = f"Error generating latitude and longitude for grid {grid}." embed.description = str(e) embed.colour = cmn.colours.bad else: @@ -101,12 +101,12 @@ If two grid squares are given, the distance and azimuth between them is calculat bearing = (math.degrees(math.atan2(y_dist, x_dist)) + 360) % 360 embed = cmn.embed_factory(ctx) - embed.title = f'Great Circle Distance and Bearing from {grid} to {grid2}' - embed.description = f'**Distance:** {d:.1f} km ({d_mi:.1f} mi)\n**Bearing:** {bearing:.1f}°' + embed.title = f"Great Circle Distance and Bearing from {grid} to {grid2}" + embed.description = f"**Distance:** {d:.1f} km ({d_mi:.1f} mi)\n**Bearing:** {bearing:.1f}°" embed.colour = cmn.colours.good except Exception as e: embed = cmn.embed_factory(ctx) - embed.title = f'Error generating great circle distance and bearing from {grid} and {grid2}.' + embed.title = f"Error generating great circle distance and bearing from {grid} and {grid2}." embed.description = str(e) embed.colour = cmn.colours.bad await ctx.send(embed=embed) @@ -114,23 +114,23 @@ If two grid squares are given, the distance and azimuth between them is calculat def get_coords(grid: str): if len(grid) < 3: - raise ValueError('The grid locator must be at least 4 characters long.') + raise ValueError("The grid locator must be at least 4 characters long.") if not grid[0:2].isalpha() or not grid[2:4].isdigit(): if len(grid) <= 4: - raise ValueError('The grid locator must be of the form AA##.') + raise ValueError("The grid locator must be of the form AA##.") if len(grid) >= 6 and not grid[5:7].isalpha(): - raise ValueError('The grid locator must be of the form AA##AA.') + raise ValueError("The grid locator must be of the form AA##AA.") - lon = ((ord(grid[0]) - ord('A')) * 20) - 180 - lat = ((ord(grid[1]) - ord('A')) * 10) - 90 - lon += ((ord(grid[2]) - ord('0')) * 2) - lat += ((ord(grid[3]) - ord('0')) * 1) + lon = ((ord(grid[0]) - ord("A")) * 20) - 180 + lat = ((ord(grid[1]) - ord("A")) * 10) - 90 + lon += ((ord(grid[2]) - ord("0")) * 2) + lat += ((ord(grid[3]) - ord("0")) * 1) if len(grid) >= 6: # have subsquares - lon += ((ord(grid[4])) - ord('A')) * (5/60) - lat += ((ord(grid[5])) - ord('A')) * (2.5/60) + lon += ((ord(grid[4])) - ord("A")) * (5/60) + lat += ((ord(grid[5])) - ord("A")) * (2.5/60) # move to center of subsquare lon += (2.5/60) lat += (1.25/60) diff --git a/exts/ham.py b/exts/ham.py index 71766ba..062ecc9 100644 --- a/exts/ham.py +++ b/exts/ham.py @@ -21,9 +21,9 @@ class HamCog(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot - @commands.command(name="qcode", aliases=['q'], category=cmn.cat.ref) + @commands.command(name="qcode", aliases=["q"], category=cmn.cat.ref) async def _qcode_lookup(self, ctx: commands.Context, qcode: str): - '''Look up a Q Code.''' + """Look up a Q Code.""" with ctx.typing(): qcode = qcode.upper() embed = cmn.embed_factory(ctx) @@ -32,49 +32,49 @@ class HamCog(commands.Cog): embed.description = qcodes.qcodes[qcode] embed.colour = cmn.colours.good else: - embed.title = f'Q Code {qcode} not found' + embed.title = f"Q Code {qcode} not found" embed.colour = cmn.colours.bad await ctx.send(embed=embed) - @commands.command(name="phonetics", aliases=['ph', 'phoneticize', 'phoneticise', 'phone'], category=cmn.cat.ref) + @commands.command(name="phonetics", aliases=["ph", "phoneticize", "phoneticise", "phone"], category=cmn.cat.ref) async def _phonetics_lookup(self, ctx: commands.Context, *, msg: str): - '''Get phonetics for a word or phrase.''' + """Get phonetics for a word or phrase.""" with ctx.typing(): - result = '' + result = "" for char in msg.lower(): if char.isalpha(): result += phonetics.phonetics[char] else: result += char - result += ' ' + result += " " embed = cmn.embed_factory(ctx) - embed.title = f'Phonetics for {msg}' + embed.title = f"Phonetics for {msg}" embed.description = result.title() embed.colour = cmn.colours.good await ctx.send(embed=embed) - @commands.command(name="utc", aliases=['z'], category=cmn.cat.ref) + @commands.command(name="utc", aliases=["z"], category=cmn.cat.ref) async def _utc_lookup(self, ctx: commands.Context): - '''Gets the current time in UTC.''' + """Gets the current time in UTC.""" with ctx.typing(): now = datetime.utcnow() - result = '**' + now.strftime('%Y-%m-%d %H:%M') + 'Z**' + result = "**" + now.strftime("%Y-%m-%d %H:%M") + "Z**" embed = cmn.embed_factory(ctx) - embed.title = 'The current time is:' + embed.title = "The current time is:" embed.description = result embed.colour = cmn.colours.good await ctx.send(embed=embed) @commands.command(name="prefixes", aliases=["vanity", "pfx", "vanities", "prefix"], category=cmn.cat.ref) async def _vanity_prefixes(self, ctx: commands.Context, country: str = None): - '''Lists valid prefixes for countries.''' + """Lists valid prefixes for countries.""" if country is None: await ctx.send_help(ctx.command) return embed = cmn.embed_factory(ctx) if country.lower() not in callsign_info.options: - embed.title = f'{country} not found!', - embed.description = f'Valid countries: {", ".join(callsign_info.options.keys())}', + embed.title = f"{country} not found!", + embed.description = f"Valid countries: {', '.join(callsign_info.options.keys())}", embed.colour = cmn.colours.bad else: embed.title = callsign_info.options[country.lower()][0] diff --git a/exts/image.py b/exts/image.py index 0388a32..33abed9 100644 --- a/exts/image.py +++ b/exts/image.py @@ -18,8 +18,8 @@ import common as cmn class ImageCog(commands.Cog): - gl_url = ('http://www.fourmilab.ch/cgi-bin/uncgi/Earth?img=NOAAtopo.evif' - '&imgsize=320&dynimg=y&opt=-p&lat=&lon=&alt=&tle=&date=0&utc=&jd=') + gl_url = ("http://www.fourmilab.ch/cgi-bin/uncgi/Earth?img=NOAAtopo.evif" + "&imgsize=320&dynimg=y&opt=-p&lat=&lon=&alt=&tle=&date=0&utc=&jd=") def __init__(self, bot: commands.Bot): self.bot = bot @@ -27,17 +27,17 @@ class ImageCog(commands.Cog): self.maps = cmn.ImagesGroup(cmn.paths.maps / "meta.json") self.session = aiohttp.ClientSession(connector=bot.qrm.connector) - @commands.command(name="bandplan", aliases=['plan', 'bands'], category=cmn.cat.ref) - async def _bandplan(self, ctx: commands.Context, region: str = ''): - '''Posts an image of Frequency Allocations.''' + @commands.command(name="bandplan", aliases=["plan", "bands"], category=cmn.cat.ref) + async def _bandplan(self, ctx: commands.Context, region: str = ""): + """Posts an image of Frequency Allocations.""" async with ctx.typing(): arg = region.lower() embed = cmn.embed_factory(ctx) if arg not in self.bandcharts: - desc = 'Possible arguments are:\n' + desc = "Possible arguments are:\n" for key, img in self.bandcharts.items(): - desc += f'`{key}`: {img.name}{(" " + img.emoji if img.emoji else "")}\n' - embed.title = f'Bandplan Not Found!' + desc += f"`{key}`: {img.name}{(' ' + img.emoji if img.emoji else '')}\n" + embed.title = f"Bandplan Not Found!" embed.description = desc embed.colour = cmn.colours.bad await ctx.send(embed=embed) @@ -51,20 +51,20 @@ class ImageCog(commands.Cog): embed.add_field(name="Source", value=metadata.source) embed.title = metadata.long_name + (" " + metadata.emoji if metadata.emoji else "") embed.colour = cmn.colours.good - embed.set_image(url='attachment://' + metadata.filename) + embed.set_image(url="attachment://" + metadata.filename) await ctx.send(embed=embed, file=img) @commands.command(name="map", category=cmn.cat.maps) - async def _map(self, ctx: commands.Context, map_id: str = ''): - '''Posts an image of a ham-relevant map.''' + async def _map(self, ctx: commands.Context, map_id: str = ""): + """Posts an image of a ham-relevant map.""" async with ctx.typing(): arg = map_id.lower() embed = cmn.embed_factory(ctx) if arg not in self.maps: - desc = 'Possible arguments are:\n' + desc = "Possible arguments are:\n" for key, img in self.maps.items(): - desc += f'`{key}`: {img.name}{(" " + img.emoji if img.emoji else "")}\n' - embed.title = 'Map Not Found!' + desc += f"`{key}`: {img.name}{(' ' + img.emoji if img.emoji else '')}\n" + embed.title = "Map Not Found!" embed.description = desc embed.colour = cmn.colours.bad await ctx.send(embed=embed) @@ -78,22 +78,22 @@ class ImageCog(commands.Cog): embed.add_field(name="Source", value=metadata.source) embed.title = metadata.long_name + (" " + metadata.emoji if metadata.emoji else "") embed.colour = cmn.colours.good - embed.set_image(url='attachment://' + metadata.filename) + embed.set_image(url="attachment://" + metadata.filename) await ctx.send(embed=embed, file=img) - @commands.command(name="grayline", aliases=['greyline', 'grey', 'gray', 'gl'], category=cmn.cat.maps) + @commands.command(name="grayline", aliases=["greyline", "grey", "gray", "gl"], category=cmn.cat.maps) async def _grayline(self, ctx: commands.Context): - '''Posts a map of the current greyline, where HF propagation is the best.''' + """Posts a map of the current greyline, where HF propagation is the best.""" async with ctx.typing(): embed = cmn.embed_factory(ctx) - embed.title = 'Current Greyline Conditions' + embed.title = "Current Greyline Conditions" embed.colour = cmn.colours.good async with self.session.get(self.gl_url) as resp: if resp.status != 200: raise cmn.BotHTTPError(resp) data = io.BytesIO(await resp.read()) - embed.set_image(url=f'attachment://greyline.jpg') - await ctx.send(embed=embed, file=discord.File(data, 'greyline.jpg')) + embed.set_image(url=f"attachment://greyline.jpg") + await ctx.send(embed=embed, file=discord.File(data, "greyline.jpg")) def setup(bot: commands.Bot): diff --git a/exts/lookup.py b/exts/lookup.py index ae22e7a..6416386 100644 --- a/exts/lookup.py +++ b/exts/lookup.py @@ -19,48 +19,48 @@ class LookupCog(commands.Cog): def __init__(self, bot): self.bot = bot try: - self.cty = BigCty('./data/cty.json') + self.cty = BigCty("./data/cty.json") except OSError: self.cty = BigCty() # TODO: See #107 # @commands.command(name="sat", category=cmn.cat.lookup) # async def _sat_lookup(self, ctx: commands.Context, sat_name: str, grid1: str, grid2: str = None): - # '''Links to info about satellite passes on satmatch.com.''' - # now = datetime.utcnow().strftime('%Y-%m-%d%%20%H:%M') - # if grid2 is None or grid2 == '': - # await ctx.send(f'http://www.satmatch.com/satellite/{sat_name}/obs1/{grid1}' - # f'?search_start_time={now}&duration_hrs=24') + # """Links to info about satellite passes on satmatch.com.""" + # now = datetime.utcnow().strftime("%Y-%m-%d%%20%H:%M") + # if grid2 is None or grid2 == "": + # await ctx.send(f"http://www.satmatch.com/satellite/{sat_name}/obs1/{grid1}" + # f"?search_start_time={now}&duration_hrs=24") # else: - # await ctx.send(f'http://www.satmatch.com/satellite/{sat_name}/obs1/{grid1}' - # f'/obs2/{grid2}?search_start_time={now}&duration_hrs=24') + # await ctx.send(f"http://www.satmatch.com/satellite/{sat_name}/obs1/{grid1}" + # f"/obs2/{grid2}?search_start_time={now}&duration_hrs=24") - @commands.command(name="dxcc", aliases=['dx'], category=cmn.cat.lookup) + @commands.command(name="dxcc", aliases=["dx"], category=cmn.cat.lookup) async def _dxcc_lookup(self, ctx: commands.Context, query: str): - '''Gets info about a DXCC prefix.''' + """Gets info about a DXCC prefix.""" with ctx.typing(): query = query.upper() full_query = query embed = cmn.embed_factory(ctx) - embed.title = f'DXCC Info for ' - embed.description = f'*Last Updated: {self.cty.formatted_version}*' + embed.title = f"DXCC Info for " + embed.description = f"*Last Updated: {self.cty.formatted_version}*" embed.colour = cmn.colours.bad while query: if query in self.cty.keys(): data = self.cty[query] - embed.add_field(name="Entity", value=data['entity']) - embed.add_field(name="CQ Zone", value=data['cq']) - embed.add_field(name="ITU Zone", value=data['itu']) - embed.add_field(name="Continent", value=data['continent']) + embed.add_field(name="Entity", value=data["entity"]) + embed.add_field(name="CQ Zone", value=data["cq"]) + embed.add_field(name="ITU Zone", value=data["itu"]) + embed.add_field(name="Continent", value=data["continent"]) embed.add_field(name="Time Zone", - value=f'+{data["tz"]}' if data['tz'] > 0 else str(data['tz'])) + value=f"+{data['tz']}" if data["tz"] > 0 else str(data["tz"])) embed.title += query embed.colour = cmn.colours.good break else: query = query[:-1] else: - embed.title += full_query + ' not found' + embed.title += full_query + " not found" embed.colour = cmn.colours.bad await ctx.send(embed=embed) diff --git a/exts/morse.py b/exts/morse.py index 4d0671a..0aa144b 100644 --- a/exts/morse.py +++ b/exts/morse.py @@ -17,63 +17,63 @@ class MorseCog(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot - @commands.command(name="morse", aliases=['cw'], category=cmn.cat.ref) + @commands.command(name="morse", aliases=["cw"], category=cmn.cat.ref) async def _morse(self, ctx: commands.Context, *, msg: str): """Converts ASCII to international morse code.""" with ctx.typing(): - result = '' + result = "" for char in msg.upper(): try: result += morse.morse[char] except KeyError: - result += '' - result += ' ' + result += "" + result += " " embed = cmn.embed_factory(ctx) - embed.title = f'Morse Code for {msg}' - embed.description = '**' + result + '**' + embed.title = f"Morse Code for {msg}" + embed.description = "**" + result + "**" embed.colour = cmn.colours.good await ctx.send(embed=embed) - @commands.command(name="unmorse", aliases=['demorse', 'uncw', 'decw'], category=cmn.cat.ref) + @commands.command(name="unmorse", aliases=["demorse", "uncw", "decw"], category=cmn.cat.ref) async def _unmorse(self, ctx: commands.Context, *, msg: str): - '''Converts international morse code to ASCII.''' + """Converts international morse code to ASCII.""" with ctx.typing(): - result = '' + result = "" msg0 = msg - msg = msg.split('/') + msg = msg.split("/") msg = [m.split() for m in msg] for word in msg: for char in word: try: result += morse.ascii[char] except KeyError: - result += '' - result += ' ' + result += "" + result += " " embed = cmn.embed_factory(ctx) - embed.title = f'ASCII for {msg0}' + embed.title = f"ASCII for {msg0}" embed.description = result embed.colour = cmn.colours.good await ctx.send(embed=embed) - @commands.command(name="cwweight", aliases=["weight", 'cww'], category=cmn.cat.ref) + @commands.command(name="cwweight", aliases=["weight", "cww"], category=cmn.cat.ref) async def _weight(self, ctx: commands.Context, *, msg: str): - '''Calculates the CW Weight of a callsign or message.''' + """Calculates the CW Weight of a callsign or message.""" embed = cmn.embed_factory(ctx) with ctx.typing(): msg = msg.upper() weight = 0 for char in msg: try: - cw_char = morse.morse[char].replace('-', '==') + cw_char = morse.morse[char].replace("-", "==") weight += len(cw_char) * 2 + 2 except KeyError: - embed.title = 'Error in calculation of CW weight' - embed.description = f'Unknown character `{char}` in message' + embed.title = "Error in calculation of CW weight" + embed.description = f"Unknown character `{char}` in message" embed.colour = cmn.colours.bad await ctx.send(embed=embed) return - embed.title = f'CW Weight of {msg}' - embed.description = f'The CW weight is **{weight}**' + embed.title = f"CW Weight of {msg}" + embed.description = f"The CW weight is **{weight}**" embed.colour = cmn.colours.good await ctx.send(embed=embed) diff --git a/exts/qrz.py b/exts/qrz.py index 0d8624a..6bc1b0f 100644 --- a/exts/qrz.py +++ b/exts/qrz.py @@ -26,11 +26,11 @@ class QRZCog(commands.Cog): @commands.command(name="call", aliases=["qrz"], category=cmn.cat.lookup) async def _qrz_lookup(self, ctx: commands.Context, callsign: str, *flags): - '''Look up a callsign on [QRZ.com](https://www.qrz.com/). Add `--link` to only link the QRZ page.''' + """Look up a callsign on [QRZ.com](https://www.qrz.com/). Add `--link` to only link the QRZ page.""" flags = [f.lower() for f in flags] - if keys.qrz_user == '' or keys.qrz_pass == '' or '--link' in flags: - await ctx.send(f'http://qrz.com/db/{callsign}') + if keys.qrz_user == "" or keys.qrz_pass == "" or "--link" in flags: + await ctx.send(f"http://qrz.com/db/{callsign}") return try: @@ -38,38 +38,38 @@ class QRZCog(commands.Cog): except ConnectionError: await self.get_session() - url = f'http://xmldata.qrz.com/xml/current/?s={self.key};callsign={callsign}' + url = f"http://xmldata.qrz.com/xml/current/?s={self.key};callsign={callsign}" async with self.session.get(url) as resp: if resp.status != 200: - raise ConnectionError(f'Unable to connect to QRZ (HTTP Error {resp.status})') + raise ConnectionError(f"Unable to connect to QRZ (HTTP Error {resp.status})") with BytesIO(await resp.read()) as resp_file: resp_xml = etree.parse(resp_file).getroot() - resp_xml_session = resp_xml.xpath('/x:QRZDatabase/x:Session', namespaces={'x': 'http://xmldata.qrz.com'}) - resp_session = {el.tag.split('}')[1]: el.text for el in resp_xml_session[0].getiterator()} - if 'Error' in resp_session: - if 'Session Timeout' in resp_session['Error']: + resp_xml_session = resp_xml.xpath("/x:QRZDatabase/x:Session", namespaces={"x": "http://xmldata.qrz.com"}) + resp_session = {el.tag.split("}")[1]: el.text for el in resp_xml_session[0].getiterator()} + if "Error" in resp_session: + if "Session Timeout" in resp_session["Error"]: await self.get_session() await self._qrz_lookup(ctx, callsign) return - if 'Not found' in resp_session['Error']: + if "Not found" in resp_session["Error"]: embed = cmn.embed_factory(ctx) embed.title = f"QRZ Data for {callsign.upper()}" embed.colour = cmn.colours.bad - embed.description = 'No data found!' + embed.description = "No data found!" await ctx.send(embed=embed) return - raise ValueError(resp_session['Error']) + raise ValueError(resp_session["Error"]) - resp_xml_data = resp_xml.xpath('/x:QRZDatabase/x:Callsign', namespaces={'x': 'http://xmldata.qrz.com'}) - resp_data = {el.tag.split('}')[1]: el.text for el in resp_xml_data[0].getiterator()} + resp_xml_data = resp_xml.xpath("/x:QRZDatabase/x:Callsign", namespaces={"x": "http://xmldata.qrz.com"}) + resp_data = {el.tag.split("}")[1]: el.text for el in resp_xml_data[0].getiterator()} embed = cmn.embed_factory(ctx) embed.title = f"QRZ Data for {resp_data['call']}" embed.colour = cmn.colours.good - embed.url = f'http://www.qrz.com/db/{resp_data["call"]}' - if 'image' in resp_data: - embed.set_thumbnail(url=resp_data['image']) + embed.url = f"http://www.qrz.com/db/{resp_data['call']}" + if "image" in resp_data: + embed.set_thumbnail(url=resp_data["image"]) data = qrz_process_info(resp_data) @@ -81,14 +81,14 @@ class QRZCog(commands.Cog): async def get_session(self): """Session creation and caching.""" self.key = await qrz_login(keys.qrz_user, keys.qrz_pass, self.session) - with open('data/qrz_session', 'w') as qrz_file: + with open("data/qrz_session", "w") as qrz_file: qrz_file.write(self.key) @tasks.loop(count=1) async def _qrz_session_init(self): """Helper task to allow obtaining a session at cog instantiation.""" try: - with open('data/qrz_session') as qrz_file: + with open("data/qrz_session") as qrz_file: self.key = qrz_file.readline().strip() await qrz_test_session(self.key, self.session) except (FileNotFoundError, ConnectionError): @@ -96,86 +96,86 @@ class QRZCog(commands.Cog): async def qrz_login(user: str, passwd: str, session: aiohttp.ClientSession): - url = f'http://xmldata.qrz.com/xml/current/?username={user};password={passwd};agent=discord-qrm2' + url = f"http://xmldata.qrz.com/xml/current/?username={user};password={passwd};agent=discord-qrm2" async with session.get(url) as resp: if resp.status != 200: - raise ConnectionError(f'Unable to connect to QRZ (HTTP Error {resp.status})') + raise ConnectionError(f"Unable to connect to QRZ (HTTP Error {resp.status})") with BytesIO(await resp.read()) as resp_file: resp_xml = etree.parse(resp_file).getroot() - resp_xml_session = resp_xml.xpath('/x:QRZDatabase/x:Session', namespaces={'x': 'http://xmldata.qrz.com'}) - resp_session = {el.tag.split('}')[1]: el.text for el in resp_xml_session[0].getiterator()} - if 'Error' in resp_session: - raise ConnectionError(resp_session['Error']) - if resp_session['SubExp'] == 'non-subscriber': - raise ConnectionError('Invalid QRZ Subscription') - return resp_session['Key'] + resp_xml_session = resp_xml.xpath("/x:QRZDatabase/x:Session", namespaces={"x": "http://xmldata.qrz.com"}) + resp_session = {el.tag.split("}")[1]: el.text for el in resp_xml_session[0].getiterator()} + if "Error" in resp_session: + raise ConnectionError(resp_session["Error"]) + if resp_session["SubExp"] == "non-subscriber": + raise ConnectionError("Invalid QRZ Subscription") + return resp_session["Key"] async def qrz_test_session(key: str, session: aiohttp.ClientSession): - url = f'http://xmldata.qrz.com/xml/current/?s={key}' + url = f"http://xmldata.qrz.com/xml/current/?s={key}" async with session.get(url) as resp: if resp.status != 200: - raise ConnectionError(f'Unable to connect to QRZ (HTTP Error {resp.status})') + raise ConnectionError(f"Unable to connect to QRZ (HTTP Error {resp.status})") with BytesIO(await resp.read()) as resp_file: resp_xml = etree.parse(resp_file).getroot() - resp_xml_session = resp_xml.xpath('/x:QRZDatabase/x:Session', namespaces={'x': 'http://xmldata.qrz.com'}) - resp_session = {el.tag.split('}')[1]: el.text for el in resp_xml_session[0].getiterator()} - if 'Error' in resp_session: - raise ConnectionError(resp_session['Error']) + resp_xml_session = resp_xml.xpath("/x:QRZDatabase/x:Session", namespaces={"x": "http://xmldata.qrz.com"}) + resp_session = {el.tag.split("}")[1]: el.text for el in resp_xml_session[0].getiterator()} + if "Error" in resp_session: + raise ConnectionError(resp_session["Error"]) def qrz_process_info(data: dict): - if 'name' in data: - if 'fname' in data: - name = data['fname'] + ' ' + data['name'] + if "name" in data: + if "fname" in data: + name = data["fname"] + " " + data["name"] else: - name = data['name'] + name = data["name"] else: name = None - if 'state' in data: - state = f', {data["state"]}' + if "state" in data: + state = f", {data['state']}" else: - state = '' - address = data.get('addr1', '') + '\n' + data.get('addr2', '') + state + ' ' + data.get('zip', '') + state = "" + address = data.get("addr1", "") + "\n" + data.get("addr2", "") + state + " " + data.get("zip", "") address = address.strip() - if address == '': + if address == "": address = None - if 'eqsl' in data: - eqsl = 'Yes' if data['eqsl'] == 1 else 'No' + if "eqsl" in data: + eqsl = "Yes" if data["eqsl"] == 1 else "No" else: - eqsl = 'Unknown' - if 'mqsl' in data: - mqsl = 'Yes' if data['mqsl'] == 1 else 'No' + eqsl = "Unknown" + if "mqsl" in data: + mqsl = "Yes" if data["mqsl"] == 1 else "No" else: - mqsl = 'Unknown' - if 'lotw' in data: - lotw = 'Yes' if data['lotw'] == 1 else 'No' + mqsl = "Unknown" + if "lotw" in data: + lotw = "Yes" if data["lotw"] == 1 else "No" else: - lotw = 'Unknown' + lotw = "Unknown" - return OrderedDict([('Name', name), - ('Country', data.get('country', None)), - ('Address', address), - ('Grid Square', data.get('grid', None)), - ('County', data.get('county', None)), - ('CQ Zone', data.get('cqzone', None)), - ('ITU Zone', data.get('ituzone', None)), - ('IOTA Designator', data.get('iota', None)), - ('Expires', data.get('expdate', None)), - ('Aliases', data.get('aliases', None)), - ('Previous Callsign', data.get('p_call', None)), - ('License Class', data.get('class', None)), - ('Trustee', data.get('trustee', None)), - ('eQSL?', eqsl), - ('Paper QSL?', mqsl), - ('LotW?', lotw), - ('QSL Info', data.get('qslmgr', None)), - ('CQ Zone', data.get('cqzone', None)), - ('ITU Zone', data.get('ituzone', None)), - ('IOTA Designator', data.get('iota', None)), - ('Born', data.get('born', None))]) + return OrderedDict([("Name", name), + ("Country", data.get("country", None)), + ("Address", address), + ("Grid Square", data.get("grid", None)), + ("County", data.get("county", None)), + ("CQ Zone", data.get("cqzone", None)), + ("ITU Zone", data.get("ituzone", None)), + ("IOTA Designator", data.get("iota", None)), + ("Expires", data.get("expdate", None)), + ("Aliases", data.get("aliases", None)), + ("Previous Callsign", data.get("p_call", None)), + ("License Class", data.get("class", None)), + ("Trustee", data.get("trustee", None)), + ("eQSL?", eqsl), + ("Paper QSL?", mqsl), + ("LotW?", lotw), + ("QSL Info", data.get("qslmgr", None)), + ("CQ Zone", data.get("cqzone", None)), + ("ITU Zone", data.get("ituzone", None)), + ("IOTA Designator", data.get("iota", None)), + ("Born", data.get("born", None))]) def setup(bot): diff --git a/exts/study.py b/exts/study.py index 5180704..eca0964 100644 --- a/exts/study.py +++ b/exts/study.py @@ -21,17 +21,17 @@ from resources import study class StudyCog(commands.Cog): - choices = {cmn.emojis.a: 'A', cmn.emojis.b: 'B', cmn.emojis.c: 'C', cmn.emojis.d: 'D'} + choices = {cmn.emojis.a: "A", cmn.emojis.b: "B", cmn.emojis.c: "C", cmn.emojis.d: "D"} def __init__(self, bot: commands.Bot): self.bot = bot self.lastq = dict() - self.source = 'Data courtesy of [HamStudy.org](https://hamstudy.org/)' + self.source = "Data courtesy of [HamStudy.org](https://hamstudy.org/)" self.session = aiohttp.ClientSession(connector=bot.qrm.connector) - @commands.command(name="hamstudy", aliases=['rq', 'randomquestion', 'randomq'], category=cmn.cat.study) - async def _random_question(self, ctx: commands.Context, country: str = '', level: str = ''): - '''Gets a random question from [HamStudy's](https://hamstudy.org) question pools.''' + @commands.command(name="hamstudy", aliases=["rq", "randomquestion", "randomq"], category=cmn.cat.study) + async def _random_question(self, ctx: commands.Context, country: str = "", level: str = ""): + """Gets a random question from [HamStudy's](https://hamstudy.org) question pools.""" with ctx.typing(): embed = cmn.embed_factory(ctx) @@ -52,7 +52,7 @@ class StudyCog(commands.Cog): embed.description = "Possible arguments are:" embed.colour = cmn.colours.bad for cty in study.pool_names: - levels = '`, `'.join(study.pool_names[cty].keys()) + levels = "`, `".join(study.pool_names[cty].keys()) embed.add_field(name=f"**Country: `{cty}` {study.pool_emojis[cty]}**", value=f"Levels: `{levels}`", inline=False) embed.add_field(name="**Random**", value="To select a random pool or country, use `random` or `r`") @@ -70,7 +70,7 @@ class StudyCog(commands.Cog): embed.description = "Possible arguments are:" embed.colour = cmn.colours.bad for cty in study.pool_names: - levels = '`, `'.join(study.pool_names[cty].keys()) + levels = "`, `".join(study.pool_names[cty].keys()) embed.add_field(name=f"**Country: `{cty}` {study.pool_emojis[cty]}**", value=f"Levels: `{levels}`", inline=False) embed.add_field(name="**Random**", value="To select a random pool or country, use `random` or `r`") @@ -99,7 +99,7 @@ class StudyCog(commands.Cog): embed.description = "Possible arguments are:" embed.colour = cmn.colours.bad for cty in study.pool_names: - levels = '`, `'.join(study.pool_names[cty].keys()) + levels = "`, `".join(study.pool_names[cty].keys()) embed.add_field(name=f"**Country: `{cty}` {study.pool_emojis[cty]}**", value=f"Levels: `{levels}`", inline=False) embed.add_field(name="**Random**", value="To select a random pool or country, use `random` or `r`") @@ -108,31 +108,31 @@ class StudyCog(commands.Cog): pool_meta = pools[pool] - async with self.session.get(f'https://hamstudy.org/pools/{pool}') as resp: + async with self.session.get(f"https://hamstudy.org/pools/{pool}") as resp: if resp.status != 200: raise cmn.BotHTTPError(resp) - pool = json.loads(await resp.read())['pool'] + pool = json.loads(await resp.read())["pool"] # Select a question - pool_section = random.choice(pool)['sections'] - pool_questions = random.choice(pool_section)['questions'] + pool_section = random.choice(pool)["sections"] + pool_questions = random.choice(pool_section)["questions"] question = random.choice(pool_questions) embed.title = f"{study.pool_emojis[country]} {pool_meta['class']} {question['id']}" embed.description = self.source - embed.add_field(name='Question:', value=question['text'], inline=False) - embed.add_field(name='Answers:', + embed.add_field(name="Question:", value=question["text"], inline=False) + embed.add_field(name="Answers:", value=(f"**{cmn.emojis.a}** {question['answers']['A']}" f"\n**{cmn.emojis.b}** {question['answers']['B']}" f"\n**{cmn.emojis.c}** {question['answers']['C']}" f"\n**{cmn.emojis.d}** {question['answers']['D']}"), inline=False) - embed.add_field(name='To Answer:', - value=('Answer with reactions below. If not answered within 10 minutes,' - ' the answer will be revealed.'), + embed.add_field(name="To Answer:", + value=("Answer with reactions below. If not answered within 10 minutes," + " the answer will be revealed."), inline=False) - if 'image' in question: - image_url = f'https://hamstudy.org/_1330011/images/{pool.split("_",1)[1]}/{question["image"]}' + if "image" in question: + image_url = f"https://hamstudy.org/_1330011/images/{pool.split('_',1)[1]}/{question['image']}" embed.set_image(url=image_url) q_msg = await ctx.send(embed=embed) @@ -148,13 +148,13 @@ class StudyCog(commands.Cog): and str(reaction.emoji) in self.choices.keys()) try: - reaction, user = await self.bot.wait_for('reaction_add', timeout=600.0, check=check) + reaction, user = await self.bot.wait_for("reaction_add", timeout=600.0, check=check) except asyncio.TimeoutError: embed.remove_field(2) embed.add_field(name="Answer:", value=f"Timed out! The correct answer was **{question['answer']}**.") await q_msg.edit(embed=embed) else: - if self.choices[str(reaction.emoji)] == question['answer']: + if self.choices[str(reaction.emoji)] == question["answer"]: embed.remove_field(2) embed.add_field(name="Answer:", value=f"Correct! The answer was **{question['answer']}**.") embed.colour = cmn.colours.good @@ -166,7 +166,7 @@ class StudyCog(commands.Cog): await q_msg.edit(embed=embed) async def hamstudy_get_pools(self): - async with self.session.get('https://hamstudy.org/pools/') as resp: + async with self.session.get("https://hamstudy.org/pools/") as resp: if resp.status != 200: raise cmn.BotHTTPError(resp) else: diff --git a/exts/weather.py b/exts/weather.py index 92dd09d..0668a83 100644 --- a/exts/weather.py +++ b/exts/weather.py @@ -25,23 +25,23 @@ class WeatherCog(commands.Cog): self.bot = bot self.session = aiohttp.ClientSession(connector=bot.qrm.connector) - @commands.command(name="bandconditions", aliases=['cond', 'condx', 'conditions'], category=cmn.cat.weather) + @commands.command(name="bandconditions", aliases=["cond", "condx", "conditions"], category=cmn.cat.weather) async def _band_conditions(self, ctx: commands.Context): - '''Posts an image of HF Band Conditions.''' + """Posts an image of HF Band Conditions.""" async with ctx.typing(): embed = cmn.embed_factory(ctx) - embed.title = 'Current Solar Conditions' + embed.title = "Current Solar Conditions" embed.colour = cmn.colours.good - async with self.session.get('http://www.hamqsl.com/solarsun.php') as resp: + async with self.session.get("http://www.hamqsl.com/solarsun.php") as resp: if resp.status != 200: raise cmn.BotHTTPError(resp) data = io.BytesIO(await resp.read()) - embed.set_image(url=f'attachment://condx.png') - await ctx.send(embed=embed, file=discord.File(data, 'condx.png')) + embed.set_image(url=f"attachment://condx.png") + await ctx.send(embed=embed, file=discord.File(data, "condx.png")) - @commands.group(name="weather", aliases=['wttr'], category=cmn.cat.weather) + @commands.group(name="weather", aliases=["wttr"], category=cmn.cat.weather) async def _weather_conditions(self, ctx: commands.Context): - '''Posts an image of Local Weather Conditions from [wttr.in](http://wttr.in/). + """Posts an image of Local Weather Conditions from [wttr.in](http://wttr.in/). *Supported location types:* city name: `paris` @@ -51,71 +51,71 @@ class WeatherCog(commands.Cog): domain name `@stackoverflow.com` area codes: `12345` GPS coordinates: `-78.46,106.79` - ''' + """ if ctx.invoked_subcommand is None: await ctx.send_help(ctx.command) - @_weather_conditions.command(name='forecast', aliases=['fc', 'future'], category=cmn.cat.weather) + @_weather_conditions.command(name="forecast", aliases=["fc", "future"], category=cmn.cat.weather) async def _weather_conditions_forecast(self, ctx: commands.Context, *, location: str): - '''Posts an image of Local Weather Conditions for the next three days from [wttr.in](http://wttr.in/). -See help for weather command for possible location types. Add a `-c` or `-f` to use Celcius or Fahrenheit.''' + """Posts an image of Local Weather Conditions for the next three days from [wttr.in](http://wttr.in/). +See help for weather command for possible location types. Add a `-c` or `-f` to use Celcius or Fahrenheit.""" async with ctx.typing(): try: units_arg = re.search(self.wttr_units_regex, location).group(1) except AttributeError: - units_arg = '' - if units_arg.lower() == 'f': - units = 'u' - elif units_arg.lower() == 'c': - units = 'm' + units_arg = "" + if units_arg.lower() == "f": + units = "u" + elif units_arg.lower() == "c": + units = "m" else: - units = '' + units = "" - loc = self.wttr_units_regex.sub('', location).strip() + loc = self.wttr_units_regex.sub("", location).strip() embed = cmn.embed_factory(ctx) - embed.title = f'Weather Forecast for {loc}' - embed.description = 'Data from [wttr.in](http://wttr.in/).' + embed.title = f"Weather Forecast for {loc}" + embed.description = "Data from [wttr.in](http://wttr.in/)." embed.colour = cmn.colours.good - loc = loc.replace(' ', '+') - async with self.session.get(f'http://wttr.in/{loc}_{units}pnFQ.png') as resp: + loc = loc.replace(" ", "+") + async with self.session.get(f"http://wttr.in/{loc}_{units}pnFQ.png") as resp: if resp.status != 200: raise cmn.BotHTTPError(resp) data = io.BytesIO(await resp.read()) - embed.set_image(url=f'attachment://wttr_forecast.png') - await ctx.send(embed=embed, file=discord.File(data, 'wttr_forecast.png')) + embed.set_image(url=f"attachment://wttr_forecast.png") + await ctx.send(embed=embed, file=discord.File(data, "wttr_forecast.png")) - @_weather_conditions.command(name='now', aliases=['n'], category=cmn.cat.weather) + @_weather_conditions.command(name="now", aliases=["n"], category=cmn.cat.weather) async def _weather_conditions_now(self, ctx: commands.Context, *, location: str): - '''Posts an image of current Local Weather Conditions from [wttr.in](http://wttr.in/). -See help for weather command for possible location types. Add a `-c` or `-f` to use Celcius or Fahrenheit.''' + """Posts an image of current Local Weather Conditions from [wttr.in](http://wttr.in/). +See help for weather command for possible location types. Add a `-c` or `-f` to use Celcius or Fahrenheit.""" async with ctx.typing(): try: units_arg = re.search(self.wttr_units_regex, location).group(1) except AttributeError: - units_arg = '' - if units_arg.lower() == 'f': - units = 'u' - elif units_arg.lower() == 'c': - units = 'm' + units_arg = "" + if units_arg.lower() == "f": + units = "u" + elif units_arg.lower() == "c": + units = "m" else: - units = '' + units = "" - loc = self.wttr_units_regex.sub('', location).strip() + loc = self.wttr_units_regex.sub("", location).strip() embed = cmn.embed_factory(ctx) - embed.title = f'Current Weather for {loc}' - embed.description = 'Data from [wttr.in](http://wttr.in/).' + embed.title = f"Current Weather for {loc}" + embed.description = "Data from [wttr.in](http://wttr.in/)." embed.colour = cmn.colours.good - loc = loc.replace(' ', '+') - async with self.session.get(f'http://wttr.in/{loc}_0{units}pnFQ.png') as resp: + loc = loc.replace(" ", "+") + async with self.session.get(f"http://wttr.in/{loc}_0{units}pnFQ.png") as resp: if resp.status != 200: raise cmn.BotHTTPError(resp) data = io.BytesIO(await resp.read()) - embed.set_image(url=f'attachment://wttr_now.png') - await ctx.send(embed=embed, file=discord.File(data, 'wttr_now.png')) + embed.set_image(url=f"attachment://wttr_now.png") + await ctx.send(embed=embed, file=discord.File(data, "wttr_now.png")) def setup(bot: commands.Bot): diff --git a/info.py b/info.py index 5a442b2..eb1cb34 100644 --- a/info.py +++ b/info.py @@ -24,5 +24,5 @@ authors = ("@ClassAbbyAmplifier#2229", "@0x5c#0639") description = """A bot with various useful ham radio-related functions, written in Python.""" license = "Released under the GNU General Public License v2" contributing = "Check out the source on GitHub, contributions welcome: https://github.com/classabbyamp/discord-qrm2" -release = '2.1.0' -bot_server = 'https://discord.gg/Ntbg3J4' +release = "2.1.0" +bot_server = "https://discord.gg/Ntbg3J4" diff --git a/main.py b/main.py index 0eaf467..3013bdc 100644 --- a/main.py +++ b/main.py @@ -167,7 +167,7 @@ async def on_command_error(ctx: commands.Context, err: commands.CommandError): await cmn.add_react(ctx.message, cmn.emojis.bangbang) elif isinstance(err, (commands.CommandInvokeError, commands.ConversionError)): # Emulating discord.py's default beaviour. - print('Ignoring exception in command {}:'.format(ctx.command), file=sys.stderr) + print("Ignoring exception in command {}:".format(ctx.command), file=sys.stderr) traceback.print_exception(type(err), err, err.__traceback__, file=sys.stderr) embed = cmn.error_embed_factory(ctx, err.original, bot.qrm.debug_mode) @@ -176,7 +176,7 @@ async def on_command_error(ctx: commands.Context, err: commands.CommandError): await ctx.send(embed=embed) else: # Emulating discord.py's default beaviour. (safest bet) - print('Ignoring exception in command {}:'.format(ctx.command), file=sys.stderr) + print("Ignoring exception in command {}:".format(ctx.command), file=sys.stderr) traceback.print_exception(type(err), err, err.__traceback__, file=sys.stderr) await cmn.add_react(ctx.message, cmn.emojis.warning) @@ -221,7 +221,7 @@ async def _ensure_activity_fixed(): # --- Run --- for ext in opt.exts: - bot.load_extension(ext_dir + '.' + ext) + bot.load_extension(ext_dir + "." + ext) try: diff --git a/resources/callsign_info.py b/resources/callsign_info.py index ac671f4..45055de 100644 --- a/resources/callsign_info.py +++ b/resources/callsign_info.py @@ -11,45 +11,45 @@ from collections import OrderedDict us_calls_title = "Valid US Vanity Callsigns" -us_calls_desc = ('#x# is the number of letters in the prefix and suffix of a callsign. ' - 'E.g., WY4RC would be a 2x2 callsign, with prefix WY and suffix RC.') -us_calls = OrderedDict([('**Group A** (Extra Only)', ('**Any:** K, N, W (1x2)\n' - ' AA-AL, KA-KZ, NA-NZ, WA-WZ (2x1)\n' - ' AA-AL (2x2)\n' - '*Except*\n' - '**Alaska:** AL, KL, NL, WL (2x1)\n' - '**Caribbean:** KP, NP, WP (2x1)\n' - '**Pacific:** AH, KH, NH, WH (2x1)')), - ('**Group B** (Advanced and Extra Only)', ('**Any:** KA-KZ, NA-NZ, WA-WZ (2x2)\n' - '*Except*\n' - '**Alaska:** AL (2x2)\n' - '**Caribbean:** KP (2x2)\n' - '**Pacific:** AH (2x2)')), - ('**Group C** (Technician, General, Advanced, Extra Only)', ('**Any Region:** K, N, W (1x3)\n' - '*Except*\n' - '**Alaska:** KL, NL, WL (2x2)\n' - '**Caribbean:** NP, WP (2x2)\n' - '**Pacific:** KH, NH, WH (2x2)')), - ('**Group D** (Any License Class)', ('**Any Region:** KA-KZ, WA-WZ (2x3)\n' - '*Except*\n' - '**Alaska:** KL, WL (2x3)\n' - '**Caribbean:** KP, WP (2x3)\n' - '**Pacific:** KH, WH (2x3)')), - ('**Unavailable**', ('- KA2AA-KA9ZZ: US Army in Japan\n' - '- KC4AAA-KC4AAF: NSF in Antartica\n' - '- KC4USA-KC4USZ: US Navy in Antartica\n' - '- KG4AA-KG4ZZ: US Navy in Guantanamo Bay\n' - '- KL9KAA-KL9KHZ: US military in Korea\n' - '- KC6AA-KC6ZZ: Former US (Eastern and Western Caroline Islands), ' - 'now Federated States of Micronesia (V6) and Republic of Palau (T8)\n' - '- KX6AA-KX6ZZ: Former US (Marshall Islands), ' - 'now Republic of the Marshall Islands (V73)\n' - '- Any suffix SOS or QRA-QUZ\n' - '- Any 2x3 with X as the first suffix letter\n' - '- Any 2x3 with AF, KF, NF, or WF prefix and suffix EMA: FEMA\n' - '- Any 2x3 with AA-AL, NA-NZ, WC, WK, WM, WR, or WT prefix: "Group X"\n' - '- Any 2x1, 2x2, or 2x3 with KP, NP, WP prefix and 0, 6, 7, 8, 9 number\n' - '- Any 1x1 callsign: Special Event'))]) +us_calls_desc = ("#x# is the number of letters in the prefix and suffix of a callsign. " + "E.g., WY4RC would be a 2x2 callsign, with prefix WY and suffix RC.") +us_calls = OrderedDict([("**Group A** (Extra Only)", ("**Any:** K, N, W (1x2)\n" + " AA-AL, KA-KZ, NA-NZ, WA-WZ (2x1)\n" + " AA-AL (2x2)\n" + "*Except*\n" + "**Alaska:** AL, KL, NL, WL (2x1)\n" + "**Caribbean:** KP, NP, WP (2x1)\n" + "**Pacific:** AH, KH, NH, WH (2x1)")), + ("**Group B** (Advanced and Extra Only)", ("**Any:** KA-KZ, NA-NZ, WA-WZ (2x2)\n" + "*Except*\n" + "**Alaska:** AL (2x2)\n" + "**Caribbean:** KP (2x2)\n" + "**Pacific:** AH (2x2)")), + ("**Group C** (Technician, General, Advanced, Extra Only)", ("**Any Region:** K, N, W (1x3)\n" + "*Except*\n" + "**Alaska:** KL, NL, WL (2x2)\n" + "**Caribbean:** NP, WP (2x2)\n" + "**Pacific:** KH, NH, WH (2x2)")), + ("**Group D** (Any License Class)", ("**Any Region:** KA-KZ, WA-WZ (2x3)\n" + "*Except*\n" + "**Alaska:** KL, WL (2x3)\n" + "**Caribbean:** KP, WP (2x3)\n" + "**Pacific:** KH, WH (2x3)")), + ("**Unavailable**", ("- KA2AA-KA9ZZ: US Army in Japan\n" + "- KC4AAA-KC4AAF: NSF in Antartica\n" + "- KC4USA-KC4USZ: US Navy in Antartica\n" + "- KG4AA-KG4ZZ: US Navy in Guantanamo Bay\n" + "- KL9KAA-KL9KHZ: US military in Korea\n" + "- KC6AA-KC6ZZ: Former US (Eastern and Western Caroline Islands), " + "now Federated States of Micronesia (V6) and Republic of Palau (T8)\n" + "- KX6AA-KX6ZZ: Former US (Marshall Islands), " + "now Republic of the Marshall Islands (V73)\n" + "- Any suffix SOS or QRA-QUZ\n" + "- Any 2x3 with X as the first suffix letter\n" + "- Any 2x3 with AF, KF, NF, or WF prefix and suffix EMA: FEMA\n" + "- Any 2x3 with AA-AL, NA-NZ, WC, WK, WM, WR, or WT prefix: \"Group X\"\n" + "- Any 2x1, 2x2, or 2x3 with KP, NP, WP prefix and 0, 6, 7, 8, 9 number\n" + "- Any 1x1 callsign: Special Event"))]) # format: country: (title, description, text) -options = {'us': (us_calls_title, us_calls_desc, us_calls)} +options = {"us": (us_calls_title, us_calls_desc, us_calls)} diff --git a/resources/phonetics.py b/resources/phonetics.py index 45bf2c7..9637aae 100644 --- a/resources/phonetics.py +++ b/resources/phonetics.py @@ -7,8 +7,8 @@ This file is part of discord-qrmbot and is released under the terms of the GNU General Public License, version 2. """ -phonetics = {'a': 'alfa', 'b': 'bravo', 'c': 'charlie', 'd': 'delta', 'e': 'echo', 'f': 'foxtrot', - 'g': 'golf', 'h': 'hotel', 'i': 'india', 'j': 'juliett', 'k': 'kilo', 'l': 'lima', - 'm': 'mike', 'n': 'november', 'o': 'oscar', 'p': 'papa', 'q': 'quebec', 'r': 'romeo', - 's': 'sierra', 't': 'tango', 'u': 'uniform', 'v': 'victor', 'w': 'whiskey', 'x': 'x-ray', - 'y': 'yankee', 'z': 'zulu'} +phonetics = {"a": "alfa", "b": "bravo", "c": "charlie", "d": "delta", "e": "echo", "f": "foxtrot", + "g": "golf", "h": "hotel", "i": "india", "j": "juliett", "k": "kilo", "l": "lima", + "m": "mike", "n": "november", "o": "oscar", "p": "papa", "q": "quebec", "r": "romeo", + "s": "sierra", "t": "tango", "u": "uniform", "v": "victor", "w": "whiskey", "x": "x-ray", + "y": "yankee", "z": "zulu"} diff --git a/resources/study.py b/resources/study.py index b68f99f..467ef9b 100644 --- a/resources/study.py +++ b/resources/study.py @@ -7,43 +7,43 @@ This file is part of discord-qrmbot and is released under the terms of the GNU General Public License, version 2. """ -pool_names = {'us': {'technician': 'E2', - 'tech': 'E2', - 't': 'E2', - 'general': 'E3', - 'gen': 'E3', - 'g': 'E3', - 'extra': 'E4', - 'e': 'E4'}, - 'ca': {'basic': 'CA_B', - 'b': 'CA_B', - 'advanced': 'CA_A', - 'adv': 'CA_A', - 'a': 'CA_A', - 'basic_fr': 'CA_FB', - 'b_fr': 'CA_FB', - 'base': 'CA_FB', - 'advanced_fr': 'CA_FS', - 'adv_fr': 'CA_FS', - 'a_fr': 'CA_FS', - 'supérieure': 'CA_FS', - 'superieure': 'CA_FS', - 's': 'CA_FS'}, - 'us_c': {'c1': 'C1', - 'comm1': 'C1', - 'c3': 'C3', - 'comm3': 'C3', - 'c6': 'C6', - 'comm6': 'C6', - 'c7': 'C7', - 'comm7': 'C7', - 'c7r': 'C7R', - 'comm7r': 'C7R', - 'c8': 'C8', - 'comm8': 'C8', - 'c9': 'C9', - 'comm9': 'C9'}} +pool_names = {"us": {"technician": "E2", + "tech": "E2", + "t": "E2", + "general": "E3", + "gen": "E3", + "g": "E3", + "extra": "E4", + "e": "E4"}, + "ca": {"basic": "CA_B", + "b": "CA_B", + "advanced": "CA_A", + "adv": "CA_A", + "a": "CA_A", + "basic_fr": "CA_FB", + "b_fr": "CA_FB", + "base": "CA_FB", + "advanced_fr": "CA_FS", + "adv_fr": "CA_FS", + "a_fr": "CA_FS", + "supérieure": "CA_FS", + "superieure": "CA_FS", + "s": "CA_FS"}, + "us_c": {"c1": "C1", + "comm1": "C1", + "c3": "C3", + "comm3": "C3", + "c6": "C6", + "comm6": "C6", + "c7": "C7", + "comm7": "C7", + "c7r": "C7R", + "comm7r": "C7R", + "c8": "C8", + "comm8": "C8", + "c9": "C9", + "comm9": "C9"}} -pool_emojis = {'us': '🇺🇸', - 'ca': '🇨🇦', - 'us_c': '🇺🇸 🏢'} +pool_emojis = {"us": "🇺🇸", + "ca": "🇨🇦", + "us_c": "🇺🇸 🏢"} diff --git a/templates/data/options.py b/templates/data/options.py index 87190ad..ca127a9 100644 --- a/templates/data/options.py +++ b/templates/data/options.py @@ -27,7 +27,7 @@ debug = False owners_uids = (200102491231092736,) # The extensions to load when running the bot. -exts = ['ae7q', 'base', 'fun', 'grid', 'ham', 'image', 'lookup', 'morse', 'qrz', 'study', 'weather'] +exts = ["ae7q", "base", "fun", "grid", "ham", "image", "lookup", "morse", "qrz", "study", "weather"] # Either "time", "random", or "fixed" (first item in statuses) status_mode = "fixed" @@ -37,17 +37,17 @@ statuses = ["with lids on the air", "with fire"] # Timezone for the status (string) # See https://pythonhosted.org/pytz/ for more info -status_tz = 'US/Eastern' +status_tz = "US/Eastern" # The text to put in the "playing" status, with start and stop times -time_statuses = [('with lids on 3.840', (00, 00), (6, 00)), - ('with lids on 7.200', (6, 00), (10, 00)), - ('with lids on 14.313', (10, 00), (18, 00)), - ('with lids on 7.200', (18, 00), (20, 00)), - ('with lids on 3.840', (20, 00), (23, 59))] +time_statuses = [("with lids on 3.840", (00, 00), (6, 00)), + ("with lids on 7.200", (6, 00), (10, 00)), + ("with lids on 14.313", (10, 00), (18, 00)), + ("with lids on 7.200", (18, 00), (20, 00)), + ("with lids on 3.840", (20, 00), (23, 59))] # Emoji IDs and keywords for emoji reactions -# Use the format {emoji_id (int): ('tuple', 'of', 'lowercase', 'keywords')} +# Use the format {emoji_id (int): ("tuple", "of", "lowercase", "keywords")} msg_reacts = {} # A :pika: emote's ID, None for no emote :c