/** * Tournament Query Utilities * * Provides advanced querying capabilities for Challonge tournaments, * including queries across multiple states with deduplication. * * Note: The Challonge API v2.1 only supports filtering by single state * (pending, in_progress, or ended), so multi-state queries require * multiple API calls that are Promise.all'd together. */ /** * Query tournaments in ALL states * * Makes three parallel API calls (pending, in_progress, ended) and combines * the results while deduplicating by tournament ID. * * @param client - Challonge API client (from createChallongeV2Client) * @param options - Query options * @param options.scopeType - USER, COMMUNITY, or APPLICATION scope (default: USER) * @param options.communityId - Community ID (if using COMMUNITY scope) * @param options.page - Page number (default: 1) * @param options.per_page - Results per page (default: 25) * @param options.states - States to query (default: full Challonge state list) * @param options.includeCommunities - Also query community tournaments (default: false) * @returns Combined and deduplicated tournament list * * @example * import { queryAllTournaments } from '../utilities/tournament-query.js' * * const tournaments = await queryAllTournaments(client, { * scopeType: 'USER', * per_page: 100 * }) */ export async function queryAllTournaments(client, options = {}) { const { scopeType = 'USER', communityId, page = 1, per_page = 25, // Challonge v2.1 tournament list supports these canonical states. // (Older v1-style states like "checking_in" are not accepted.) states = ['pending', 'in_progress', 'ended'], includeCommunities = false } = options; // Build base query options const baseOptions = { scopeType, communityId, page, per_page }; let firstAuthError = null; // Query all states in parallel const promises = states.map(state => client.tournaments .list({ ...baseOptions, state }) .catch(err => { const status = err?.status || err?.errors?.[0]?.status; if ((status === 401 || status === 403) && !firstAuthError) { firstAuthError = err; } console.error(`Error querying ${state} tournaments:`, err); return []; }) ); // Wait for all requests const results = await Promise.all(promises); // If we hit an auth error and fetched nothing at all, surface the auth error // so the UI can prompt to connect/reconnect Challonge. const totalCount = results.reduce( (sum, arr) => sum + (Array.isArray(arr) ? arr.length : 0), 0 ); if (firstAuthError && totalCount === 0) { throw firstAuthError; } // Flatten and deduplicate by tournament ID const tournamentMap = new Map(); results.forEach(tournamentArray => { if (Array.isArray(tournamentArray)) { tournamentArray.forEach(tournament => { // Handle both v1 and v2.1 response formats const id = tournament.id || tournament.tournament?.id; if (id && !tournamentMap.has(id)) { tournamentMap.set(id, tournament); } }); } }); return Array.from(tournamentMap.values()); } /** * Query tournaments you created + tournaments where you're admin * * For the USER scope, the Challonge API returns both created and admin tournaments, * but optionally query across all states for completeness. * * @param client - Challonge API client * @param options - Query options (same as queryAllTournaments) * @returns User's created and admin tournaments */ export async function queryUserTournaments(client, options = {}) { return queryAllTournaments(client, { ...options, scopeType: 'USER' }); } /** * Query all tournaments in a community (all states) * * @param client - Challonge API client * @param communityId - Community numeric ID * @param options - Query options * @returns Community tournaments across all states */ export async function queryCommunityTournaments( client, communityId, options = {} ) { return queryAllTournaments(client, { ...options, scopeType: 'COMMUNITY', communityId }); } /** * Query tournaments with custom state list * * Useful if you only care about specific states or want to use * a different set of states than the default. * * @param client - Challonge API client * @param states - States to query (e.g., ['pending', 'in_progress']) * @param options - Query options * @returns Tournaments matching the given states */ export async function queryTournamentsByStates(client, states, options = {}) { return queryAllTournaments(client, { ...options, states }); } /** * Query active tournaments only (pending + in_progress) * * @param client - Challonge API client * @param options - Query options * @returns Active tournaments */ export async function queryActiveTournaments(client, options = {}) { return queryTournamentsByStates(client, ['pending', 'in_progress'], options); } /** * Query completed tournaments only (ended) * * @param client - Challonge API client * @param options - Query options * @returns Completed tournaments */ export async function queryCompletedTournaments(client, options = {}) { return queryTournamentsByStates(client, ['ended'], options); }