Files
bedolaga-cabinet/src/utils/campaign.ts
c0mrade 2dab25c5a0 fix: resolve telegram auth token expiration and clean up codebase
- Fix stale initData comparison in clearStaleSessionIfNeeded that destroyed
  valid refresh tokens on mobile WebView reopens
- Restrict X-Telegram-Init-Data header to auth endpoints only
- Close Mini App on auth retry to force fresh initData from Telegram
- Merge Connection page error/not-configured states for better UX
- Remove unnecessary comments across 40+ files (section dividers,
  restating comments, noise catch block comments)
- Configure ESLint allowEmptyCatch to properly handle intentional
  empty catch blocks (62 warnings resolved)
2026-03-13 17:50:49 +03:00

71 lines
1.9 KiB
TypeScript

const CAMPAIGN_KEY = 'campaign_slug';
const CAMPAIGN_TTL_KEY = 'campaign_slug_ttl';
const TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
const SLUG_PATTERN = /^[a-zA-Z0-9_-]{1,64}$/;
/**
* Get valid slug from localStorage, clearing expired entries.
*/
function getValidSlug(): string | null {
try {
const slug = localStorage.getItem(CAMPAIGN_KEY);
if (!slug) return null;
const ttl = localStorage.getItem(CAMPAIGN_TTL_KEY);
if (!ttl || Number.isNaN(Number(ttl)) || Date.now() > Number(ttl)) {
localStorage.removeItem(CAMPAIGN_KEY);
localStorage.removeItem(CAMPAIGN_TTL_KEY);
return null;
}
return slug;
} catch {
return null;
}
}
function clearSlug(): void {
try {
localStorage.removeItem(CAMPAIGN_KEY);
localStorage.removeItem(CAMPAIGN_TTL_KEY);
} catch {}
}
/**
* Capture campaign slug from URL query param, store in localStorage with TTL,
* and clean the URL.
*/
export function captureCampaignFromUrl(): void {
try {
const params = new URLSearchParams(window.location.search);
const slug = params.get('campaign');
if (!slug || !SLUG_PATTERN.test(slug)) return;
localStorage.setItem(CAMPAIGN_KEY, slug);
localStorage.setItem(CAMPAIGN_TTL_KEY, String(Date.now() + TTL_MS));
// Clean URL
params.delete('campaign');
const newSearch = params.toString();
const newUrl =
window.location.pathname + (newSearch ? `?${newSearch}` : '') + window.location.hash;
window.history.replaceState(null, '', newUrl);
} catch {}
}
/**
* Consume (get + clear) the stored campaign slug. One-time use during auth.
*/
export function consumeCampaignSlug(): string | null {
const slug = getValidSlug();
if (slug) clearSlug();
return slug;
}
/**
* Read stored campaign slug without clearing it (for email registration flow).
*/
export function getPendingCampaignSlug(): string | null {
return getValidSlug();
}