Skip to content

Commit

Permalink
Get pub list from API
Browse files Browse the repository at this point in the history
  • Loading branch information
trickeydan committed Sep 14, 2024
1 parent d0ff31a commit 126e487
Show file tree
Hide file tree
Showing 10 changed files with 64 additions and 45 deletions.
23 changes: 21 additions & 2 deletions kmibot/modules/ferry/api.py → kmibot/api.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from datetime import datetime
from logging import getLogger
from typing import Any
from typing import Any, Optional
from uuid import UUID
import discord
import httpx
from pydantic import BaseModel, TypeAdapter
from pydantic import BaseModel, TypeAdapter, HttpUrl, validator

LOGGER = getLogger(__name__)

Expand Down Expand Up @@ -62,6 +62,18 @@ class FactSchema(BaseModel):
link_token: str | None


class PubSchema(BaseModel):
id: UUID
name: str
emoji: str
menu_url: Optional[HttpUrl] = None
map_url: HttpUrl

@validator("menu_url", pre=True)
def parse_menu_url(cls, val: str) -> str | None:
return val if val else None


class FerryAPI:
def __init__(self, api_url: str, api_key: str) -> None:
self._api_url = api_url
Expand Down Expand Up @@ -147,3 +159,10 @@ async def create_ratification(
"POST", f"v2/court/accusations/{accusation_id}/ratification/", json=payload
)
return RatificationSchema.model_validate(data)

async def get_pubs(
self,
) -> list[PubSchema]:
data = await self._request("GET", "v2/pub/pubs/")
ta = TypeAdapter(list[PubSchema])
return ta.validate_python(data["results"])
4 changes: 3 additions & 1 deletion kmibot/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import discord
from discord import app_commands

from .api import FerryAPI
from .config import BotConfig
from .modules import MODULES, Module

Expand All @@ -17,8 +18,9 @@ def __init__(self, config: BotConfig) -> None:
self.config = config
self.guild = discord.Object(config.discord.guild_id)
self.tree = app_commands.CommandTree(self)
self.api_client = FerryAPI(self.config.ferry.api_url, self.config.ferry.api_key)

self._modules: list[Module] = [module_cls(self) for module_cls in MODULES]
self._modules: list[Module] = [module_cls(self, self.api_client) for module_cls in MODULES]
LOGGER.info(f"Set up {len(self._modules)} modules")

@property
Expand Down
18 changes: 1 addition & 17 deletions kmibot/config.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
from pathlib import Path
from typing import Optional
from zoneinfo import ZoneInfo

import discord
import tomllib
from pydantic import BaseModel, HttpUrl, ValidationError, validator
from pydantic import BaseModel, ValidationError, validator
from pydantic_settings import BaseSettings


Expand All @@ -17,28 +15,14 @@ class DiscordConfig(BaseModel):
guild_id: int


class PubInfo(BaseModel):
name: str
emoji: str
menu_url: Optional[HttpUrl] = None
map_url: HttpUrl


class PubConfig(BaseModel):
pubs: list[PubInfo]
supplemental_emoji: str = "🍺"
channel_id: int
description: str
weekday: int
hour: int
minute: int = 0

def get_pub_by_name(self, name: str) -> Optional[PubInfo]:
return discord.utils.find(
lambda p: p.name == name,
self.pubs,
)


class FerryConfig(BaseModel):
api_url: str
Expand Down
6 changes: 3 additions & 3 deletions kmibot/modules/ferry/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import discord

from kmibot.modules import Module
from kmibot.modules.ferry.api import FerryAPI
from kmibot.api import FerryAPI

from .commands import FerryCommand
from .modals import AccuseModal
Expand All @@ -19,10 +19,10 @@


