Spaces:
Build error
Build error
File size: 3,623 Bytes
ef73937 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | 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, '"')
.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<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
export function chunkArray<T>(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;
} |