sidequest_common.schemas.guild_hub#

Guild hub v2 schemas: the addon export/import v2 sections and the /api/guild/* HTTP API.

local://addon-contract-v2.md is the source of truth; field names and string prefixes here are binding. Lua json encoders drop nil keys rather than emitting null (see sidequest_common.schemas.epgp), so every nullable contract field here is a pydantic default, not a required key.

Attributes#

Classes#

AnnouncementImportCounts

Count of new announcement rows inserted by one import.

AnnouncementPosted

Body for POST /api/guilds/{guild_id}/announcements/{id}/posted (bot).

AnnouncementPostedResult

Response for POST /api/guilds/{guild_id}/announcements/{id}/posted (bot).

AnnouncementSource

Where an announcement was made.

BankImportCounts

Count of new bank log rows inserted by one import.

BankKind

What kind of guild bank activity log row this is.

EpgpMemberNoteList

Response for GET /api/epgp/member-notes (officer).

EpgpMemberNoteRow

One row of GET /api/epgp/member-notes (officer).

EpgpRecruitList

Response for GET /api/epgp/recruits (officer).

EpgpRecruitRow

One recruit, as returned by GET /api/epgp/recruits / mutated by PUT .../{id}.

EpgpRecruitUpdate

Body for PUT /api/epgp/recruits/{id} (officer). Only fields present change.

EpgpRecruitVoteCreate

Body for POST /api/epgp/recruits/{id}/votes (officer).

ExportAnnouncement

One announcement posted in game.

ExportBankEntry

One guild bank log row.

ExportMemberNote

One officer note about a character.

ExportProfession

One character's profession scan in the export payload.

ExportRecipe

One known recipe in a profession scan.

ExportRecruit

One recruiting candidate in the export payload.

ExportRecruitVote

One officer's vote on a recruit, within the export payload.

ExportRoster

The roster object in the export payload: one sweep, taken at taken_at.

ExportRosterMember

One roster row in the export payload's roster.members.

ExportSignupV2

One in-game sign-up relayed by an officer's addon.

GameImportBadgeRef

One earned badge's id and display name.

GameImportCharacter

One of a member's characters in the members game-import section.

GameImportCrafter

One character's profession, recipes as ids (named in the shared recipe_names table).

GameImportInactiveMember

One inactive member flagged in the officer-only game-import part.

GameImportLedgerEntry

One ledger row in a member's on-demand sheet.

GameImportLootEntry

One loot row in a member's on-demand sheet.

GameImportMember

One members row in the game-import payload's public part.

GameImportNews

One news row in the game-import payload's public part.

GameImportOfficerNote

One note in the officer-only game-import part: same shape as the export.

GameImportOfficerPart

The officer-only part of the game-import payload, never broadcast to the whole guild.

GameImportOfficerRecruit

One recruit in the officer-only game-import part: same shape as the export, plus member_id.

GameImportSheet

One member's on-demand sheet: last 15 ledger entries and last 10 loot wins.

GuildAnnouncementCreate

Body for POST /api/guild/announcements (officer).

GuildAnnouncementRow

One row of GET /api/guild/announcements (public).

GuildAnnouncementsPage

Response for GET /api/guild/announcements (public), newest first, last 20.

GuildBankPage

Response for GET /api/guild/bank (member), newest first.

GuildBankRow

One row of GET /api/guild/bank (member).

GuildBankTotals

Deposit/withdrawal totals over the last 30 days, for GET /api/guild/bank.

GuildCrafterProfessionCount

How many characters know each profession, for the professions filter list.

GuildCrafterResult

One matched recipe and the characters that know it.

GuildCrafterRow

One character that knows a matched recipe, in GET /api/guild/crafters.

GuildCrafters

Response for GET /api/guild/crafters (member).

GuildNewsItem

One row of GET /api/guild/news (public).

GuildNewsPage

Response for GET /api/guild/news (public), newest first.

GuildRoster

Response for GET /api/guild/roster (member).

GuildRosterCharacter

One of a member's characters on GET /api/guild/roster.

GuildRosterMember

One member's row on GET /api/guild/roster, alts grouped under their main.

GuildRosterUnlinked

One roster-only character with no linked member, on GET /api/guild/roster.

MemberNoteImportCounts

Counts for the member_notes section of one import.

NewsKind

What kind of guild news feed item this is.

PendingAnnouncement

One queued Discord announcement, for GET /api/guilds/{guild_id}/announcements/pending (bot).

PendingAnnouncementsPage

Response for GET /api/guilds/{guild_id}/announcements/pending (bot).

ProfessionImportCounts

Count of profession rows upserted by one import.

RecruitChecklist

An officer's vetting checklist for one recruit.

RecruitImportCounts

Counts for the recruits section of one import.

RecruitStatus

A recruiting candidate's status in the vetting pipeline.

RecruitVoteChoice

An officer's vote on a recruit.

RosterImportCounts

Count of roster rows upserted by one import.

SignupImportCounts

Counts for the signups section of one import.

Module Contents#

class sidequest_common.schemas.guild_hub.AnnouncementImportCounts#

Bases: pydantic.BaseModel

Count of new announcement rows inserted by one import.

new: int = 0#
class sidequest_common.schemas.guild_hub.AnnouncementPosted#

Bases: pydantic.BaseModel

Body for POST /api/guilds/{guild_id}/announcements/{id}/posted (bot).

message_id: int#
class sidequest_common.schemas.guild_hub.AnnouncementPostedResult#

Bases: pydantic.BaseModel

Response for POST /api/guilds/{guild_id}/announcements/{id}/posted (bot).

message_id: int#
class sidequest_common.schemas.guild_hub.AnnouncementSource#

Bases: enum.StrEnum

Where an announcement was made.

Initialize self. See help(type(self)) for accurate signature.

GAME = 'game'#
SITE = 'site'#
class sidequest_common.schemas.guild_hub.BankImportCounts#

Bases: pydantic.BaseModel

Count of new bank log rows inserted by one import.

new: int = 0#
class sidequest_common.schemas.guild_hub.BankKind#

Bases: enum.StrEnum

What kind of guild bank activity log row this is.

Initialize self. See help(type(self)) for accurate signature.

BUY_TAB = 'buy_tab'#
DEPOSIT = 'deposit'#
DEPOSIT_MONEY = 'deposit_money'#
MOVE = 'move'#
REPAIR = 'repair'#
WITHDRAW = 'withdraw'#
WITHDRAW_MONEY = 'withdraw_money'#
class sidequest_common.schemas.guild_hub.EpgpMemberNoteList#

Bases: pydantic.BaseModel

Response for GET /api/epgp/member-notes (officer).

notes: list[EpgpMemberNoteRow]#
class sidequest_common.schemas.guild_hub.EpgpMemberNoteRow#

Bases: pydantic.BaseModel

One row of GET /api/epgp/member-notes (officer).

at: datetime.datetime#
character: str#
id: uuid.UUID#
member_id: int | None#
note: str#
officer: str#
voided: bool#
class sidequest_common.schemas.guild_hub.EpgpRecruitList#

Bases: pydantic.BaseModel

Response for GET /api/epgp/recruits (officer).

recruits: list[EpgpRecruitRow]#
class sidequest_common.schemas.guild_hub.EpgpRecruitRow#

Bases: pydantic.BaseModel

One recruit, as returned by GET /api/epgp/recruits / mutated by PUT .../{id}.

at: datetime.datetime#
character: str#
checklist: RecruitChecklist#
id: uuid.UUID#
member_id: int | None#
model_config#
note: str | None#
status: RecruitStatus#
votes: list[ExportRecruitVote]#
wow_class: sidequest_common.schemas.events.WowClass | None#
class sidequest_common.schemas.guild_hub.EpgpRecruitUpdate#

Bases: pydantic.BaseModel

Body for PUT /api/epgp/recruits/{id} (officer). Only fields present change.

checklist: RecruitChecklist | None = None#
note: str | None#
status: RecruitStatus | None = None#
class sidequest_common.schemas.guild_hub.EpgpRecruitVoteCreate#

Bases: pydantic.BaseModel

Body for POST /api/epgp/recruits/{id}/votes (officer).

vote: RecruitVoteChoice#
class sidequest_common.schemas.guild_hub.ExportAnnouncement#

Bases: pydantic.BaseModel

One announcement posted in game.

at: int#
discord: bool = False#
id: str#
officer: str#
text: str#
class sidequest_common.schemas.guild_hub.ExportBankEntry#

Bases: pydantic.BaseModel

One guild bank log row.

at: int#
character: str | None#
count: int = 0#
id: str#
item_id: int | None = None#
item_name: str | None#
kind: BankKind#
money: int = 0#
tab: int | None = None#
class sidequest_common.schemas.guild_hub.ExportMemberNote#

Bases: pydantic.BaseModel

One officer note about a character.

at: int#
character: str#
id: str#
note: str#
officer: str#
voided: bool = False#
class sidequest_common.schemas.guild_hub.ExportProfession#

Bases: pydantic.BaseModel

One character’s profession scan in the export payload.

character: str#
max_skill: int = 0#
profession: str#
recipes: list[ExportRecipe]#
scanned_at: int#
skill: int = 0#
class sidequest_common.schemas.guild_hub.ExportRecipe#

Bases: pydantic.BaseModel

One known recipe in a profession scan.

id: int#
item_id: int | None = None#
name: str#
class sidequest_common.schemas.guild_hub.ExportRecruit#

Bases: pydantic.BaseModel

One recruiting candidate in the export payload.

at: int#
character: str#
checklist: RecruitChecklist#
id: str#
model_config#
note: str | None#
status: RecruitStatus#
votes: list[ExportRecruitVote]#
wow_class: GameClass | None#
class sidequest_common.schemas.guild_hub.ExportRecruitVote#

Bases: pydantic.BaseModel

One officer’s vote on a recruit, within the export payload.

at: int#
officer: str#
vote: RecruitVoteChoice#
class sidequest_common.schemas.guild_hub.ExportRoster#

Bases: pydantic.BaseModel

The roster object in the export payload: one sweep, taken at taken_at.

members: list[ExportRosterMember]#
taken_at: int#
class sidequest_common.schemas.guild_hub.ExportRosterMember#

Bases: pydantic.BaseModel

One roster row in the export payload’s roster.members.

character: str#
last_online_hours: float = 0#
level: int = 0#
model_config#
online: bool = False#
rank: str#
rank_index: int = 0#
wow_class: GameClass | None#
zone: str#
class sidequest_common.schemas.guild_hub.ExportSignupV2#

Bases: pydantic.BaseModel

One in-game sign-up relayed by an officer’s addon.

at: int#
character: str#
comment: str | None#
event_id: uuid.UUID#
id: str#
model_config#
role: sidequest_common.schemas.events.SignupRole | None = None#
status: sidequest_common.schemas.events.SignupStatus#
wow_class: GameClass | None#
class sidequest_common.schemas.guild_hub.GameImportBadgeRef#

Bases: pydantic.BaseModel

One earned badge’s id and display name.

id: str#
name: str#
class sidequest_common.schemas.guild_hub.GameImportCharacter#

Bases: pydantic.BaseModel

One of a member’s characters in the members game-import section.

is_main: bool#
level: int#
model_config#
name: str#
wow_class: sidequest_common.schemas.events.WowClass | None#
class sidequest_common.schemas.guild_hub.GameImportCrafter#

Bases: pydantic.BaseModel

One character’s profession, recipes as ids (named in the shared recipe_names table).

character: str#
member_id: int | None#
profession: str#
recipes: list[int]#
skill: int#
class sidequest_common.schemas.guild_hub.GameImportInactiveMember#

Bases: pydantic.BaseModel

One inactive member flagged in the officer-only game-import part.

last_raid_at: int | None#
last_seen_at: int | None#
member_id: int#
name: str#
class sidequest_common.schemas.guild_hub.GameImportLedgerEntry#

Bases: pydantic.BaseModel

One ledger row in a member’s on-demand sheet.

amount: int#
at: int#
decayed: float#
kind: str#
note: str | None#
reason: str#
class sidequest_common.schemas.guild_hub.GameImportLootEntry#

Bases: pydantic.BaseModel

One loot row in a member’s on-demand sheet.

at: int#
gp: int#
item_id: int#
item_name: str#
quality: int#
response: str#
class sidequest_common.schemas.guild_hub.GameImportMember#

Bases: pydantic.BaseModel

One members row in the game-import payload’s public part.

attendance_rate: float#
badges: list[GameImportBadgeRef]#
characters: list[GameImportCharacter]#
events_attended: int#
guild_ep: int#
main: str | None#
member_id: int#
model_config#
name: str#
raid_status: str | None#
rank: str | None#
wow_class: sidequest_common.schemas.events.WowClass | None#
class sidequest_common.schemas.guild_hub.GameImportNews#

Bases: pydantic.BaseModel

One news row in the game-import payload’s public part.

at: int#
character: str | None#
id: str#
item_id: int | None#
kind: NewsKind#
quality: int | None#
text: str#
class sidequest_common.schemas.guild_hub.GameImportOfficerNote#

Bases: pydantic.BaseModel

One note in the officer-only game-import part: same shape as the export.

at: int#
character: str#
id: str#
note: str#
officer: str#
voided: bool#
class sidequest_common.schemas.guild_hub.GameImportOfficerPart#

Bases: pydantic.BaseModel

The officer-only part of the game-import payload, never broadcast to the whole guild.

inactive: list[GameImportInactiveMember]#
member_notes: list[GameImportOfficerNote]#
recruits: list[GameImportOfficerRecruit]#
class sidequest_common.schemas.guild_hub.GameImportOfficerRecruit#

Bases: pydantic.BaseModel

One recruit in the officer-only game-import part: same shape as the export, plus member_id.

at: int#
character: str#
checklist: RecruitChecklist#
id: str#
member_id: int | None#
model_config#
note: str | None#
status: RecruitStatus#
votes: list[ExportRecruitVote]#
wow_class: sidequest_common.schemas.events.WowClass | None#
class sidequest_common.schemas.guild_hub.GameImportSheet#

Bases: pydantic.BaseModel

One member’s on-demand sheet: last 15 ledger entries and last 10 loot wins.

ledger: list[GameImportLedgerEntry]#
loot: list[GameImportLootEntry]#
class sidequest_common.schemas.guild_hub.GuildAnnouncementCreate#

Bases: pydantic.BaseModel

Body for POST /api/guild/announcements (officer).

discord: bool = False#
text: str#
class sidequest_common.schemas.guild_hub.GuildAnnouncementRow#

Bases: pydantic.BaseModel

One row of GET /api/guild/announcements (public).

at: datetime.datetime#
author: str#
id: uuid.UUID#
posted_at: datetime.datetime | None#
source: AnnouncementSource#
text: str#
class sidequest_common.schemas.guild_hub.GuildAnnouncementsPage#

Bases: pydantic.BaseModel

Response for GET /api/guild/announcements (public), newest first, last 20.

items: list[GuildAnnouncementRow]#
class sidequest_common.schemas.guild_hub.GuildBankPage#

Bases: pydantic.BaseModel

Response for GET /api/guild/bank (member), newest first.

rows: list[GuildBankRow]#
totals: GuildBankTotals#
class sidequest_common.schemas.guild_hub.GuildBankRow#

Bases: pydantic.BaseModel

One row of GET /api/guild/bank (member).

at: datetime.datetime#
character: str | None#
count: int#
id: uuid.UUID#
item_id: int | None#
item_name: str | None#
kind: BankKind#
member_name: str | None#
money: int#
tab: int | None#
class sidequest_common.schemas.guild_hub.GuildBankTotals#

Bases: pydantic.BaseModel

Deposit/withdrawal totals over the last 30 days, for GET /api/guild/bank.

deposits_30d: int#
withdrawals_30d: int#
class sidequest_common.schemas.guild_hub.GuildCrafterProfessionCount#

Bases: pydantic.BaseModel

How many characters know each profession, for the professions filter list.

crafters: int#
profession: str#
class sidequest_common.schemas.guild_hub.GuildCrafterResult#

Bases: pydantic.BaseModel

One matched recipe and the characters that know it.

crafters: list[GuildCrafterRow]#
item_id: int | None#
recipe_id: int#
recipe_name: str#
class sidequest_common.schemas.guild_hub.GuildCrafterRow#

Bases: pydantic.BaseModel

One character that knows a matched recipe, in GET /api/guild/crafters.

character: str#
member_id: int | None#
member_name: str | None#
profession: str#
skill: int#
class sidequest_common.schemas.guild_hub.GuildCrafters#

Bases: pydantic.BaseModel

Response for GET /api/guild/crafters (member).

professions: list[GuildCrafterProfessionCount]#
results: list[GuildCrafterResult]#
class sidequest_common.schemas.guild_hub.GuildNewsItem#

Bases: pydantic.BaseModel

One row of GET /api/guild/news (public).

at: datetime.datetime#
character: str | None#
id: uuid.UUID#
item_id: int | None#
kind: NewsKind#
quality: int | None#
text: str#
class sidequest_common.schemas.guild_hub.GuildNewsPage#

Bases: pydantic.BaseModel

Response for GET /api/guild/news (public), newest first.

items: list[GuildNewsItem]#
class sidequest_common.schemas.guild_hub.GuildRoster#

Bases: pydantic.BaseModel

Response for GET /api/guild/roster (member).

members: list[GuildRosterMember]#
taken_at: datetime.datetime | None#
unlinked: list[GuildRosterUnlinked]#
class sidequest_common.schemas.guild_hub.GuildRosterCharacter#

Bases: pydantic.BaseModel

One of a member’s characters on GET /api/guild/roster.

is_main: bool#
last_seen_at: datetime.datetime#
level: int#
model_config#
name: str#
wow_class: sidequest_common.schemas.events.WowClass | None#
zone: str#
class sidequest_common.schemas.guild_hub.GuildRosterMember#

Bases: pydantic.BaseModel

One member’s row on GET /api/guild/roster, alts grouped under their main.

characters: list[GuildRosterCharacter]#
main: str | None#
member_id: int#
name: str#
raid_status: str | None#
rank: str | None#
class sidequest_common.schemas.guild_hub.GuildRosterUnlinked#

Bases: pydantic.BaseModel

One roster-only character with no linked member, on GET /api/guild/roster.

last_seen_at: datetime.datetime#
level: int#
model_config#
name: str#
rank: str#
wow_class: sidequest_common.schemas.events.WowClass | None#
class sidequest_common.schemas.guild_hub.MemberNoteImportCounts#

Bases: pydantic.BaseModel

Counts for the member_notes section of one import.

new: int = 0#
updated: int = 0#
voided: int = 0#
class sidequest_common.schemas.guild_hub.NewsKind#

Bases: enum.StrEnum

What kind of guild news feed item this is.

Initialize self. See help(type(self)) for accurate signature.

ANNOUNCEMENT = 'announcement'#
BADGE = 'badge'#
BOSS_KILL = 'boss_kill'#
FIRST_KILL = 'first_kill'#
JOINED = 'joined'#
LEVEL = 'level'#
LOOT = 'loot'#
class sidequest_common.schemas.guild_hub.PendingAnnouncement#

Bases: pydantic.BaseModel

One queued Discord announcement, for GET /api/guilds/{guild_id}/announcements/pending (bot).

at: datetime.datetime#
author: str#
id: uuid.UUID#
text: str#
class sidequest_common.schemas.guild_hub.PendingAnnouncementsPage#

Bases: pydantic.BaseModel

Response for GET /api/guilds/{guild_id}/announcements/pending (bot).

items: list[PendingAnnouncement]#
class sidequest_common.schemas.guild_hub.ProfessionImportCounts#

Bases: pydantic.BaseModel

Count of profession rows upserted by one import.

updated: int = 0#
class sidequest_common.schemas.guild_hub.RecruitChecklist#

Bases: pydantic.BaseModel

An officer’s vetting checklist for one recruit.

first_raid: bool = False#
gear_check: bool = False#
talked: bool = False#
vouched: bool = False#
class sidequest_common.schemas.guild_hub.RecruitImportCounts#

Bases: pydantic.BaseModel

Counts for the recruits section of one import.

new: int = 0#
updated: int = 0#
class sidequest_common.schemas.guild_hub.RecruitStatus#

Bases: enum.StrEnum

A recruiting candidate’s status in the vetting pipeline.

Initialize self. See help(type(self)) for accurate signature.

ACCEPTED = 'accepted'#
APPLICANT = 'applicant'#
DECLINED = 'declined'#
TRIAL = 'trial'#
class sidequest_common.schemas.guild_hub.RecruitVoteChoice#

Bases: enum.StrEnum

An officer’s vote on a recruit.

Initialize self. See help(type(self)) for accurate signature.

NO = 'no'#
WAIT = 'wait'#
YES = 'yes'#
class sidequest_common.schemas.guild_hub.RosterImportCounts#

Bases: pydantic.BaseModel

Count of roster rows upserted by one import.

updated: int = 0#
class sidequest_common.schemas.guild_hub.SignupImportCounts#

Bases: pydantic.BaseModel

Counts for the signups section of one import.

applied: int = 0#
skipped_older: int = 0#
unlinked: int = 0#
sidequest_common.schemas.guild_hub.ANNOUNCEMENT_TEXT_MAX = 500#
sidequest_common.schemas.guild_hub.INACTIVE_AFTER_DAYS = 14#
sidequest_common.schemas.guild_hub.LEFT_GUILD_AFTER_DAYS = 30#
sidequest_common.schemas.guild_hub.LEVEL_MILESTONE_STEP = 10#
sidequest_common.schemas.guild_hub.MAX_ANNOUNCEMENTS_V2 = 200#
sidequest_common.schemas.guild_hub.MAX_BANK_ENTRIES = 2000#
sidequest_common.schemas.guild_hub.MAX_MEMBER_NOTES_V2 = 500#
sidequest_common.schemas.guild_hub.MAX_PROFESSION_PAIRS = 400#
sidequest_common.schemas.guild_hub.MAX_RECIPES_PER_PROFESSION = 2000#
sidequest_common.schemas.guild_hub.MAX_RECRUITS_V2 = 200#
sidequest_common.schemas.guild_hub.MAX_ROSTER_MEMBERS = 1000#
sidequest_common.schemas.guild_hub.MAX_SIGNUPS_V2 = 500#
sidequest_common.schemas.guild_hub.NOTE_TEXT_MAX = 500#
sidequest_common.schemas.guild_hub.RECRUIT_NOTE_MAX = 500#