class FerryModule(Module):
def __init__(self, client: DiscordClient) -> None:
def __init__(self, client: DiscordClient, api_client: FerryAPI) -> None:
self.client = client
self.command_group = FerryCommand(client.config, self)
self.api_client = FerryAPI(client.config.ferry.api_url, client.config.ferry.api_key)
self.api_client = api_client
client.tree.add_command(self.command_group, guild=client.guild)
client.tree.context_menu(name="Accuse of Ferrying", guild=client.guild)(
self.accuse_context_menu
Expand Down
2 changes: 1 addition & 1 deletion kmibot/modules/ferry/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import discord
import httpx

from kmibot.modules.ferry.api import AccusationSchema
from kmibot.api import AccusationSchema

if typing.TYPE_CHECKING:
from kmibot.modules.ferry import FerryModule
Expand Down
3 changes: 2 additions & 1 deletion kmibot/modules/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

if TYPE_CHECKING:
from kmibot.client import DiscordClient
from kmibot.api import FerryAPI


class Module:
def __init__(self, client: "DiscordClient") -> None:
def __init__(self, client: "DiscordClient", api_client: "FerryAPI") -> None:
pass

async def on_ready(self, client: "DiscordClient") -> None:
Expand Down
14 changes: 11 additions & 3 deletions kmibot/modules/pub/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,25 @@
import discord
from discord import EventStatus

from kmibot.api import FerryAPI

from ..module import Module
from .commands import PubCommand
from .utils import event_is_pub, get_pub_buttons_view

if TYPE_CHECKING:
from kmibot.client import DiscordClient
from kmibot.api import FerryAPI


LOGGER = logging.getLogger(__name__)


class PubModule(Module):
def __init__(self, client: "DiscordClient") -> None:
def __init__(self, client: "DiscordClient", api_client: "FerryAPI") -> None:
self.client = client
client.tree.add_command(PubCommand(client.config), guild=client.guild)
self.api_client = api_client
client.tree.add_command(PubCommand(client.config, api_client), guild=client.guild)

async def on_scheduled_event_update(
self,
Expand All @@ -41,7 +45,11 @@ async def handle_pub_event_change(
if old_event.status is not EventStatus.active and new_event.status is EventStatus.active:
# The Pub has started.
LOGGER.info("A pub event has started.")
pub = client.config.pub.get_pub_by_name(new_event.location or "")

pub = discord.utils.find(
lambda p: p.name == new_event.location or "",
await self.api_client.get_pubs(),
)
if pub:
formatted_pub_name = (
f"{pub.emoji} **{pub.name}** {self.client.config.pub.supplemental_emoji}"
Expand Down
14 changes: 8 additions & 6 deletions kmibot/modules/pub/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,27 @@
import discord
from discord.app_commands import Group, command

from kmibot.config import BotConfig, PubInfo
from kmibot.config import BotConfig

from .utils import event_is_pub, get_pub_buttons_view
from .views import PubView
from kmibot.api import FerryAPI, PubSchema

LOGGER = getLogger(__name__)


class PubCommand(Group):
def __init__(self, config: BotConfig) -> None:
super().__init__(name="pub", description="Manage the pub event")
def __init__(self, config: BotConfig, api_client: FerryAPI) -> None:
self.config = config
self.api_client = api_client
super().__init__(name="pub", description="Manage the pub event")

async def _choose_pub(
self,
interaction: discord.Interaction,
prompt: str,
) -> PubInfo:
view = PubView(self.config.pub, prompt)
) -> PubSchema:
view = PubView(await self.api_client.get_pubs(), prompt)
await interaction.response.send_message(
prompt,
view=view,
Expand Down Expand Up @@ -66,7 +68,7 @@ def _get_next_event(self, guild: discord.Guild) -> Optional[discord.ScheduledEve
async def _create_pub_event(
self,
guild: discord.Guild,
pub: PubInfo,
pub: PubSchema,
start_time: datetime,
*,
user: str = "A user",
Expand Down
4 changes: 2 additions & 2 deletions kmibot/modules/pub/utils.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import discord

from kmibot.config import PubInfo
from kmibot.api import PubSchema


def event_is_pub(event: discord.ScheduledEvent) -> bool:
return "Pub" in event.name


def get_pub_buttons_view(pub: PubInfo) -> discord.ui.View:
def get_pub_buttons_view(pub: PubSchema) -> discord.ui.View:
view = discord.ui.View()
view.add_item(discord.ui.Button(label="Map", url=str(pub.map_url)))
if pub.menu_url:
Expand Down
21 changes: 12 additions & 9 deletions kmibot/modules/pub/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@

import discord

from kmibot.config import PubConfig, PubInfo
from kmibot.api import PubSchema


class PubSelector(discord.ui.Select):
def __init__(self, pub_config: PubConfig, prompt: str) -> None:
self._pub_config = pub_config
def __init__(self, pubs: list[PubSchema], prompt: str) -> None:
self._pubs = pubs
self.prompt = prompt

self.selected = asyncio.Event()
self.pub: Optional[PubInfo] = None
self.pub: Optional[PubSchema] = None

options = [discord.SelectOption(label=pub.name, emoji=pub.emoji) for pub in pub_config.pubs]
options = [discord.SelectOption(label=pub.name, emoji=pub.emoji) for pub in pubs]

super().__init__(
placeholder="Choose a pub...",
Expand All @@ -24,7 +24,10 @@ def __init__(self, pub_config: PubConfig, prompt: str) -> None:
)

async def callback(self, interaction: discord.Interaction) -> None:
self.pub = self._pub_config.get_pub_by_name(self.values[0])
self.pub = discord.utils.find(
lambda p: p.name == self.values[0],
self._pubs,
)
if self.pub:
await interaction.response.edit_message(
content=f"{self.prompt}\n {self.pub.emoji} {self.pub.name} has been selected", # noqa: E501
Expand All @@ -34,13 +37,13 @@ async def callback(self, interaction: discord.Interaction) -> None:


class PubView(discord.ui.View):
def __init__(self, pub_config: PubConfig, prompt: str) -> None:
def __init__(self, pubs: list[PubSchema], prompt: str) -> None:
super().__init__()

self.pub_selector = PubSelector(pub_config, prompt)
self.pub_selector = PubSelector(pubs, prompt)
self.add_item(self.pub_selector)

async def wait_until_complete(self) -> PubInfo:
async def wait_until_complete(self) -> PubSchema:
await self.pub_selector.selected.wait()
if self.pub_selector.pub is not None:
return self.pub_selector.pub
Expand Down

0 comments on commit 126e487

Please sign in to comment.