import { config } from '@config/index.js'; import crypto from 'crypto'; export function hashIP(ip: string): string { return crypto.createHash('sha256').update(ip + config.SESSION_SECRET).digest('hex').substring(0, 32); } export function formatNumber(num: number): string { if (num >= 1_000_000) { return (num / 1_000_000).toFixed(1).replace(/\.0$/, '') + 'M'; } if (num >= 1_000) { return (num / 1_000).toFixed(1).replace(/\.0$/, '') + 'K'; } return num.toString(); } export function formatDate(date: string | Date, options?: Intl.DateTimeFormatOptions): string { const d = typeof date === 'string' ? new Date(date) : date; return d.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric', ...options, }); } export function formatRelativeTime(date: string | Date): string { const d = typeof date === 'string' ? new Date(date) : date; const now = new Date(); const diffMs = now.getTime() - d.getTime(); const diffSecs = Math.floor(diffMs / 1000); const diffMins = Math.floor(diffSecs / 60); const diffHours = Math.floor(diffMins / 60); const diffDays = Math.floor(diffHours / 24); if (diffSecs < 60) return 'just now'; if (diffMins < 60) return `${diffMins}m ago`; if (diffHours < 24) return `${diffHours}h ago`; if (diffDays < 7) return `${diffDays}d ago`; if (diffDays < 30) return `${Math.floor(diffDays / 7)}w ago`; if (diffDays < 365) return `${Math.floor(diffDays / 30)}mo ago`; return `${Math.floor(diffDays / 365)}y ago`; } export function truncate(text: string, maxLength: number): string { if (text.length <= maxLength) return text; return text.substring(0, maxLength - 3) + '...'; } export function isValidWhatsAppChannelUrl(url: string): boolean { return config.whatsappChannelRegex.test(url); } export function extractWhatsAppChannelCode(url: string): string | null { const match = url.match(/chat\.whatsapp\.com\/([A-Za-z0-9]{22})/); return match ? match[1] : null; } export function sanitizeHtml(html: string): string { return html .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } export function getSortOptions(): Array<{ value: string; label: string }> { return [ { value: 'trending', label: 'Trending' }, { value: 'followers', label: 'Most Followers' }, { value: 'votes', label: 'Most Votes' }, { value: 'newest', label: 'Newest' }, { value: 'oldest', label: 'Oldest' }, { value: 'alphabetical', label: 'Alphabetical' }, { value: 'updated', label: 'Recently Updated' }, ]; } export function getSortField(sort: string): { field: string; order: 'asc' | 'desc' } { switch (sort) { case 'trending': return { field: 'voteCount', order: 'desc' }; case 'followers': return { field: 'followerCount', order: 'desc' }; case 'votes': return { field: 'voteCount', order: 'desc' }; case 'newest': return { field: 'createdAt', order: 'desc' }; case 'oldest': return { field: 'createdAt', order: 'asc' }; case 'alphabetical': return { field: 'name', order: 'asc' }; case 'updated': return { field: 'lastScrapedAt', order: 'desc' }; default: return { field: 'createdAt', order: 'desc' }; } } export function sleep(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)); } export function chunkArray(array: T[], size: number): T[][] { const chunks: T[][] = []; for (let i = 0; i < array.length; i += size) { chunks.push(array.slice(i, i + size)); } return chunks; }