Skip to content

Commit

Permalink
Tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
trickeydan committed Sep 19, 2024
1 parent 2bc92f3 commit fa3e2c1
Show file tree
Hide file tree
Showing 5 changed files with 328 additions and 194 deletions.
52 changes: 51 additions & 1 deletion kmibot/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,24 @@ def parse_menu_url(cls, val: str) -> str | None:
return val if val else None


class PubLinkSchema(BaseModel):
id: UUID
name: str


class PubTableSchema(BaseModel):
id: UUID
pub: PubLinkSchema
number: int


class PubEventSchema(BaseModel):
id: UUID
timestamp: datetime
pub: UUID
discord_id: int | None
attendees: list[UUID]
table: PubTableSchema | None
attendees: list[PersonLinkSchema]


class FerryAPI:
Expand Down Expand Up @@ -181,6 +193,13 @@ async def get_pubs(
ta = TypeAdapter(list[PubSchema])
return ta.validate_python(data["results"])

async def get_pub(
self,
pub_id: UUID,
) -> PubSchema:
data = await self._request("GET", f"v2/pub/pubs/{pub_id}/")
return PubSchema.model_validate(data)

async def create_pub_event(
self,
timestamp: datetime,
Expand All @@ -206,3 +225,34 @@ async def get_pub_event_by_discord_id(self, scheduled_event_id: int) -> PubEvent

ta = TypeAdapter(list[PubEventSchema])
return ta.validate_python(data["results"])[0]

async def add_attendee_to_pub_event(self, pub_event_id: UUID, person_id: UUID) -> None:
payload = {
"person": str(person_id),
}
try:
await self._request(
"POST", f"v2/pub/events/{pub_event_id}/attendees/add/", json=payload
)
except httpx.HTTPStatusError as exc:
LOGGER.exception(exc)

async def remove_attendee_from_pub_event(self, pub_event_id: UUID, person_id: UUID) -> None:
payload = {
"person": str(person_id),
}
try:
await self._request(
"POST", f"v2/pub/events/{pub_event_id}/attendees/remove/", json=payload
)
except httpx.HTTPStatusError as exc:
LOGGER.exception(exc)

async def update_table_for_pub_event(self, pub_event_id: UUID, table_number: int) -> None:
payload = {
"table_number": table_number,
}
try:
await self._request("POST", f"v2/pub/events/{pub_event_id}/table/", json=payload)
except httpx.HTTPStatusError as exc:
LOGGER.exception(exc)
30 changes: 27 additions & 3 deletions kmibot/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import discord
from discord import app_commands

from kmibot.modules.pub.utils import event_is_pub

from .api import FerryAPI
from .config import BotConfig
from .modules import MODULES, Module
Expand All @@ -16,7 +18,7 @@ def __init__(self, config: BotConfig) -> None:
super().__init__(intents=self.intents)

self.config = config
self.guild = discord.Object(config.discord.guild_id)
self.guild: discord.Object | discord.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)

Expand All @@ -26,7 +28,9 @@ def __init__(self, config: BotConfig) -> None:
@property
def intents(self) -> discord.Intents:
intents = discord.Intents.default()
intents.members = True
intents.message_content = True
intents.guild_scheduled_events = True
return intents

async def setup_hook(self) -> None:
Expand All @@ -43,8 +47,8 @@ async def on_ready(self) -> None:
raise RuntimeError(
f"Expected to connect to exactly 1 guild, found {len(guilds)}",
)
guild = guilds[0]
LOGGER.info(f"Guild: {guild.name}")
self.guild = guilds[0]
LOGGER.info(f"Guild: {self.guild}")

for module in self._modules:
asyncio.create_task(module.on_ready(self))
Expand All @@ -57,3 +61,23 @@ async def on_scheduled_event_update(
LOGGER.info(f"Received update for scheduled event: {old_event.name}")
for module in self._modules:
asyncio.create_task(module.on_scheduled_event_update(self, old_event, new_event))

async def on_scheduled_event_user_add(
self, event: discord.ScheduledEvent, user: discord.User
) -> None:
LOGGER.info(f"{user} joined {event.name}")
if event_is_pub(event):
pub_event = await self.api_client.get_pub_event_by_discord_id(event.id)
person = await self.api_client.get_person_for_discord_member(user)
await self.api_client.add_attendee_to_pub_event(pub_event.id, person.id)
LOGGER.info(f"Added {person.display_name} to {pub_event}")

async def on_scheduled_event_user_remove(
self, event: discord.ScheduledEvent, user: discord.User
) -> None:
LOGGER.info(f"{user} left {event.name}")
if event_is_pub(event):
pub_event = await self.api_client.get_pub_event_by_discord_id(event.id)
person = await self.api_client.get_person_for_discord_member(user)
await self.api_client.remove_attendee_from_pub_event(pub_event.id, person.id)
LOGGER.info(f"Removed {person.display_name} from {pub_event}")
64 changes: 60 additions & 4 deletions kmibot/modules/pub/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from logging import getLogger

import discord
from discord.app_commands import Group, command
from discord.app_commands import Group, command, describe

from kmibot.config import BotConfig

Expand Down Expand Up @@ -36,6 +36,7 @@ async def _choose_pub(

def _get_next_pub_time(self) -> datetime:
now = datetime.now(tz=self.config.timezone)

today = now.date()
if today.weekday() < self.config.pub.weekday or (
today.weekday() == self.config.pub.weekday
Expand All @@ -57,10 +58,16 @@ def _get_next_pub_time(self) -> datetime:
tzinfo=self.config.timezone,
)

def _get_next_event(self, guild: discord.Guild) -> discord.ScheduledEvent | None:
def _get_next_event(
self, guild: discord.Guild, *, ignore_time: bool = False
) -> discord.ScheduledEvent | None:
pub_time = self._get_next_pub_time()
for event in guild.scheduled_events:
if event_is_pub(event) and event.start_time == pub_time:
for event in sorted(guild.scheduled_events, key=lambda se: se.start_time):
if (
event_is_pub(event)
and (ignore_time or event.start_time == pub_time)
and event.status in {discord.EventStatus.scheduled, discord.EventStatus.active}
):
return event
return None

Expand Down Expand Up @@ -123,6 +130,9 @@ async def next(self, interaction: discord.Interaction) -> None: # noqa: A003
user=interaction.user,
)

pub_channel = interaction.guild.get_channel(self.config.pub.channel_id)
assert isinstance(pub_channel, discord.TextChannel)

LOGGER.info(f"Posting pub info in {pub_channel}")
formatted_pub_name = f"{pub.emoji} **{pub.name}** {self.config.pub.supplemental_emoji}"
await pub_channel.send(
Expand Down Expand Up @@ -161,3 +171,49 @@ async def now(self, interaction: discord.Interaction) -> None:
)

# A message is posted in the channel by the scheduled event handler

@command(description="Update the table number for the current pub event")
@describe(
table_number="The table number",
)
async def table(self, interaction: discord.Interaction, table_number: int) -> None:
assert interaction.guild
if table_number <= 0:
await interaction.response.send_message(
"Sorry, the table number must exist in this dimension.",
ephemeral=True,
)
return

event = self._get_next_event(interaction.guild, ignore_time=True)
if event is None:
LOGGER.info("No pub exists.")
await interaction.response.send_message(
"There doesn't appear to be a pub at this time.",
ephemeral=True,
)
return

pub_event = await self.api_client.get_pub_event_by_discord_id(event.id)
pub = await self.api_client.get_pub(pub_event.pub)
await self.api_client.update_table_for_pub_event(pub_event.id, table_number)

await interaction.response.send_message(
f"Set table number to {table_number}, thanks.",
ephemeral=True,
)

pub_channel = interaction.guild.get_channel(self.config.pub.channel_id)
assert isinstance(pub_channel, discord.TextChannel)

LOGGER.info(f"Posting pub table info in {pub_channel}")
formatted_pub_name = f"{pub.emoji} **{pub.name}** {self.config.pub.supplemental_emoji}"
await pub_channel.send(
"\n".join(
[
"**Pub Table**",
f"We are at table {table_number} in {formatted_pub_name}",
],
),
view=get_pub_buttons_view(pub),
)
Loading

0 comments on commit fa3e2c1

Please sign in to comment.