Move actual arkhamdb communication to its own class

This commit is contained in:
Adam Goldsmith 2021-05-02 23:22:52 -04:00
parent dfe4be1f6d
commit 4ba198c00e
2 changed files with 47 additions and 34 deletions

View File

@ -3,25 +3,21 @@
from datetime import datetime from datetime import datetime
import json import json
import re import re
from typing import Any
import discord import discord
import aiohttp
from discord.ext import tasks from discord.ext import tasks
from arkhamdb import ArkhamDBClient
from secret import TOKEN from secret import TOKEN
ArkhamDBDeck = Any # TODO: better typing
ARKHAMDB_URL = 'https://arkhamdb.adamgoldsmith.name'
# TODO: should really be a database # TODO: should really be a database
with open('channel_list.json') as f: with open('channel_list.json') as f:
channel_list = json.load(f) channel_list = json.load(f)
class ArkhamDBClient(discord.Client): class ArkhamDBUpdater(discord.Client):
session: aiohttp.ClientSession arkhamdb_client: ArkhamDBClient
async def on_ready(self): async def on_ready(self):
print(f'Logged in as {self.user} (ID: {self.user.id})') print(f'Logged in as {self.user} (ID: {self.user.id})')
@ -30,7 +26,7 @@ class ArkhamDBClient(discord.Client):
print(' ', guild.name) print(' ', guild.name)
print('------') print('------')
self.session = aiohttp.ClientSession() self.arkhamdb_client = ArkhamDBClient()
self.arkhamdb_monitor.start() self.arkhamdb_monitor.start()
async def gather_deck_ids(self, channel: discord.TextChannel) -> dict[int, str]: async def gather_deck_ids(self, channel: discord.TextChannel) -> dict[int, str]:
@ -40,34 +36,12 @@ class ArkhamDBClient(discord.Client):
if message.author.id == self.user.id: if message.author.id == self.user.id:
continue continue
matches = re.finditer(r'(?P<prefix>.*)' + ARKHAMDB_URL + r'/deck/view/(?P<deck_id>\d+)', message.content) matches = re.finditer(r'(?P<prefix>.*)' + self.arkhamdb_client.origin + r'/deck/view/(?P<deck_id>\d+)', message.content)
for match in matches: for match in matches:
deck_ids[int(match.group('deck_id'))] = match.group('prefix') deck_ids[int(match.group('deck_id'))] = match.group('prefix')
return deck_ids return deck_ids
async def get_latest_deck(self, deck_id: int) -> ArkhamDBDeck:
next_deck_id = deck_id
deck = None
while deck is None or deck["next_deck"] is not None:
async with self.session.get(ARKHAMDB_URL + f"/api/public/deck/{next_deck_id}.json") as resp:
deck = await resp.json()
next_deck_id = deck["next_deck"]
return deck
async def get_latest_decks(self, deck_ids: dict[int, str]) -> dict[int, tuple[str, ArkhamDBDeck]]:
latest_decks: dict[int, tuple[str, ArkhamDBDeck]] = {}
for deck_id, prefix in deck_ids.items():
try:
deck = await self.get_latest_deck(deck_id)
latest_decks[deck['id']] = (prefix, deck)
except aiohttp.ContentTypeError:
# TODO: json was invalid, should probably alert user
pass
return latest_decks
async def clear_old_messages(self, channel: discord.TextChannel) -> None: async def clear_old_messages(self, channel: discord.TextChannel) -> None:
async for message in channel.history(limit=200): async for message in channel.history(limit=200):
if message.author.id == self.user.id and message.id != channel.last_message_id: if message.author.id == self.user.id and message.id != channel.last_message_id:
@ -75,7 +49,7 @@ class ArkhamDBClient(discord.Client):
async def update_channel_latest_decks(self, channel: discord.TextChannel) -> None: async def update_channel_latest_decks(self, channel: discord.TextChannel) -> None:
deck_ids = await self.gather_deck_ids(channel) deck_ids = await self.gather_deck_ids(channel)
latest_decks = await self.get_latest_decks(deck_ids) latest_decks = await self.arkhamdb_client.get_latest_decks(deck_ids)
await self.clear_old_messages(channel) await self.clear_old_messages(channel)
@ -85,7 +59,7 @@ class ArkhamDBClient(discord.Client):
last_message = None last_message = None
message_text = '\n'.join( message_text = '\n'.join(
f"{prefix}[{deck['name']}]({ARKHAMDB_URL}/deck/view/{deck['id']}) [{deck['id']}]" f"{prefix}[{deck['name']}]({self.arkhamdb_client.origin}/deck/view/{deck['id']}) [{deck['id']}]"
for prefix, deck in latest_decks.values()) for prefix, deck in latest_decks.values())
message_embed = discord.Embed( message_embed = discord.Embed(
title=f'Updated as of {datetime.now()}', title=f'Updated as of {datetime.now()}',
@ -126,5 +100,5 @@ class ArkhamDBClient(discord.Client):
await self.update_channel_latest_decks(channel) await self.update_channel_latest_decks(channel)
client = ArkhamDBClient() client = ArkhamDBUpdater()
client.run(TOKEN) client.run(TOKEN)

39
arkhamdb.py Normal file
View File

@ -0,0 +1,39 @@
from typing import Any
import aiohttp
ARKHAMDB_ORIGIN = 'https://arkhamdb.adamgoldsmith.name'
ArkhamDBDeck = Any # TODO: better typing
class ArkhamDBClient:
session: aiohttp.ClientSession
origin: str
def __init__(self, arkhamdb_origin: str = ARKHAMDB_ORIGIN):
self.session = aiohttp.ClientSession()
self.origin = arkhamdb_origin
async def get_latest_deck(self, deck_id: int) -> ArkhamDBDeck:
next_deck_id = deck_id
deck = None
while deck is None or deck["next_deck"] is not None:
async with self.session.get(self.origin + f"/api/public/deck/{next_deck_id}.json") as resp:
deck = await resp.json()
next_deck_id = deck["next_deck"]
return deck
async def get_latest_decks(self, deck_ids: dict[int, str]) -> dict[int, tuple[str, ArkhamDBDeck]]:
latest_decks: dict[int, tuple[str, ArkhamDBDeck]] = {}
for deck_id, prefix in deck_ids.items():
try:
deck = await self.get_latest_deck(deck_id)
latest_decks[deck['id']] = (prefix, deck)
except aiohttp.ContentTypeError:
# TODO: json was invalid, should probably alert user
pass
return latest_decks