File size: 3,953 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
import { z } from 'zod';
import { config } from '@config/index.js';

export const registerSchema = z.object({
  username: z.string()
    .min(3, 'Username must be at least 3 characters')
    .max(16, 'Username must not exceed 16 characters')
    .regex(/^[a-zA-Z0-9_-]+$/, 'Username can only contain letters, numbers, underscore and hyphen')
    .toLowerCase(),
  password: z.string()
    .min(8, 'Password must be at least 8 characters')
    .max(16, 'Password must not exceed 16 characters')
    .regex(/[A-Z]/, 'Password must contain at least one uppercase letter')
    .regex(/[a-z]/, 'Password must contain at least one lowercase letter')
    .regex(/[0-9]/, 'Password must contain at least one number')
    .regex(/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/, 'Password must contain at least one special character'),
  captchaToken: z.string().min(1, 'Captcha verification required'),
  acceptTerms: z.boolean().refine(v => v === true, 'You must accept the terms of service'),
});

export const loginSchema = z.object({
  username: z.string().min(1, 'Username is required').toLowerCase(),
  password: z.string().min(1, 'Password is required'),
  captchaToken: z.string().min(1, 'Captcha verification required'),
});

export const channelAddSchema = z.object({
  inviteLink: z.string().url('Invalid URL format').regex(config.whatsappChannelRegex, 'Must be a valid WhatsApp channel link'),
});

export const channelTagsSchema = z.object({
  tags: z.array(z.string().min(1).max(30).toLowerCase()).max(10, 'Maximum 10 tags allowed'),
});

export const profileUpdateSchema = z.object({
  email: z.string().email('Invalid email format').optional().or(z.literal('')),
  currentPassword: z.string().optional(),
  newPassword: z.string()
    .min(8, 'Password must be at least 8 characters')
    .max(16, 'Password must not exceed 16 characters')
    .regex(/[A-Z]/, 'Password must contain at least one uppercase letter')
    .regex(/[a-z]/, 'Password must contain at least one lowercase letter')
    .regex(/[0-9]/, 'Password must contain at least one number')
    .regex(/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/, 'Password must contain at least one special character')
    .optional(),
}).refine(data => data.currentPassword || !data.newPassword, {
  message: 'Current password required to change password',
  path: ['currentPassword'],
});

export const searchSchema = z.object({
  q: z.string().max(100).optional(),
  tag: z.string().max(50).optional(),
  sort: z.enum(['trending', 'followers', 'votes', 'newest', 'oldest', 'alpha', 'updated']).default('newest'),
  page: z.coerce.number().min(1).default(1),
  limit: z.coerce.number().min(1).max(100).default(20),
});

export const voteSchema = z.object({
  channelId: z.string().min(1, 'Channel ID required'),
});

export const adminUserSearchSchema = z.object({
  q: z.string().max(100).optional(),
  isAdmin: z.coerce.boolean().optional(),
  isBanned: z.coerce.boolean().optional(),
  page: z.coerce.number().min(1).default(1),
  limit: z.coerce.number().min(1).max(100).default(20),
});

export const adminChannelSearchSchema = z.object({
  q: z.string().max(100).optional(),
  status: z.enum(['pending', 'scraping', 'validating', 'published', 'rejected', 'banned']).optional(),
  isBanned: z.coerce.boolean().optional(),
  page: z.coerce.number().min(1).default(1),
  limit: z.coerce.number().min(1).max(100).default(20),
});

export const banSchema = z.object({
  type: z.enum(['user', 'channel', 'ip']),
  targetId: z.string().min(1),
  targetValue: z.string().min(1),
  reason: z.string().min(1, 'Reason required').max(500),
  expiresAt: z.string().datetime().optional(),
});

export function validateInput<T>(schema: z.ZodSchema<T>, data: unknown): { success: true; data: T } | { success: false; errors: z.ZodIssue[] } {
  const result = schema.safeParse(data);
  if (result.success) {
    return { success: true, data: result.data };
  }
  return { success: false, errors: result.error.issues };
}