Add RSVP role synchronization and localization support for Discord
Some checks failed
CI / backend (push) Has been cancelled
CI / frontend (push) Has been cancelled
CI / compose (push) Has been cancelled

This commit introduces functionality for managing event-specific RSVP roles in Discord, including roles for "Registered", "Going", "Maybe", and "Not Going". The `RoleWorker` has been enhanced to handle these roles based on user registrations, with localization support for role names in Russian and English. Additionally, the database schema has been updated to accommodate new role types and actions, and the service layer has been modified to trigger role synchronization upon relevant event updates. Tests have been added to ensure the correct behavior of the new RSVP handling logic.
This commit is contained in:
2026-07-19 11:42:40 +03:00
parent c3624376b0
commit 966c81ba12
12 changed files with 373 additions and 40 deletions

View File

@@ -20,12 +20,19 @@ func (s *Store) EnqueueDiscordRoleSync(ctx context.Context, eventID, action stri
}
func (s *Store) SeedDiscordRoleSyncJobs(ctx context.Context) error {
_, err := s.pool.Exec(ctx, `INSERT INTO discord_role_sync_jobs(event_id,action,generation)
if _, err := s.pool.Exec(ctx, `INSERT INTO discord_role_sync_jobs(event_id,action,generation)
SELECT e.id,'reconcile',e.version
FROM events e
JOIN event_rosters er ON er.event_id=e.id
WHERE e.state IN ('RostersConfirmed','BracketDraft','Live')
AND COALESCE((er.body->>'confirmed')::boolean,false)=true
ON CONFLICT(event_id,action,generation) DO NOTHING`); err != nil {
return err
}
_, err := s.pool.Exec(ctx, `INSERT INTO discord_role_sync_jobs(event_id,action,generation)
SELECT DISTINCT e.id,'rsvp',e.version
FROM events e JOIN rsvps r ON r.event_id=e.id
WHERE e.state NOT IN ('Completed','Cancelled')
ON CONFLICT(event_id,action,generation) DO NOTHING`)
return err
}
@@ -182,6 +189,26 @@ func (s *Store) ListActiveDiscordRoleRosters(ctx context.Context) ([]application
return out, nil
}
func (s *Store) GetDiscordRoleRegistration(ctx context.Context, eventID string) (application.DiscordRoleRegistration, error) {
event, err := s.GetEvent(ctx, eventID)
if err != nil {
return application.DiscordRoleRegistration{}, err
}
registrations, err := s.ListRSVPs(ctx, eventID)
if err != nil {
return application.DiscordRoleRegistration{}, err
}
playerIDs := make([]string, 0, len(registrations))
for _, registration := range registrations {
playerIDs = append(playerIDs, registration.PlayerID)
}
discordIDs, err := s.playerDiscordIDs(ctx, playerIDs)
if err != nil {
return application.DiscordRoleRegistration{}, err
}
return application.DiscordRoleRegistration{Event: event, Registrations: registrations, PlayerDiscordIDs: discordIDs}, nil
}
func (s *Store) discordRoleRoster(ctx context.Context, roster domain.RosterDraft) (application.DiscordRoleRoster, error) {
playerIDs := make([]string, 0)
for _, team := range roster.Teams {
@@ -191,25 +218,31 @@ func (s *Store) discordRoleRoster(ctx context.Context, roster domain.RosterDraft
}
}
}
discordIDs := make(map[string]string)
if len(playerIDs) > 0 {
rows, err := s.pool.Query(ctx, `SELECT p.id,a.discord_id
FROM players p JOIN accounts a ON a.id=p.account_id
WHERE p.id=ANY($1)`, playerIDs)
if err != nil {
return application.DiscordRoleRoster{}, err
}
defer rows.Close()
for rows.Next() {
var playerID, discordID string
if err = rows.Scan(&playerID, &discordID); err != nil {
return application.DiscordRoleRoster{}, err
}
discordIDs[playerID] = discordID
}
if err = rows.Err(); err != nil {
return application.DiscordRoleRoster{}, err
}
discordIDs, err := s.playerDiscordIDs(ctx, playerIDs)
if err != nil {
return application.DiscordRoleRoster{}, err
}
return application.DiscordRoleRoster{Roster: roster, PlayerDiscordIDs: discordIDs}, nil
}
func (s *Store) playerDiscordIDs(ctx context.Context, playerIDs []string) (map[string]string, error) {
discordIDs := make(map[string]string)
if len(playerIDs) == 0 {
return discordIDs, nil
}
rows, err := s.pool.Query(ctx, `SELECT p.id,a.discord_id
FROM players p JOIN accounts a ON a.id=p.account_id
WHERE p.id=ANY($1)`, playerIDs)
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var playerID, discordID string
if err = rows.Scan(&playerID, &discordID); err != nil {
return nil, err
}
discordIDs[playerID] = discordID
}
return discordIDs, rows.Err()
}