Feat: Agregar botón para iniciar conversación con número nuevo
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m11s
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m11s
- Nuevo endpoint POST /api/messages/:instanceId/new-chat - Valida que el número esté registrado en WhatsApp - Crea el chat en la DB si no existe - Modal en UI para ingresar número de teléfono - Botón verde "+" junto a la barra de búsqueda
This commit is contained in:
138
server/api/messages/[instanceId]/new-chat.post.ts
Normal file
138
server/api/messages/[instanceId]/new-chat.post.ts
Normal file
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* 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<NewChatBody>(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}`
|
||||
})
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user