/** * POST /api/messages/:instanceId/new-chat * Create or get a chat by phone number to start a new conversation */ import { query } from '../../../utils/database' import { baileysManager } from '../../../services/baileys/manager' import { randomUUID } from 'crypto' interface NewChatBody { phoneNumber: string } export default defineEventHandler(async (event) => { const username = getHeader(event, 'x-authentik-username') if (!username) { throw createError({ statusCode: 401, message: 'Unauthorized' }) } const instanceId = getRouterParam(event, 'instanceId') if (!instanceId) { throw createError({ statusCode: 400, message: 'Missing instanceId' }) } // Verify instance exists and is connected const socket = baileysManager.getSocket(instanceId) if (!socket) { throw createError({ statusCode: 400, message: 'Instance not connected' }) } const body = await readBody(event) if (!body.phoneNumber?.trim()) { throw createError({ statusCode: 400, message: 'Phone number is required' }) } // Clean phone number: remove spaces, dashes, parentheses, and + prefix const cleanNumber = body.phoneNumber.replace(/[\s\-\(\)\+]/g, '') // Validate it's a numeric string if (!/^\d+$/.test(cleanNumber)) { throw createError({ statusCode: 400, message: 'Invalid phone number format' }) } // Build WhatsApp JID (individual chat) const jid = `${cleanNumber}@s.whatsapp.net` try { // Check if chat already exists const existingChat = await query( `SELECT id, jid, name, is_group, unread_count, last_message_at, last_message_type, (SELECT COALESCE(content, caption) FROM messages m WHERE m.chat_id = chats.id ORDER BY timestamp DESC LIMIT 1) as last_message FROM chats WHERE instance_id = $1 AND jid = $2`, [instanceId, jid] ) if (existingChat.rows.length > 0) { // Chat exists, return it const chat = existingChat.rows[0] return { success: true, chat: { id: chat.id, jid: chat.jid, name: chat.name || cleanNumber, isGroup: chat.is_group, unreadCount: chat.unread_count || 0, lastMessage: chat.last_message, lastMessageAt: chat.last_message_at, lastMessageType: chat.last_message_type }, isNew: false } } // Chat doesn't exist, create it const chatId = randomUUID() // Try to get contact name from WhatsApp (optional, may fail) let contactName = cleanNumber try { // Check if number exists on WhatsApp using onWhatsApp const [exists] = await socket.onWhatsApp(jid) if (!exists?.exists) { throw createError({ statusCode: 400, message: 'Este número no está registrado en WhatsApp' }) } // Try to get the push name or contact name if (exists.notify) { contactName = exists.notify } } catch (e: any) { // If it's our validation error, rethrow if (e.statusCode === 400) { throw e } // Otherwise just use the number as name console.log('[NewChat] Could not verify WhatsApp status:', e.message) } // Insert new chat await query( `INSERT INTO chats (id, instance_id, jid, name, is_group, unread_count, created_at, updated_at) VALUES ($1, $2, $3, $4, false, 0, NOW(), NOW())`, [chatId, instanceId, jid, contactName] ) return { success: true, chat: { id: chatId, jid: jid, name: contactName, isGroup: false, unreadCount: 0, lastMessage: null, lastMessageAt: null, lastMessageType: null }, isNew: true } } catch (e: any) { // Rethrow HTTP errors if (e.statusCode) { throw e } console.error('[NewChat] Error creating chat:', e) throw createError({ statusCode: 500, message: `Error creating chat: ${e.message}` }) } })