sidequest_common.models.members#

Guild members who have signed in through Discord OAuth.

Classes#

Member

One Discord user who has logged into the member hub.

Module Contents#

class sidequest_common.models.members.Member#

Bases: advanced_alchemy.base.BigIntAuditBase

One Discord user who has logged into the member hub.

id is a small internal integer (the contract’s Me.id), distinct from discord_id (Discord’s 64-bit snowflake, carried as a string in JSON). username/global_name/roles/guild_nick/ avatar_hash/is_guild_member are refreshed from Discord both at sign-in and continuously by the bot (PUT /api/guilds/{guild_id}/member-profiles: a full sweep plus debounced pushes on Discord profile/role/ membership changes), so they stay current even for a member who never signs in again after renaming. avatar_hash is Discord’s raw avatar hash (null for the default avatar); build the CDN URL from it rather than storing a URL that can go stale.

battlenet_id/battletag are set when the member links Battle.net (one Battle.net account per member, so one Blizzard account can’t vouch for several Discord accounts); officers compare the BattleTag to the roster.

officer_notice_posted_at is when the bot posted the new-signup notice embed for this member in the configured signup-notice channel (null until posted; existing members are backfilled non-null at migration so prod isn’t flooded). officer_notice_channel_id/officer_notice_message_id locate that message so it can be edited later. officer_notice_resolved_at is set once the posted message accurately reflects the member’s current roster status (approved via the embed’s button, or edited after a site confirmation).

avatar_hash: sqlalchemy.orm.Mapped[str | None]#
battlenet_id: sqlalchemy.orm.Mapped[int | None]#
battlenet_linked_at: sqlalchemy.orm.Mapped[datetime.datetime | None]#
battletag: sqlalchemy.orm.Mapped[str | None]#
calendar_token: sqlalchemy.orm.Mapped[str | None]#

Secret token for the member’s private calendar feed (GET /api/calendar/{token}.ics); generated lazily.

discord_id: sqlalchemy.orm.Mapped[int]#
property display_name: str#

Guild nick, else Discord global name, else username.

global_name: sqlalchemy.orm.Mapped[str | None]#
guild_nick: sqlalchemy.orm.Mapped[str | None]#
is_guild_member: sqlalchemy.orm.Mapped[bool]#
last_login_at: sqlalchemy.orm.Mapped[datetime.datetime | None]#
officer_notice_channel_id: sqlalchemy.orm.Mapped[int | None]#
officer_notice_message_id: sqlalchemy.orm.Mapped[int | None]#
officer_notice_posted_at: sqlalchemy.orm.Mapped[datetime.datetime | None]#
officer_notice_resolved_at: sqlalchemy.orm.Mapped[datetime.datetime | None]#
raid_status: sqlalchemy.orm.Mapped[str | None]#

EPGP roster status ("trial"/"raider", or null for not-yet-rostered); set by an officer.

roles: sqlalchemy.orm.Mapped[list[int]]#
roster_confirmed_at: sqlalchemy.orm.Mapped[datetime.datetime | None]#
trial_started_at: sqlalchemy.orm.Mapped[datetime.datetime | None]#

When raid_status was last set to "trial"; the EPGP bid order treats a trial as a trial for 14 days.

username: sqlalchemy.orm.Mapped[str]#