Skip to main content
Glama
palhamel
by palhamel
validation.ts6.65 kB
/** * Phone number validation utilities */ export const validatePhoneNumber = (phoneNumber: string): { isValid: boolean; error?: string } => { // Remove all whitespace and special characters except + const cleanNumber = phoneNumber.replace(/[\s\-\(\)\.]/g, ''); // Check if it's empty if (!cleanNumber) { return { isValid: false, error: 'Phone number is required' }; } // Block placeholder/test numbers that AI assistants commonly use const blockedNumbers = [ '+46701234567', '+46700000000', '+1234567890', '+46000000000' ]; if (blockedNumbers.includes(cleanNumber)) { return { isValid: false, error: 'Please provide a real phone number - test/placeholder numbers are not allowed' }; } // Check if it starts with + if (!cleanNumber.startsWith('+')) { return { isValid: false, error: 'Phone number must include country code (e.g., +46XXXXXXXXX)' }; } // Check length (international numbers are typically 7-15 digits + country code) if (cleanNumber.length < 8 || cleanNumber.length > 16) { return { isValid: false, error: 'Phone number length is invalid' }; } // Check if it contains only digits after the + const digitsOnly = cleanNumber.slice(1); if (!/^\d+$/.test(digitsOnly)) { return { isValid: false, error: 'Phone number can only contain digits after country code' }; } // Specific validation for Swedish numbers if (cleanNumber.startsWith('+46')) { const swedishNumber = cleanNumber.slice(3); // Remove +46 if (swedishNumber.length !== 9 && swedishNumber.length !== 8) { return { isValid: false, error: 'Swedish phone numbers should be 8-9 digits after +46' }; } } return { isValid: true }; }; /** * SMS message content validation with proper encoding considerations */ export const validateSmsMessage = (message: string): { isValid: boolean; error?: string; info?: string; warning?: string } => { if (!message || message.trim().length === 0) { return { isValid: false, error: 'Message content is required' }; } const trimmedMessage = message.trim(); // Check if message contains non-GSM characters (emojis, special unicode) const gsmChars = /^[A-Za-z0-9\s@£$¥èéùìòÇØøÅåÉæÆß\^{}\[~\]|€\n\r\f\\]*$/; const isGsmEncoding = gsmChars.test(trimmedMessage); let maxSingleLength: number; let maxMultipartLength: number; let segmentLength: number; if (isGsmEncoding) { // GSM 03.38 encoding (standard SMS) maxSingleLength = 160; segmentLength = 153; maxMultipartLength = 1530; // 10 segments max for safety } else { // UTF-16 encoding (contains emojis/unicode) maxSingleLength = 70; segmentLength = 67; maxMultipartLength = 670; // 10 segments max for safety } // Check reasonable maximum length (prevent accidental bulk/long messages) if (trimmedMessage.length > maxMultipartLength) { return { isValid: false, error: `Message too long (max ${maxMultipartLength} chars). This appears to be bulk content - use dedicated bulk SMS services instead.` }; } // Calculate segments and provide info let segments: number; let info = ''; let warning = ''; if (trimmedMessage.length <= maxSingleLength) { segments = 1; info = `1 SMS segment (${isGsmEncoding ? 'GSM' : 'Unicode'} encoding)`; } else { segments = Math.ceil(trimmedMessage.length / segmentLength); info = `${segments} SMS segments (${isGsmEncoding ? 'GSM' : 'Unicode'} encoding)`; // Add warnings for expensive multi-part messages if (segments >= 3) { warning = `⚠️ Multi-part SMS will cost ${segments}x normal price`; } if (!isGsmEncoding && segments >= 2) { warning = `⚠️ Unicode SMS is more expensive and uses ${segments} segments`; } } return { isValid: true, info, warning: warning || undefined }; }; /** * Sender ID validation (from field) with responsible usage checks */ export const validateSenderId = (senderId: string): { isValid: boolean; error?: string; warning?: string } => { if (!senderId) { return { isValid: true }; // Sender ID is optional } const trimmed = senderId.trim(); // Check if it's a phone number if (trimmed.startsWith('+')) { const phoneValidation = validatePhoneNumber(trimmed); if (!phoneValidation.isValid) { return phoneValidation; } // Add warning about using unverified phone numbers return { isValid: true, warning: 'Using phone numbers as sender - ensure you can receive replies and have permission to use this number' }; } // Check if it's an alphanumeric sender ID if (trimmed.length > 11) { return { isValid: false, error: 'Alphanumeric sender ID must be 11 characters or less' }; } // Check if sender ID starts with a letter (46elks requirement) if (!/^[a-zA-Z]/.test(trimmed)) { return { isValid: false, error: 'Alphanumeric sender ID must start with a letter (46elks requirement)' }; } // Check for valid characters in alphanumeric sender ID if (!/^[a-zA-Z0-9]+$/.test(trimmed)) { return { isValid: false, error: 'Sender ID can only contain letters and numbers (no spaces)' }; } // Check for potentially problematic sender IDs const suspiciousSenders = [ 'BANK', 'POLICE', 'GOVERNMENT', 'OFFICIAL', 'URGENT', 'WINNER', 'PRIZE', 'SECURITY', 'VERIFY', 'CONFIRM', 'ALERT', 'WARNING' ]; if (suspiciousSenders.some(suspicious => trimmed.toUpperCase().includes(suspicious))) { return { isValid: false, error: 'Sender ID appears to impersonate official entities - use your own business/service name' }; } return { isValid: true }; }; /** * Validate message limit parameter */ export const validateMessageLimit = (limit: number): { isValid: boolean; error?: string } => { if (!Number.isInteger(limit)) { return { isValid: false, error: 'Limit must be an integer' }; } if (limit < 1) { return { isValid: false, error: 'Limit must be at least 1' }; } if (limit > 100) { return { isValid: false, error: 'Limit cannot exceed 100' }; } return { isValid: true }; }; /** * Validate direction parameter */ export const validateDirection = (direction: string): { isValid: boolean; error?: string } => { const validDirections = ['inbound', 'outbound', 'both']; if (!validDirections.includes(direction)) { return { isValid: false, error: `Direction must be one of: ${validDirections.join(', ')}` }; } return { isValid: true }; };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/palhamel/46elks-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server