@akson/chatsuite-sdk
Version:
Production-ready TypeScript SDK for ChatSuite - WhatsApp automation with built-in session management, message queuing, webhook server, and database sync
1 lines • 265 kB
Source Map (JSON)
{"version":3,"sources":["../src/client/BaseClient.ts","../src/resources/Sessions.ts","../src/resources/Messages.ts","../src/resources/Chats.ts","../src/resources/Contacts.ts","../src/resources/Groups.ts","../src/resources/Status.ts","../src/resources/Webhooks.ts","../src/resources/Admin.ts","../src/resources/Business.ts","../src/bot/BotFramework.ts","../src/queue/MessageQueue.ts","../src/adapters/DatabaseAdapter.ts","../src/polling/PollingService.ts","../src/session/SessionManager.ts","../src/types/index.ts","../src/metrics/MetricsCollector.ts","../src/client/WhatsAppClient.ts","../src/migration/MigrationHelper.ts","../src/index.ts"],"sourcesContent":["import axios, { AxiosInstance, AxiosRequestConfig, AxiosError } from 'axios';\nimport { ApiError, ClientOptions } from '../types';\n\nexport class BaseClient {\n protected axiosInstance: AxiosInstance;\n protected apiToken: string;\n protected baseUrl: string;\n\n constructor(options: ClientOptions) {\n this.apiToken = options.apiToken;\n this.baseUrl = options.baseUrl || 'https://api.chatsuite.com';\n\n this.axiosInstance = axios.create({\n baseURL: this.baseUrl,\n timeout: options.timeout || 30000,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiToken}`,\n ...options.headers,\n },\n });\n\n // Add request interceptor for auth\n this.axiosInstance.interceptors.request.use(\n (config) => {\n // Ensure auth header is always present\n if (!config.headers.Authorization) {\n config.headers.Authorization = `Bearer ${this.apiToken}`;\n }\n return config;\n },\n (error) => Promise.reject(error)\n );\n\n // Add response interceptor for error handling\n this.axiosInstance.interceptors.response.use(\n (response) => response,\n async (error: AxiosError) => {\n return Promise.reject(this.handleError(error));\n }\n );\n\n // Add retry logic if configured\n if (options.retryConfig) {\n this.setupRetryInterceptor(options.retryConfig);\n }\n }\n\n private setupRetryInterceptor(retryConfig: ClientOptions['retryConfig']) {\n this.axiosInstance.interceptors.response.use(\n undefined,\n async (error: AxiosError) => {\n const config = error.config as AxiosRequestConfig & { _retry?: number };\n \n if (!config || !retryConfig) {\n return Promise.reject(error);\n }\n\n config._retry = config._retry || 0;\n\n if (\n config._retry >= (retryConfig.retries || 3) ||\n (retryConfig.retryCondition && !retryConfig.retryCondition(error))\n ) {\n return Promise.reject(error);\n }\n\n config._retry += 1;\n\n // Wait before retrying\n const retryCount = config._retry || 1;\n await new Promise(resolve => \n setTimeout(resolve, retryConfig.retryDelay || 1000 * retryCount)\n );\n\n return this.axiosInstance(config);\n }\n );\n }\n\n private handleError(error: AxiosError): ApiError {\n const apiError = new Error() as ApiError;\n\n if (error.response) {\n // Server responded with error\n const responseData = error.response.data as any;\n apiError.message = responseData?.error || responseData?.message || error.message;\n apiError.status = error.response.status;\n apiError.code = responseData?.code;\n apiError.details = responseData;\n } else if (error.request) {\n // Request made but no response\n apiError.message = 'No response from server';\n apiError.code = 'NETWORK_ERROR';\n } else {\n // Request setup error\n apiError.message = error.message;\n apiError.code = 'REQUEST_ERROR';\n }\n\n apiError.name = 'WhatsAppApiError';\n return apiError;\n }\n\n protected async get<T>(path: string, config?: AxiosRequestConfig): Promise<T> {\n const response = await this.axiosInstance.get<T>(path, config);\n return response.data;\n }\n\n protected async post<T>(path: string, data?: any, config?: AxiosRequestConfig): Promise<T> {\n const response = await this.axiosInstance.post<T>(path, data, config);\n return response.data;\n }\n\n protected async put<T>(path: string, data?: any, config?: AxiosRequestConfig): Promise<T> {\n const response = await this.axiosInstance.put<T>(path, data, config);\n return response.data;\n }\n\n protected async delete<T>(path: string, config?: AxiosRequestConfig): Promise<T> {\n const response = await this.axiosInstance.delete<T>(path, config);\n return response.data;\n }\n\n protected async patch<T>(path: string, data?: any, config?: AxiosRequestConfig): Promise<T> {\n const response = await this.axiosInstance.patch<T>(path, data, config);\n return response.data;\n }\n\n /**\n * Update the API token\n */\n public setApiToken(token: string): void {\n this.apiToken = token;\n this.axiosInstance.defaults.headers.common['Authorization'] = `Bearer ${token}`;\n }\n\n /**\n * Get the current base URL\n */\n public getBaseUrl(): string {\n return this.baseUrl;\n }\n}","import { BaseClient } from '../client/BaseClient';\nimport {\n Session,\n CreateSessionRequest,\n UpdateSessionRequest,\n ApiResponse,\n} from '../types';\n\nexport class Sessions {\n constructor(private client: BaseClient) {}\n\n /**\n * List all sessions\n * @param environment - Filter by environment (optional)\n */\n async list(environment?: string): Promise<{ sessions: Session[]; count: number }> {\n const params = environment ? { environment } : undefined;\n const response = await this.client['get']<{\n success: boolean;\n sessions: Session[];\n count: number;\n }>('/api/sessions', { params });\n \n return {\n sessions: response.sessions,\n count: response.count,\n };\n }\n\n /**\n * Get session details\n * @param tel - Phone number\n */\n async get(tel: string): Promise<Session> {\n const response = await this.client['get']<{\n success: boolean;\n session: Session;\n }>(`/api/sessions/${encodeURIComponent(tel)}`);\n \n return response.session;\n }\n\n /**\n * Create a new session\n * @param data - Session creation data\n */\n async create(data: CreateSessionRequest): Promise<Session> {\n const response = await this.client['post']<{\n success: boolean;\n session: Session;\n }>('/api/sessions', data);\n \n return response.session;\n }\n\n /**\n * Update session details\n * @param tel - Phone number\n * @param data - Update data\n */\n async update(tel: string, data: UpdateSessionRequest): Promise<Session> {\n const response = await this.client['put']<{\n success: boolean;\n session: Session;\n }>(`/api/sessions/${encodeURIComponent(tel)}`, data);\n \n return response.session;\n }\n\n /**\n * Initialize session (start connection and generate QR code)\n * @param tel - Phone number\n */\n async initialize(tel: string): Promise<{ message: string }> {\n const response = await this.client['post']<ApiResponse<never>>(`/api/sessions/${encodeURIComponent(tel)}/init`);\n return { message: response.message || 'Session initialization started' };\n }\n\n\n /**\n * Reset session (disconnect and clear auth)\n * @param tel - Phone number\n */\n async reset(tel: string): Promise<{ message: string }> {\n const response = await this.client['post']<ApiResponse<never>>(`/api/sessions/${encodeURIComponent(tel)}/reset`);\n return { message: response.message || 'Session reset successfully' };\n }\n\n /**\n * Delete session permanently\n * @param tel - Phone number\n */\n async delete(tel: string): Promise<{ message: string }> {\n const response = await this.client['delete']<ApiResponse<never>>(`/api/sessions/${encodeURIComponent(tel)}`);\n return { message: response.message || 'Session deleted successfully' };\n }\n\n /**\n * Poll for session status (useful for checking QR code availability)\n * @param tel - Phone number\n * @param maxAttempts - Maximum polling attempts\n * @param interval - Polling interval in milliseconds\n */\n async pollForQR(\n tel: string,\n maxAttempts: number = 30,\n interval: number = 2000\n ): Promise<Session> {\n let attempts = 0;\n \n while (attempts < maxAttempts) {\n const session = await this.get(tel);\n \n if (session.qr || session.ready) {\n return session;\n }\n \n attempts++;\n if (attempts < maxAttempts) {\n await new Promise(resolve => setTimeout(resolve, interval));\n }\n }\n \n throw new Error('Timeout waiting for QR code');\n }\n\n /**\n * Wait for session to be ready (connected)\n * @param tel - Phone number\n * @param maxAttempts - Maximum polling attempts\n * @param interval - Polling interval in milliseconds\n */\n async waitForReady(\n tel: string,\n maxAttempts: number = 60,\n interval: number = 2000\n ): Promise<Session> {\n let attempts = 0;\n \n while (attempts < maxAttempts) {\n const session = await this.get(tel);\n \n if (session.ready) {\n return session;\n }\n \n attempts++;\n if (attempts < maxAttempts) {\n await new Promise(resolve => setTimeout(resolve, interval));\n }\n }\n \n throw new Error('Timeout waiting for session to be ready');\n }\n}","import { BaseClient } from '../client/BaseClient';\nimport {\n Message,\n SendMessageRequest,\n ListMessagesParams,\n InteractiveMessage,\n Poll,\n PollVote,\n} from '../types';\n\nexport class Messages {\n constructor(private client: BaseClient) {}\n\n /**\n * Send a text or media message\n * @param data - Message data\n */\n async send(data: SendMessageRequest): Promise<Message> {\n const response = await this.client['post']<{\n success: boolean;\n message: Message;\n }>('/api/messages/send', data);\n \n return response.message;\n }\n\n /**\n * Send a text message (convenience method)\n * @param tel - Sender phone number\n * @param to - Recipient ID\n * @param text - Message text\n * @param options - Additional options\n */\n async sendText(\n tel: string,\n to: string,\n text: string,\n options?: SendMessageRequest['options']\n ): Promise<Message> {\n return this.send({ tel, to, text, options });\n }\n\n /**\n * Send a media message (convenience method)\n * @param tel - Sender phone number\n * @param to - Recipient ID\n * @param media - Base64 encoded media\n * @param mimetype - Media MIME type\n * @param filename - Media filename\n * @param caption - Optional caption\n */\n async sendMedia(\n tel: string,\n to: string,\n media: string,\n mimetype: string,\n filename: string,\n caption?: string\n ): Promise<Message> {\n return this.send({ tel, to, media, mimetype, filename, caption });\n }\n\n /**\n * Send an interactive message (buttons or list)\n * @param tel - Sender phone number\n * @param to - Recipient ID\n * @param interactive - Interactive message data\n */\n async sendInteractive(\n tel: string,\n to: string,\n interactive: InteractiveMessage\n ): Promise<Message> {\n const response = await this.client['post']<{\n success: boolean;\n message: Message;\n }>('/api/messages/interactive', {\n tel,\n to,\n interactive,\n });\n \n return response.message;\n }\n\n /**\n * Send a poll\n * @param tel - Sender phone number\n * @param to - Recipient ID\n * @param poll - Poll data\n */\n async sendPoll(\n tel: string,\n to: string,\n poll: Poll\n ): Promise<Message> {\n const response = await this.client['post']<{\n success: boolean;\n message: Message;\n }>('/api/messages/poll', {\n tel,\n to,\n poll,\n });\n \n return response.message;\n }\n\n /**\n * Vote on a poll\n * @param tel - Voter phone number\n * @param vote - Vote data\n */\n async votePoll(tel: string, vote: PollVote): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>('/api/messages/poll/vote', {\n tel,\n ...vote,\n });\n }\n\n /**\n * List messages with filtering and pagination\n * @param params - Query parameters\n */\n async list(params?: ListMessagesParams): Promise<{\n messages: Message[];\n count: number;\n total: number;\n }> {\n const response = await this.client['get']<{\n success: boolean;\n messages: Message[];\n count: number;\n total: number;\n }>('/api/messages', { params });\n \n return {\n messages: response.messages,\n count: response.count,\n total: response.total,\n };\n }\n\n /**\n * Get a single message by ID\n * @param id - Message database ID\n */\n async get(id: string): Promise<Message> {\n const response = await this.client['get']<{\n success: boolean;\n message: Message;\n }>(`/api/messages/${id}`);\n \n return response.message;\n }\n\n /**\n * Download media from a message\n * @param id - Message database ID\n */\n async downloadMedia(id: string): Promise<{\n data: string;\n mimetype: string;\n filename: string;\n }> {\n const response = await this.client['get']<{\n success: boolean;\n data: string;\n mimetype: string;\n filename: string;\n }>(`/api/messages/${id}/media`);\n \n return {\n data: response.data,\n mimetype: response.mimetype,\n filename: response.filename,\n };\n }\n\n /**\n * Delete a message\n * @param tel - Phone number\n * @param messageId - WhatsApp message ID\n * @param forEveryone - Delete for everyone\n */\n async delete(\n tel: string,\n messageId: string,\n forEveryone: boolean = false\n ): Promise<{ success: boolean }> {\n return this.client['delete']<{ success: boolean }>('/api/messages', {\n data: { tel, messageId, forEveryone },\n });\n }\n\n /**\n * React to a message\n * @param tel - Phone number\n * @param messageId - Message to react to\n * @param emoji - Emoji reaction\n */\n async react(\n tel: string,\n messageId: string,\n emoji: string\n ): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>(`/api/messages/${messageId}/reactions`, {\n tel,\n emoji,\n });\n }\n\n /**\n * Remove a reaction from a message\n * @param tel - Phone number\n * @param messageId - Message to remove reaction from\n */\n async removeReaction(\n tel: string,\n messageId: string\n ): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>(`/api/messages/${messageId}/reactions/remove`, {\n tel,\n });\n }\n\n /**\n * Get reactions for a message\n * @param messageId - Message ID to get reactions for\n */\n async getReactions(messageId: string): Promise<{\n success: boolean;\n data: Array<{\n emoji: string;\n from: string;\n timestamp: number;\n }>;\n }> {\n return this.client['get']<{\n success: boolean;\n data: Array<{\n emoji: string;\n from: string;\n timestamp: number;\n }>;\n }>(`/api/messages/${messageId}/reactions`);\n }\n\n /**\n * Edit a message\n * @param tel - Phone number\n * @param messageId - Message to edit\n * @param newText - New message text\n */\n async edit(\n tel: string,\n messageId: string,\n newText: string\n ): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>('/api/messages/edit', {\n tel,\n messageId,\n newText,\n });\n }\n\n /**\n * Pin a message\n * @param tel - Phone number\n * @param messageId - Message to pin\n * @param duration - Pin duration in seconds (0 = forever)\n */\n async pin(\n tel: string,\n messageId: string,\n duration: number = 0\n ): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>('/api/messages/pin', {\n tel,\n messageId,\n duration,\n });\n }\n\n /**\n * Unpin a message\n * @param tel - Phone number\n * @param messageId - Message to unpin\n */\n async unpin(\n tel: string,\n messageId: string\n ): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>('/api/messages/unpin', {\n tel,\n messageId,\n });\n }\n\n /**\n * Star a message\n * @param tel - Phone number\n * @param messageId - Message to star\n */\n async star(\n tel: string,\n messageId: string\n ): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>('/api/messages/star', {\n tel,\n messageId,\n star: true,\n });\n }\n\n /**\n * Unstar a message\n * @param tel - Phone number\n * @param messageId - Message to unstar\n */\n async unstar(\n tel: string,\n messageId: string\n ): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>('/api/messages/star', {\n tel,\n messageId,\n star: false,\n });\n }\n\n /**\n * Forward messages\n * @param tel - Phone number\n * @param to - Recipient IDs\n * @param messageIds - Messages to forward\n */\n async forward(\n tel: string,\n to: string[],\n messageIds: string[]\n ): Promise<{ success: boolean; count: number }> {\n const response = await this.client['post']<{\n success: boolean;\n count: number;\n }>('/api/messages/forward', {\n tel,\n to,\n messageIds,\n });\n \n return response;\n }\n\n /**\n * Send typing indicator\n * @param tel - Phone number\n * @param to - Chat ID\n * @param typing - true for typing, false for paused\n */\n async sendTyping(\n tel: string,\n to: string,\n typing: boolean = true\n ): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>('/api/messages/typing', {\n tel,\n chatId: to,\n typing,\n });\n }\n\n /**\n * Mark messages as read\n * @param tel - Phone number\n * @param messageIds - Message IDs to mark as read\n */\n async markRead(\n tel: string,\n messageIds: string[]\n ): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>('/api/messages/read', {\n tel,\n messageIds,\n });\n }\n\n /**\n * Send voice note\n * @param tel - Phone number\n * @param to - Recipient ID\n * @param audioData - Base64 encoded audio data\n * @param mimetype - Audio mimetype\n * @param duration - Duration in seconds\n */\n async sendVoiceNote(\n tel: string,\n to: string,\n audioData: string,\n mimetype: string = 'audio/ogg; codecs=opus',\n duration?: number\n ): Promise<Message> {\n const response = await this.client['post']<{\n success: boolean;\n message: Message;\n }>('/api/messages/voice', {\n tel,\n to,\n audioData,\n mimetype,\n duration,\n });\n \n return response.message;\n }\n\n /**\n * Send location message\n * @param tel - Phone number\n * @param to - Recipient ID\n * @param latitude - Latitude coordinate\n * @param longitude - Longitude coordinate\n * @param name - Location name\n * @param address - Location address\n */\n async sendLocation(\n tel: string,\n to: string,\n latitude: number,\n longitude: number,\n name?: string,\n address?: string\n ): Promise<Message> {\n const response = await this.client['post']<{\n success: boolean;\n message: Message;\n }>('/api/messages/location', {\n tel,\n to,\n latitude,\n longitude,\n name,\n address,\n });\n \n return response.message;\n }\n\n /**\n * Send live location message\n * @param tel - Phone number\n * @param to - Recipient ID\n * @param latitude - Latitude coordinate\n * @param longitude - Longitude coordinate\n * @param duration - Sharing duration in seconds\n */\n async sendLiveLocation(\n tel: string,\n to: string,\n latitude: number,\n longitude: number,\n duration: number = 3600\n ): Promise<Message> {\n const response = await this.client['post']<{\n success: boolean;\n message: Message;\n }>('/api/messages/live-location', {\n tel,\n to,\n latitude,\n longitude,\n duration,\n });\n \n return response.message;\n }\n\n /**\n * Send buttons message\n * @param tel - Phone number\n * @param to - Recipient ID\n * @param text - Message text\n * @param buttons - Array of buttons\n * @param headerText - Optional header text\n * @param footerText - Optional footer text\n */\n async sendButtons(\n tel: string,\n to: string,\n text: string,\n buttons: Array<{\n id: string;\n text: string;\n type?: 'reply' | 'call' | 'url';\n data?: string;\n }>,\n headerText?: string,\n footerText?: string\n ): Promise<Message> {\n const response = await this.client['post']<{\n success: boolean;\n message: Message;\n }>('/api/messages/buttons', {\n tel,\n to,\n text,\n buttons,\n headerText,\n footerText,\n });\n \n return response.message;\n }\n\n /**\n * Send list message\n * @param tel - Phone number\n * @param to - Recipient ID\n * @param title - List title\n * @param buttonText - Button text\n * @param sections - List sections\n */\n async sendList(\n tel: string,\n to: string,\n title: string,\n buttonText: string,\n sections: Array<{\n title: string;\n rows: Array<{\n id: string;\n title: string;\n description?: string;\n }>;\n }>\n ): Promise<Message> {\n const response = await this.client['post']<{\n success: boolean;\n message: Message;\n }>('/api/messages/list', {\n tel,\n to,\n title,\n buttonText,\n sections,\n });\n \n return response.message;\n }\n\n /**\n * Send sticker message\n * @param tel - Phone number\n * @param to - Recipient ID\n * @param stickerData - Base64 encoded sticker data (WebP format)\n */\n async sendSticker(\n tel: string,\n to: string,\n stickerData: string\n ): Promise<Message> {\n const response = await this.client['post']<{\n success: boolean;\n message: Message;\n }>('/api/messages/sticker', {\n tel,\n to,\n stickerData,\n });\n \n return response.message;\n }\n\n /**\n * Send album/multiple media\n * @param tel - Phone number\n * @param to - Recipient ID\n * @param media - Array of media items\n * @param caption - Shared caption\n */\n async sendAlbum(\n tel: string,\n to: string,\n media: Array<{\n data: string;\n mimetype: string;\n filename?: string;\n caption?: string;\n }>,\n caption?: string\n ): Promise<Message> {\n const response = await this.client['post']<{\n success: boolean;\n message: Message;\n }>('/api/messages/album', {\n tel,\n to,\n media,\n caption,\n });\n \n return response.message;\n }\n}","import { BaseClient } from '../client/BaseClient';\nimport { ApiResponse } from '../types';\n\nexport interface Chat {\n _id: string;\n id: any;\n tel: string;\n name: string;\n isGroup: boolean;\n unreadCount: number;\n timestamp: number;\n archived: boolean;\n pinned: boolean;\n profilePicUrl?: string;\n isMuted: boolean;\n lastMessage?: {\n id: any;\n body: string;\n from: string;\n timestamp: number;\n type: string;\n fromMe: boolean;\n };\n groupMetadata?: {\n id: string;\n subject: string;\n desc?: string;\n owner?: string;\n participants: Array<{\n id: string;\n admin?: 'admin' | 'superadmin' | null;\n }>;\n };\n participants?: string[];\n description?: string;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface ChatFilters {\n tel?: string;\n groups?: boolean;\n unreadOnly?: boolean;\n archived?: boolean;\n search?: string;\n limit?: number;\n offset?: number;\n}\n\nexport interface ChatsResponse {\n success: boolean;\n data: {\n chats: Chat[];\n total: number;\n page: number;\n limit: number;\n };\n}\n\nexport interface ChatResponse {\n success: boolean;\n data: Chat;\n}\n\nexport class Chats {\n constructor(private client: BaseClient) {}\n\n /**\n * List all chats with optional filtering\n * @param params - Query parameters for filtering\n */\n async list(params?: ChatFilters): Promise<ChatsResponse> {\n return this.client['get']<ChatsResponse>('/api/chats', { params });\n }\n\n /**\n * Get a specific chat by ID\n * @param tel - Phone number\n * @param chatId - Chat ID\n */\n async get(tel: string, chatId: string): Promise<ChatResponse> {\n const response = await this.client['get']<ChatResponse>(\n `/api/chats/${encodeURIComponent(chatId)}`,\n { params: { tel } }\n );\n return response;\n }\n\n /**\n * Mark chat as read\n * @param tel - Phone number\n * @param chatId - Chat ID\n */\n async markAsRead(tel: string, chatId: string): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>(\n `/api/chats/${encodeURIComponent(chatId)}/read`,\n { tel }\n );\n }\n\n /**\n * Send typing indicator to chat\n * @param tel - Phone number\n * @param chatId - Chat ID\n */\n async sendTyping(tel: string, chatId: string): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>(\n `/api/chats/${encodeURIComponent(chatId)}/typing`,\n { tel }\n );\n }\n\n /**\n * Archive or unarchive a chat\n * @param tel - Phone number\n * @param chatId - Chat ID\n * @param archived - Archive status\n */\n async archive(tel: string, chatId: string, archived: boolean = true): Promise<{ success: boolean }> {\n return this.client['patch']<{ success: boolean }>(\n `/api/chats/${encodeURIComponent(chatId)}`,\n { tel, archived }\n );\n }\n\n /**\n * Pin or unpin a chat\n * @param tel - Phone number\n * @param chatId - Chat ID\n * @param pinned - Pin status\n */\n async pin(tel: string, chatId: string, pinned: boolean = true): Promise<{ success: boolean }> {\n return this.client['patch']<{ success: boolean }>(\n `/api/chats/${encodeURIComponent(chatId)}`,\n { tel, pinned }\n );\n }\n\n /**\n * Mute or unmute a chat\n * @param tel - Phone number\n * @param chatId - Chat ID\n * @param muted - Mute status\n */\n async mute(tel: string, chatId: string, muted: boolean = true): Promise<{ success: boolean }> {\n return this.client['patch']<{ success: boolean }>(\n `/api/chats/${encodeURIComponent(chatId)}`,\n { tel, muted }\n );\n }\n\n /**\n * Clear chat history\n * @param tel - Phone number\n * @param chatId - Chat ID\n */\n async clearHistory(tel: string, chatId: string): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>(\n `/api/chats/${encodeURIComponent(chatId)}/clear`,\n { tel }\n );\n }\n\n /**\n * Update multiple chat properties at once\n * @param tel - Phone number\n * @param chatId - Chat ID\n * @param updates - Properties to update\n */\n async update(\n tel: string,\n chatId: string,\n updates: {\n archived?: boolean;\n pinned?: boolean;\n muted?: boolean;\n }\n ): Promise<{ success: boolean }> {\n return this.client['patch']<{ success: boolean }>(\n `/api/chats/${encodeURIComponent(chatId)}`,\n { tel, ...updates }\n );\n }\n\n /**\n * Get group chats only\n * @param tel - Phone number\n * @param params - Additional query parameters\n */\n async getGroups(tel: string, params?: Omit<ChatFilters, 'tel' | 'groups'>): Promise<ChatsResponse> {\n return this.list({ tel, groups: true, ...params });\n }\n\n /**\n * Get individual chats only\n * @param tel - Phone number\n * @param params - Additional query parameters\n */\n async getIndividual(tel: string, params?: Omit<ChatFilters, 'tel' | 'groups'>): Promise<ChatsResponse> {\n return this.list({ tel, groups: false, ...params });\n }\n\n /**\n * Get unread chats only\n * @param tel - Phone number\n * @param params - Additional query parameters\n */\n async getUnread(tel: string, params?: Omit<ChatFilters, 'tel' | 'unreadOnly'>): Promise<ChatsResponse> {\n return this.list({ tel, unreadOnly: true, ...params });\n }\n\n /**\n * Get archived chats\n * @param tel - Phone number\n * @param params - Additional query parameters\n */\n async getArchived(tel: string, params?: Omit<ChatFilters, 'tel' | 'archived'>): Promise<ChatsResponse> {\n return this.list({ tel, archived: true, ...params });\n }\n\n /**\n * Search chats by name or content\n * @param tel - Phone number\n * @param query - Search query\n * @param params - Additional query parameters\n */\n async search(tel: string, query: string, params?: Omit<ChatFilters, 'tel' | 'search'>): Promise<ChatsResponse> {\n return this.list({ tel, search: query, ...params });\n }\n}","import { BaseClient } from '../client/BaseClient';\nimport { Contact, ContactsResponse } from '../types';\n\nexport class Contacts {\n constructor(private client: BaseClient) {}\n\n /**\n * List all contacts\n * @param tel - Phone number\n * @param search - Optional search query\n */\n async list(tel: string, search?: string): Promise<Contact[]> {\n const params = search ? { search } : undefined;\n const response = await this.client['get']<ContactsResponse>(\n `/api/contacts/${encodeURIComponent(tel)}`,\n { params }\n );\n \n return response.contacts;\n }\n\n /**\n * Get contact details\n * @param tel - Phone number\n * @param contactId - Contact ID\n */\n async get(tel: string, contactId: string): Promise<Contact> {\n const response = await this.client['get']<{\n success: boolean;\n contact: Contact;\n }>(`/api/contacts/${encodeURIComponent(tel)}/${encodeURIComponent(contactId)}`);\n \n return response.contact;\n }\n\n /**\n * Check if numbers are registered on WhatsApp\n * @param tel - Phone number\n * @param numbers - Array of phone numbers to check\n */\n async checkRegistered(\n tel: string,\n numbers: string[]\n ): Promise<{ [number: string]: boolean }> {\n const response = await this.client['post']<{\n success: boolean;\n results: { [number: string]: boolean };\n }>('/api/contacts/check', {\n tel,\n numbers,\n });\n \n return response.results;\n }\n\n /**\n * Get contact profile picture\n * @param tel - Phone number\n * @param contactId - Contact ID\n */\n async getProfilePicture(\n tel: string,\n contactId: string\n ): Promise<{ url: string }> {\n const response = await this.client['get']<{\n success: boolean;\n url: string;\n }>(`/api/contacts/${encodeURIComponent(tel)}/${encodeURIComponent(contactId)}/picture`);\n \n return { url: response.url };\n }\n\n /**\n * Get contact status/about\n * @param tel - Phone number\n * @param contactId - Contact ID\n */\n async getStatus(\n tel: string,\n contactId: string\n ): Promise<{ status: string }> {\n const response = await this.client['get']<{\n success: boolean;\n status: string;\n }>(`/api/contacts/${encodeURIComponent(tel)}/${encodeURIComponent(contactId)}/status`);\n \n return { status: response.status };\n }\n\n /**\n * Block a contact\n * @param tel - Phone number\n * @param contactId - Contact ID to block\n */\n async block(tel: string, contactId: string): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>('/api/contacts/block', {\n tel,\n contactId,\n });\n }\n\n /**\n * Unblock a contact\n * @param tel - Phone number\n * @param contactId - Contact ID to unblock\n */\n async unblock(tel: string, contactId: string): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>('/api/contacts/unblock', {\n tel,\n contactId,\n });\n }\n\n /**\n * Get blocked contacts\n * @param tel - Phone number\n */\n async getBlocked(tel: string): Promise<string[]> {\n const response = await this.client['get']<{\n success: boolean;\n blockedContacts: string[];\n }>(`/api/contacts/${encodeURIComponent(tel)}/blocked`);\n \n return response.blockedContacts;\n }\n\n /**\n * Get business profile of a contact\n * @param tel - Phone number\n * @param contactId - Business contact ID\n */\n async getBusinessProfile(\n tel: string,\n contactId: string\n ): Promise<any> {\n const response = await this.client['get']<{\n success: boolean;\n profile: any;\n }>(`/api/contacts/${encodeURIComponent(tel)}/${encodeURIComponent(contactId)}/business`);\n \n return response.profile;\n }\n}","import { BaseClient } from '../client/BaseClient';\nimport {\n Group,\n CreateGroupRequest,\n UpdateGroupRequest,\n} from '../types';\n\nexport class Groups {\n constructor(private client: BaseClient) {}\n\n /**\n * List all groups\n * @param tel - Phone number\n */\n async list(tel: string): Promise<Group[]> {\n const response = await this.client['get']<{\n success: boolean;\n groups: Group[];\n }>(`/api/groups/${encodeURIComponent(tel)}`);\n \n return response.groups;\n }\n\n /**\n * Get group details\n * @param tel - Phone number\n * @param groupId - Group ID\n */\n async get(tel: string, groupId: string): Promise<Group> {\n const response = await this.client['get']<{\n success: boolean;\n group: Group;\n }>(`/api/groups/${encodeURIComponent(tel)}/${encodeURIComponent(groupId)}`);\n \n return response.group;\n }\n\n /**\n * Create a new group\n * @param data - Group creation data\n */\n async create(data: CreateGroupRequest): Promise<Group> {\n const response = await this.client['post']<{\n success: boolean;\n group: Group;\n }>('/api/groups', data);\n \n return response.group;\n }\n\n /**\n * Update group details\n * @param tel - Phone number\n * @param groupId - Group ID\n * @param data - Update data\n */\n async update(\n tel: string,\n groupId: string,\n data: UpdateGroupRequest\n ): Promise<{ success: boolean }> {\n return this.client['put']<{ success: boolean }>(\n `/api/groups/${encodeURIComponent(tel)}/${encodeURIComponent(groupId)}`,\n data\n );\n }\n\n /**\n * Leave a group\n * @param tel - Phone number\n * @param groupId - Group ID\n */\n async leave(tel: string, groupId: string): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>(\n `/api/groups/${encodeURIComponent(tel)}/${encodeURIComponent(groupId)}/leave`\n );\n }\n\n /**\n * Add participants to a group\n * @param tel - Phone number\n * @param groupId - Group ID\n * @param participants - Array of participant IDs\n */\n async addParticipants(\n tel: string,\n groupId: string,\n participants: string[]\n ): Promise<{ success: boolean; added: string[]; failed: string[] }> {\n return this.client['post']<{\n success: boolean;\n added: string[];\n failed: string[];\n }>(`/api/groups/${encodeURIComponent(tel)}/${encodeURIComponent(groupId)}/participants`, {\n participants,\n });\n }\n\n /**\n * Remove participants from a group\n * @param tel - Phone number\n * @param groupId - Group ID\n * @param participants - Array of participant IDs\n */\n async removeParticipants(\n tel: string,\n groupId: string,\n participants: string[]\n ): Promise<{ success: boolean }> {\n return this.client['delete']<{ success: boolean }>(\n `/api/groups/${encodeURIComponent(tel)}/${encodeURIComponent(groupId)}/participants`,\n { data: { participants } }\n );\n }\n\n /**\n * Promote participants to admin\n * @param tel - Phone number\n * @param groupId - Group ID\n * @param participants - Array of participant IDs\n */\n async promoteParticipants(\n tel: string,\n groupId: string,\n participants: string[]\n ): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>(\n `/api/groups/${encodeURIComponent(tel)}/${encodeURIComponent(groupId)}/promote`,\n { participants }\n );\n }\n\n /**\n * Demote participants from admin\n * @param tel - Phone number\n * @param groupId - Group ID\n * @param participants - Array of participant IDs\n */\n async demoteParticipants(\n tel: string,\n groupId: string,\n participants: string[]\n ): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>(\n `/api/groups/${encodeURIComponent(tel)}/${encodeURIComponent(groupId)}/demote`,\n { participants }\n );\n }\n\n /**\n * Get group invite link\n * @param tel - Phone number\n * @param groupId - Group ID\n */\n async getInviteLink(\n tel: string,\n groupId: string\n ): Promise<{ code: string; url: string }> {\n const response = await this.client['get']<{\n success: boolean;\n code: string;\n url: string;\n }>(`/api/groups/${encodeURIComponent(tel)}/${encodeURIComponent(groupId)}/invite`);\n \n return { code: response.code, url: response.url };\n }\n\n /**\n * Revoke group invite link\n * @param tel - Phone number\n * @param groupId - Group ID\n */\n async revokeInviteLink(\n tel: string,\n groupId: string\n ): Promise<{ code: string; url: string }> {\n const response = await this.client['post']<{\n success: boolean;\n code: string;\n url: string;\n }>(`/api/groups/${encodeURIComponent(tel)}/${encodeURIComponent(groupId)}/invite/revoke`);\n \n return { code: response.code, url: response.url };\n }\n\n /**\n * Accept group invite\n * @param tel - Phone number\n * @param inviteCode - Invite code\n */\n async acceptInvite(\n tel: string,\n inviteCode: string\n ): Promise<{ groupId: string }> {\n const response = await this.client['post']<{\n success: boolean;\n groupId: string;\n }>('/api/groups/join', { tel, inviteCode });\n \n return { groupId: response.groupId };\n }\n\n /**\n * Set group profile picture\n * @param tel - Phone number\n * @param groupId - Group ID\n * @param image - Base64 encoded image\n */\n async setProfilePicture(\n tel: string,\n groupId: string,\n image: string\n ): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>(\n `/api/groups/${encodeURIComponent(tel)}/${encodeURIComponent(groupId)}/picture`,\n { image }\n );\n }\n\n /**\n * Remove group profile picture\n * @param tel - Phone number\n * @param groupId - Group ID\n */\n async removeProfilePicture(\n tel: string,\n groupId: string\n ): Promise<{ success: boolean }> {\n return this.client['delete']<{ success: boolean }>(\n `/api/groups/${encodeURIComponent(tel)}/${encodeURIComponent(groupId)}/picture`\n );\n }\n\n /**\n * Get group members who have read a message\n * @param tel - Phone number\n * @param groupId - Group ID\n * @param messageId - Message ID\n */\n async getMessageReaders(\n tel: string,\n groupId: string,\n messageId: string\n ): Promise<string[]> {\n const response = await this.client['get']<{\n success: boolean;\n readers: string[];\n }>(`/api/groups/${encodeURIComponent(tel)}/${encodeURIComponent(groupId)}/readers/${messageId}`);\n \n return response.readers;\n }\n\n /**\n * Toggle group settings\n * @param tel - Phone number\n * @param groupId - Group ID\n * @param setting - Setting to toggle\n * @param value - New value\n */\n async toggleSetting(\n tel: string,\n groupId: string,\n setting: 'announce' | 'restrict' | 'locked',\n value: boolean\n ): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>(\n `/api/groups/${encodeURIComponent(tel)}/${encodeURIComponent(groupId)}/settings`,\n { [setting]: value }\n );\n }\n}","import { BaseClient } from '../client/BaseClient';\nimport { Status as StatusType, StatusUpdate } from '../types';\n\nexport class Status {\n constructor(private client: BaseClient) {}\n\n /**\n * Get all status updates\n * @param tel - Phone number\n */\n async list(tel: string): Promise<StatusType[]> {\n const response = await this.client['get']<{\n success: boolean;\n statuses: StatusType[];\n }>(`/api/status/${encodeURIComponent(tel)}`);\n \n return response.statuses;\n }\n\n /**\n * Get status updates from a specific contact\n * @param tel - Phone number\n * @param contactId - Contact ID\n */\n async getContactStatus(\n tel: string,\n contactId: string\n ): Promise<StatusType[]> {\n const response = await this.client['get']<{\n success: boolean;\n statuses: StatusType[];\n }>(`/api/status/${encodeURIComponent(tel)}/${encodeURIComponent(contactId)}`);\n \n return response.statuses;\n }\n\n /**\n * Post a new status update\n * @param data - Status update data\n */\n async post(data: StatusUpdate): Promise<{ id: string }> {\n const response = await this.client['post']<{\n success: boolean;\n id: string;\n }>('/api/status', data);\n \n return { id: response.id };\n }\n\n /**\n * Post a text status\n * @param tel - Phone number\n * @param content - Status text\n * @param backgroundColor - Background color (hex)\n * @param font - Font style (0-5)\n */\n async postText(\n tel: string,\n content: string,\n backgroundColor?: string,\n font?: number\n ): Promise<{ id: string }> {\n return this.post({\n tel,\n type: 'text',\n content,\n backgroundColor,\n font,\n });\n }\n\n /**\n * Post an image status\n * @param tel - Phone number\n * @param media - Base64 encoded image\n * @param caption - Optional caption\n */\n async postImage(\n tel: string,\n media: string,\n caption?: string\n ): Promise<{ id: string }> {\n return this.post({\n tel,\n type: 'image',\n media,\n caption,\n });\n }\n\n /**\n * Post a video status\n * @param tel - Phone number\n * @param media - Base64 encoded video\n * @param caption - Optional caption\n */\n async postVideo(\n tel: string,\n media: string,\n caption?: string\n ): Promise<{ id: string }> {\n return this.post({\n tel,\n type: 'video',\n media,\n caption,\n });\n }\n\n /**\n * Delete a status update\n * @param tel - Phone number\n * @param statusId - Status ID to delete\n */\n async delete(\n tel: string,\n statusId: string\n ): Promise<{ success: boolean }> {\n return this.client['delete']<{ success: boolean }>(\n `/api/status/${encodeURIComponent(tel)}/${statusId}`\n );\n }\n\n /**\n * Mark status as seen\n * @param tel - Phone number\n * @param statusId - Status ID\n */\n async markSeen(\n tel: string,\n statusId: string\n ): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>('/api/status/seen', {\n tel,\n statusId,\n });\n }\n\n /**\n * Get status privacy settings\n * @param tel - Phone number\n */\n async getPrivacySettings(tel: string): Promise<{\n blacklist: string[];\n whitelist: string[];\n mode: 'all' | 'contacts' | 'contact_blacklist' | 'selected';\n }> {\n const response = await this.client['get']<{\n success: boolean;\n privacy: {\n blacklist: string[];\n whitelist: string[];\n mode: 'all' | 'contacts' | 'contact_blacklist' | 'selected';\n };\n }>(`/api/status/${encodeURIComponent(tel)}/privacy`);\n \n return response.privacy;\n }\n\n /**\n * Update status privacy settings\n * @param tel - Phone number\n * @param settings - Privacy settings\n */\n async updatePrivacySettings(\n tel: string,\n settings: {\n mode?: 'all' | 'contacts' | 'contact_blacklist' | 'selected';\n blacklist?: string[];\n whitelist?: string[];\n }\n ): Promise<{ success: boolean }> {\n return this.client['post']<{ success: boolean }>(\n `/api/status/${encodeURIComponent(tel)}/privacy`,\n settings\n );\n }\n\n /**\n * Download status media\n * @param tel - Phone number\n * @param statusId - Status ID\n */\n async downloadMedia(\n tel: string,\n statusId: string\n ): Promise<{\n data: string;\n mimetype: string;\n filename: string;\n }> {\n const response = await this.client['get']<{\n success: boolean;\n data: string;\n mimetype: string;\n filename: string;\n }>(`/api/status/${encodeURIComponent(tel)}/${statusId}/media`);\n \n return {\n data: response.data,\n mimetype: response.mimetype,\n filename: response.filename,\n };\n }\n\n /**\n * Get who viewed a status\n * @param tel - Phone number\n * @param statusId - Status ID\n */\n async getViewers(\n tel: string,\n statusId: string\n ): Promise<string[]> {\n const response = await this.client['get']<{\n success: boolean;\n viewers: string[];\n }>(`/api/status/${encodeURIComponent(tel)}/${statusId}/viewers`);\n \n return response.viewers;\n }\n}","import { BaseClient } from '../client/BaseClient';\nimport {\n Webhook,\n CreateWebhookRequest,\n UpdateWebhookRequest,\n WebhookTestResult,\n ApiResponse,\n} from '../types';\n\nexport class Webhooks {\n constructor(private client: BaseClient) {}\n\n /**\n * Get all webhooks for a session\n * @param tel - Phone number\n */\n async list(tel: string): Promise<Webhook[]> {\n const response = await this.client['get']<{\n success: boolean;\n data: Webhook[];\n }>(`/api/sessions/${encodeURIComponent(tel)}/webhooks`);\n \n return response.data;\n }\n\n /**\n * Get webhook details\n * @param tel - Phone number\n * @param webhookId - Webhook ID\n */\n async get(tel: string, webhookId: string): Promise<Webhook> {\n const response = await this.client['get']<{\n success: boolean;\n data: Webhook;\n }>(`/api/sessions/${encodeURIComponent(tel)}/webhooks/${webhookId}`);\n \n return response.data;\n }\n\n /**\n * Create a new webhook for a session\n * @param tel - Phone number\n * @param data - Webhook creation data\n */\n async create(tel: string, data: Omit<CreateWebhookRequest, 'tel'>): Promise<Webhook & { secret: string }> {\n const response = await this.client['post']<{\n success: boolean;\n data: Webhook & { secret: string };\n }>(`/api/sessions/${encodeURIComponent(tel)}/webhooks`, {\n ...data,\n tel,\n });\n \n return response.data;\n }\n\n /**\n * Update webhook details\n * @param tel - Phone number\n * @param webhookId - Webhook ID\n * @param data - Update data\n */\n async update(\n tel: string, \n webhookId: string, \n data: Omit<UpdateWebhookRequest, 'tel' | 'webhookId'>\n ): Promise<Webhook> {\n const response = await this.client['put']<{\n success: boolean;\n data: Webhook;\n }>(`/api/sessions/${encodeURIComponent(tel)}/webhooks/${webhookId}`, data);\n \n return response.data;\n }\n\n /**\n * Delete a webhook\n * @param tel - Phone number\n * @param webhookId - Webhook ID\n */\n async delete(tel: string, webhookId: string): Promise<{ message: string }> {\n const response = await this.client['delete']<ApiResponse<never>>(\n `/api/sessions/${encodeURIComponent(tel)}/webhooks/${webhookId}`\n );\n return { message: response.message || 'Webhook deleted successfully' };\n }\n\n /**\n * Test a webhook\n * @param tel - Phone number\n * @param webhookId - Webhook ID\n */\n async test(tel: string, webhookId: string): Promise<WebhookTestResult> {\n return this.client['post']<WebhookTestResult>(\n `/api/sessions/${encodeURIComponent(tel)}/webhooks/${webhookId}/test`\n );\n }\n\n /**\n * Rotate webhook secret\n * @param tel - Phone number\n * @param webhookId - Webhook ID\n */\n async rotateSecret(tel: string, webhookId: string): Promise<{\n id: string;\n name: string;\n secret: string;\n }> {\n const response = await this.client['post']<{\n success: boolean;\n data: { id: string; name: string; secret: string };\n }>(`/api/sessions/${encodeURIComponent(tel)}/webhooks/${webhookId}/rotate-secret`);\n \n return response.data;\n }\n\n /**\n * Get webhook logs and statistics\n * @param tel - Phone number\n * @param webhookId - Webhook ID\n */\n async getLogs(tel: string, webhookId: string): Promise<{\n name: string;\n url: string;\n statistics: Webhook['statistics'];\n }> {\n const response = await this.client['get']<{\n success: boolean;\n data: {\n name: string;\n url: string;\n statistics: Webhook['statistics'];\n };\n }>(`/api/sessions/${encodeURIComponent(tel)}/webhooks/${webhookId}/logs`);\n \n return response.data;\n }\n\n /**\n * Toggle webhook active status\n * @param tel - Phone number\n * @param webhookId - Webhook ID\n * @param active - Active status\n */\n async toggleActive(tel: string, webhookId: string, active: boolean): Promise<Webhook> {\n return this.update(tel