mirror of
https://github.com/Pandipipas/scoreko-dev.git
synced 2026-06-06 03:32:06 +00:00
feat(players): add Challonge temporary imported-player expiration
This commit is contained in:
@@ -45,6 +45,7 @@ interface ChallongeImportedPlayer extends Player {
|
||||
const STARTGG_TOKEN_STORAGE_KEY = 'scoreko-dev.startgg-token';
|
||||
const CHALLONGE_TOKEN_STORAGE_KEY = 'scoreko-dev.challonge-token';
|
||||
const STARTGG_TEMP_PLAYERS_STORAGE_KEY = 'scoreko-dev.startgg-temp-players';
|
||||
const CHALLONGE_TEMP_PLAYERS_STORAGE_KEY = 'scoreko-dev.challonge-temp-players';
|
||||
const STARTGG_TEMP_FALLBACK_DURATION_SECONDS = 12 * 60 * 60;
|
||||
|
||||
interface TemporaryStartGGPlayerMeta {
|
||||
@@ -53,6 +54,7 @@ interface TemporaryStartGGPlayerMeta {
|
||||
}
|
||||
|
||||
type TemporaryStartGGPlayersMap = Record<string, TemporaryStartGGPlayerMeta>;
|
||||
type TemporaryChallongePlayersMap = Record<string, TemporaryStartGGPlayerMeta>;
|
||||
|
||||
const playersStore = usePlayersStore();
|
||||
const rows = computed<PlayerRow[]>(() => playersStore.rows);
|
||||
@@ -122,6 +124,7 @@ const selectedStartGGPlayerIds = ref<string[]>([]);
|
||||
const selectedTournamentSlug = ref('');
|
||||
const tournamentInput = ref('');
|
||||
const temporaryStartGGPlayers = ref<TemporaryStartGGPlayersMap>({});
|
||||
const temporaryChallongePlayers = ref<TemporaryChallongePlayersMap>({});
|
||||
let temporaryCleanupTimer: ReturnType<typeof setInterval> | null = null;
|
||||
|
||||
const oauthLoading = ref(false);
|
||||
@@ -171,6 +174,10 @@ const persistTemporaryStartGGPlayers = () => {
|
||||
localStorage.setItem(STARTGG_TEMP_PLAYERS_STORAGE_KEY, JSON.stringify(temporaryStartGGPlayers.value));
|
||||
};
|
||||
|
||||
const persistTemporaryChallongePlayers = () => {
|
||||
localStorage.setItem(CHALLONGE_TEMP_PLAYERS_STORAGE_KEY, JSON.stringify(temporaryChallongePlayers.value));
|
||||
};
|
||||
|
||||
const loadTemporaryStartGGPlayers = (): TemporaryStartGGPlayersMap => {
|
||||
try {
|
||||
const raw = localStorage.getItem(STARTGG_TEMP_PLAYERS_STORAGE_KEY);
|
||||
@@ -205,6 +212,40 @@ const loadTemporaryStartGGPlayers = (): TemporaryStartGGPlayersMap => {
|
||||
}
|
||||
};
|
||||
|
||||
const loadTemporaryChallongePlayers = (): TemporaryChallongePlayersMap => {
|
||||
try {
|
||||
const raw = localStorage.getItem(CHALLONGE_TEMP_PLAYERS_STORAGE_KEY);
|
||||
if (!raw) {
|
||||
return {};
|
||||
}
|
||||
const parsed = JSON.parse(raw) as unknown;
|
||||
if (typeof parsed !== 'object' || parsed === null) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const result: TemporaryChallongePlayersMap = {};
|
||||
Object.entries(parsed as Record<string, unknown>).forEach(([playerId, value]) => {
|
||||
if (!playerId || typeof value !== 'object' || value === null) {
|
||||
return;
|
||||
}
|
||||
const candidate = value as Record<string, unknown>;
|
||||
const expiresAt = Number(candidate.expiresAt);
|
||||
const tournamentSlug = String(candidate.tournamentSlug || '').trim();
|
||||
if (!Number.isFinite(expiresAt) || expiresAt <= 0 || !tournamentSlug) {
|
||||
return;
|
||||
}
|
||||
result[playerId] = {
|
||||
expiresAt,
|
||||
tournamentSlug,
|
||||
};
|
||||
});
|
||||
|
||||
return result;
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
const tournamentOptions = computed(() =>
|
||||
recentTournaments.value.map((tournament) => ({
|
||||
label: tournament.name,
|
||||
@@ -276,22 +317,31 @@ const clearTemporaryCleanupTimer = () => {
|
||||
|
||||
const cleanupExpiredTemporaryPlayers = () => {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const expiredIds = Object.entries(temporaryStartGGPlayers.value)
|
||||
const expiredStartGGIds = Object.entries(temporaryStartGGPlayers.value)
|
||||
.filter(([, meta]) => meta.expiresAt <= now)
|
||||
.map(([playerId]) => playerId);
|
||||
const expiredChallongeIds = Object.entries(temporaryChallongePlayers.value)
|
||||
.filter(([, meta]) => meta.expiresAt <= now)
|
||||
.map(([playerId]) => playerId);
|
||||
|
||||
const expiredIds = Array.from(new Set([...expiredStartGGIds, ...expiredChallongeIds]));
|
||||
|
||||
if (!expiredIds.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextMeta = { ...temporaryStartGGPlayers.value };
|
||||
const nextStartGGMeta = { ...temporaryStartGGPlayers.value };
|
||||
const nextChallongeMeta = { ...temporaryChallongePlayers.value };
|
||||
expiredIds.forEach((playerId) => {
|
||||
playersStore.removePlayer(playerId);
|
||||
delete nextMeta[playerId];
|
||||
delete nextStartGGMeta[playerId];
|
||||
delete nextChallongeMeta[playerId];
|
||||
});
|
||||
|
||||
temporaryStartGGPlayers.value = nextMeta;
|
||||
temporaryStartGGPlayers.value = nextStartGGMeta;
|
||||
temporaryChallongePlayers.value = nextChallongeMeta;
|
||||
persistTemporaryStartGGPlayers();
|
||||
persistTemporaryChallongePlayers();
|
||||
};
|
||||
|
||||
const checkOAuthStatus = async () => {
|
||||
@@ -569,6 +619,11 @@ const importSelectedChallongePlayers = () => {
|
||||
selectedChallongePlayerIds.value.includes(player.id),
|
||||
);
|
||||
|
||||
const nextMeta = { ...temporaryChallongePlayers.value };
|
||||
const tournament = importingChallongeTournament.value;
|
||||
const fallbackEndAt = (tournament?.startAt ?? Math.floor(Date.now() / 1000)) + STARTGG_TEMP_FALLBACK_DURATION_SECONDS;
|
||||
const expiresAt = tournament?.endAt ?? fallbackEndAt;
|
||||
|
||||
selectedPlayers.forEach((player) => {
|
||||
playersStore.upsertPlayer(player.id, {
|
||||
gamertag: player.gamertag,
|
||||
@@ -577,8 +632,17 @@ const importSelectedChallongePlayers = () => {
|
||||
country: player.country,
|
||||
twitter: player.twitter,
|
||||
});
|
||||
|
||||
if (tournament) {
|
||||
nextMeta[player.id] = {
|
||||
expiresAt,
|
||||
tournamentSlug: tournament.slug,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
temporaryChallongePlayers.value = nextMeta;
|
||||
persistTemporaryChallongePlayers();
|
||||
challongeImportDialogOpen.value = false;
|
||||
};
|
||||
|
||||
@@ -718,6 +782,7 @@ const handleImport = async (event: Event) => {
|
||||
|
||||
onMounted(() => {
|
||||
temporaryStartGGPlayers.value = loadTemporaryStartGGPlayers();
|
||||
temporaryChallongePlayers.value = loadTemporaryChallongePlayers();
|
||||
cleanupExpiredTemporaryPlayers();
|
||||
temporaryCleanupTimer = setInterval(cleanupExpiredTemporaryPlayers, 60 * 1000);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user