From 19284ee1cce0ce5ef746aa70b0068509d73348b7 Mon Sep 17 00:00:00 2001 From: Abigail Gold Date: Mon, 7 Oct 2019 16:11:30 -0400 Subject: [PATCH 1/2] add ae7q call search, basic functionality. need to error check etc still --- cogs/ae7qcog.py | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ main.py | 1 + requirements.txt | 1 + 3 files changed, 99 insertions(+) create mode 100644 cogs/ae7qcog.py diff --git a/cogs/ae7qcog.py b/cogs/ae7qcog.py new file mode 100644 index 0000000..7c55b97 --- /dev/null +++ b/cogs/ae7qcog.py @@ -0,0 +1,97 @@ +""" +ae7q cog for qrm +--- +Copyright (C) 2019 Abigail Gold, 0x5c + +This file is part of discord-qrmbot and is released under the terms of the GNU +General Public License, version 2. +""" + +import discord +import discord.ext.commands as commands + +from datetime import datetime +from bs4 import BeautifulSoup +import aiohttp + + +class AE7QCog(commands.Cog): + def __init__(self, bot): + self.bot = bot + self.gs = bot.get_cog("GlobalSettings") + + @commands.group(name="ae7q", aliases=["ae"]) + async def _ae7q_lookup(self, ctx): + '''Look up a callsign, FRN, or Licensee ID on ae7q.com''' + if ctx.invoked_subcommand is None: + await ctx.send('Invalid ae7q command passed\nPossible commands:' + + '`call`, `frn`, `lic` or `licensee`.') + + @_ae7q_lookup.command(name="call") + async def _ae7q_call(self, ctx, callsign: str): + callsign = callsign.upper() + base_url = "http://ae7q.com/query/data/CallHistory.php?CALL=" + + async with aiohttp.ClientSession() as session: + async with session.get(base_url + callsign) as resp: + if resp.status != 200: + return await ctx.send('Could not load AE7Q') + page = await resp.text() + + soup = BeautifulSoup(page, features="html.parser") + table = soup.select("table.Database")[1] + + rows = table.find_all("tr") + table_contents = [] # store your table here + for tr in rows: + if rows.index(tr) == 0: + continue + else: + row_cells = [] + for td in tr.find_all('td'): + if td.getText().strip() != '': + row_cells.append(td.getText().strip()) + else: + row_cells.append('-') + if 'colspan' in td.attrs and int(td.attrs['colspan']) > 1: + for i in range(int(td.attrs['colspan']) - 1): + row_cells.append(row_cells[-1]) + for i in range(len(row_cells)): + if row_cells[i] == '"': + row_cells[i] = table_contents[-1][i] + if len(row_cells) > 1: + table_contents += [row_cells] + + embed = discord.Embed(title=f"AE7Q History for {callsign}", + colour=self.gs.colours.good, + url=f"{base_url}{callsign}", + timestamp=datetime.utcnow()) + + embed.set_author(name=ctx.author.name, + icon_url=str(ctx.author.avatar_url)) + + for row in table_contents: + embed.add_field(name=row[0], value=row[1], inline=False) + embed.add_field(name="Class", value=row[2], inline=True) + embed.add_field(name="Region", value=row[3], inline=True) + embed.add_field(name="Status", value=row[4], inline=True) + embed.add_field(name="Grant", value=row[5], inline=True) + embed.add_field(name="Effective", value=row[6], inline=True) + embed.add_field(name="Cancel", value=row[7], inline=True) + embed.add_field(name="Expire", value=row[8], inline=True) + + await ctx.send(embed=embed) + + @_ae7q_lookup.command(name="frn") + async def _ae7q_frn(self, ctx, frn: str): + base_url = "http://ae7q.com/query/data/FrnHistory.php?FRN=" + pass + + @_ae7q_lookup.command(name="licensee", aliases=["lic"]) + async def _ae7q_licensee(self, ctx, frn: str): + base_url = "http://ae7q.com/query/data/LicenseeIdHistory.php?ID=" + pass + + +def setup(bot): + bot.add_cog(AE7QCog(bot)) diff --git a/main.py b/main.py index d4ac98c..bed52ba 100644 --- a/main.py +++ b/main.py @@ -114,6 +114,7 @@ bot.load_extension("cogs.gridcog") bot.load_extension("cogs.hamcog") bot.load_extension("cogs.imagecog") bot.load_extension("cogs.studycog") +bot.load_extension("cogs.ae7qcog") _ensure_activity.start() diff --git a/requirements.txt b/requirements.txt index 844f49a..11e81ce 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ discord.py +beautifulsoup4 From d8d0b681000f83548edef06731656f909a441869 Mon Sep 17 00:00:00 2001 From: Abigail Gold Date: Tue, 8 Oct 2019 18:57:37 -0400 Subject: [PATCH 2/2] more work on ae7q callsign lookup --- cogs/ae7qcog.py | 86 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 21 deletions(-) diff --git a/cogs/ae7qcog.py b/cogs/ae7qcog.py index 7c55b97..c4d67e8 100644 --- a/cogs/ae7qcog.py +++ b/cogs/ae7qcog.py @@ -5,6 +5,12 @@ Copyright (C) 2019 Abigail Gold, 0x5c This file is part of discord-qrmbot and is released under the terms of the GNU General Public License, version 2. +--- +Test callsigns: +KN8U: active, restricted +AB2EE: expired, restricted +KE8FGB: assigned once, no restrictions +NA2AAA: unassigned, no records """ import discord @@ -30,6 +36,7 @@ class AE7QCog(commands.Cog): @_ae7q_lookup.command(name="call") async def _ae7q_call(self, ctx, callsign: str): callsign = callsign.upper() + desc = '' base_url = "http://ae7q.com/query/data/CallHistory.php?CALL=" async with aiohttp.ClientSession() as session: @@ -39,9 +46,31 @@ class AE7QCog(commands.Cog): page = await resp.text() soup = BeautifulSoup(page, features="html.parser") - table = soup.select("table.Database")[1] + tables = soup.select("table.Database") + + for table in tables: + rows = table.find_all("tr") + if len(rows) > 1 and len(rows[0]) > 1: + break + elif desc == '': + for row in rows: + desc += " ".join(row.getText().split()) + desc += '\n' + desc = desc.replace(callsign, f'`{callsign}`') + rows = None + + if rows is None: + embed = discord.Embed(title=f"AE7Q History for {callsign}", + colour=self.gs.colours.bad, + url=f"{base_url}{callsign}", + timestamp=datetime.utcnow()) + embed.set_footer(text=ctx.author.name, + icon_url=str(ctx.author.avatar_url)) + embed.description = desc + embed.description += f'\nNo records found for `{callsign}`' + await ctx.send(embed=embed) + return - rows = table.find_all("tr") table_contents = [] # store your table here for tr in rows: if rows.index(tr) == 0: @@ -62,35 +91,50 @@ class AE7QCog(commands.Cog): if len(row_cells) > 1: table_contents += [row_cells] - embed = discord.Embed(title=f"AE7Q History for {callsign}", + embed = discord.Embed(title=f"AE7Q Records for {callsign}", colour=self.gs.colours.good, url=f"{base_url}{callsign}", timestamp=datetime.utcnow()) - embed.set_author(name=ctx.author.name, + embed.set_footer(text=ctx.author.name, icon_url=str(ctx.author.avatar_url)) - for row in table_contents: - embed.add_field(name=row[0], value=row[1], inline=False) - embed.add_field(name="Class", value=row[2], inline=True) - embed.add_field(name="Region", value=row[3], inline=True) - embed.add_field(name="Status", value=row[4], inline=True) - embed.add_field(name="Grant", value=row[5], inline=True) - embed.add_field(name="Effective", value=row[6], inline=True) - embed.add_field(name="Cancel", value=row[7], inline=True) - embed.add_field(name="Expire", value=row[8], inline=True) + for row in table_contents[0:3]: + header = f'**{row[0]}** ({row[1]})' + body = f'Class: *{row[2]}*\n' + body += f'Region: *{row[3]}*\n' + body += f'Status: *{row[4]}*\n' + body += f'Granted: *{row[5]}*\n' + body += f'Effective: *{row[6]}*\n' + body += f'Cancelled: *{row[7]}*\n' + body += f'Expires: *{row[8]}*' + embed.add_field(name=header, value=body, inline=False) + + embed.description = desc + if len(table_contents) > 3: + embed.description += f'\nRecords 1 to 3 of {len(table_contents)}.' + embed.description += ' See ae7q.com for more...' await ctx.send(embed=embed) - @_ae7q_lookup.command(name="frn") - async def _ae7q_frn(self, ctx, frn: str): - base_url = "http://ae7q.com/query/data/FrnHistory.php?FRN=" - pass + # TODO: write commands for other AE7Q response types? + # @_ae7q_lookup.command(name="trustee") + # async def _ae7q_trustee(self, ctx, callsign: str): + # pass - @_ae7q_lookup.command(name="licensee", aliases=["lic"]) - async def _ae7q_licensee(self, ctx, frn: str): - base_url = "http://ae7q.com/query/data/LicenseeIdHistory.php?ID=" - pass + # @_ae7q_lookup.command(name="applications", aliases=['apps']) + # async def _ae7q_applications(self, ctx, callsign: str): + # pass + + # @_ae7q_lookup.command(name="frn") + # async def _ae7q_frn(self, ctx, frn: str): + # base_url = "http://ae7q.com/query/data/FrnHistory.php?FRN=" + # pass + + # @_ae7q_lookup.command(name="licensee", aliases=["lic"]) + # async def _ae7q_licensee(self, ctx, frn: str): + # base_url = "http://ae7q.com/query/data/LicenseeIdHistory.php?ID=" + # pass def setup(bot):