Skip to content

Commit d6262ca

Browse files
committed
fix(mysql): compatibilidade da coluna lid e queries RAW
1 parent cd800f2 commit d6262ca

File tree

5 files changed

+343
-144
lines changed

5 files changed

+343
-144
lines changed

prisma/mysql-migrations/20250918183910_add_kafka_integration/migration.sql

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,7 @@ ALTER TABLE `IntegrationSession` MODIFY `createdAt` TIMESTAMP NULL DEFAULT CURRE
131131
MODIFY `updatedAt` TIMESTAMP NOT NULL;
132132

133133
-- AlterTable
134-
ALTER TABLE `IsOnWhatsapp` DROP COLUMN `lid`,
135-
MODIFY `createdAt` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
134+
ALTER TABLE `IsOnWhatsapp` MODIFY `createdAt` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
136135
MODIFY `updatedAt` TIMESTAMP NOT NULL;
137136

138137
-- AlterTable

prisma/mysql-schema.prisma

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,7 @@ model IsOnWhatsapp {
655655
id String @id @default(cuid())
656656
remoteJid String @unique @db.VarChar(100)
657657
jidOptions String
658+
lid String? @db.VarChar(100)
658659
createdAt DateTime @default(dbgenerated("CURRENT_TIMESTAMP")) @db.Timestamp
659660
updatedAt DateTime @updatedAt @db.Timestamp
660661
}

src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

Lines changed: 172 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -522,12 +522,27 @@ export class BaileysStartupService extends ChannelStartupService {
522522

523523
private async getMessage(key: proto.IMessageKey, full = false) {
524524
try {
525-
// Use raw SQL to avoid JSON path issues
526-
const webMessageInfo = (await this.prismaRepository.$queryRaw`
527-
SELECT * FROM "Message"
528-
WHERE "instanceId" = ${this.instanceId}
529-
AND "key"->>'id' = ${key.id}
530-
`) as proto.IWebMessageInfo[];
525+
const provider = this.configService.get<Database>('DATABASE').PROVIDER;
526+
527+
let webMessageInfo: proto.IWebMessageInfo[];
528+
529+
if (provider === 'mysql') {
530+
// MySQL version
531+
webMessageInfo = (await this.prismaRepository.$queryRaw`
532+
SELECT * FROM Message
533+
WHERE instanceId = ${this.instanceId}
534+
AND JSON_UNQUOTE(JSON_EXTRACT(\`key\`, '$.id')) = ${key.id}
535+
LIMIT 1
536+
`) as proto.IWebMessageInfo[];
537+
} else {
538+
// PostgreSQL version
539+
webMessageInfo = (await this.prismaRepository.$queryRaw`
540+
SELECT * FROM "Message"
541+
WHERE "instanceId" = ${this.instanceId}
542+
AND "key"->>'id' = ${key.id}
543+
LIMIT 1
544+
`) as proto.IWebMessageInfo[];
545+
}
531546

532547
if (full) {
533548
return webMessageInfo[0];
@@ -1636,13 +1651,24 @@ export class BaileysStartupService extends ChannelStartupService {
16361651
}
16371652

16381653
const searchId = originalMessageId || key.id;
1639-
1640-
const messages = (await this.prismaRepository.$queryRaw`
1641-
SELECT * FROM "Message"
1642-
WHERE "instanceId" = ${this.instanceId}
1643-
AND "key"->>'id' = ${searchId}
1644-
LIMIT 1
1645-
`) as any[];
1654+
const dbProvider = this.configService.get<Database>('DATABASE').PROVIDER;
1655+
1656+
let messages: any[];
1657+
if (dbProvider === 'mysql') {
1658+
messages = (await this.prismaRepository.$queryRaw`
1659+
SELECT * FROM Message
1660+
WHERE instanceId = ${this.instanceId}
1661+
AND JSON_UNQUOTE(JSON_EXTRACT(\`key\`, '$.id')) = ${searchId}
1662+
LIMIT 1
1663+
`) as any[];
1664+
} else {
1665+
messages = (await this.prismaRepository.$queryRaw`
1666+
SELECT * FROM "Message"
1667+
WHERE "instanceId" = ${this.instanceId}
1668+
AND "key"->>'id' = ${searchId}
1669+
LIMIT 1
1670+
`) as any[];
1671+
}
16461672
findMessage = messages[0] || null;
16471673

16481674
if (!findMessage?.id) {
@@ -4734,16 +4760,32 @@ export class BaileysStartupService extends ChannelStartupService {
47344760
private async updateMessagesReadedByTimestamp(remoteJid: string, timestamp?: number): Promise<number> {
47354761
if (timestamp === undefined || timestamp === null) return 0;
47364762

4737-
// Use raw SQL to avoid JSON path issues
4738-
const result = await this.prismaRepository.$executeRaw`
4739-
UPDATE "Message"
4740-
SET "status" = ${status[4]}
4741-
WHERE "instanceId" = ${this.instanceId}
4742-
AND "key"->>'remoteJid' = ${remoteJid}
4743-
AND ("key"->>'fromMe')::boolean = false
4744-
AND "messageTimestamp" <= ${timestamp}
4745-
AND ("status" IS NULL OR "status" = ${status[3]})
4746-
`;
4763+
const provider = this.configService.get<Database>('DATABASE').PROVIDER;
4764+
let result: number;
4765+
4766+
if (provider === 'mysql') {
4767+
// MySQL version
4768+
result = await this.prismaRepository.$executeRaw`
4769+
UPDATE Message
4770+
SET status = ${status[4]}
4771+
WHERE instanceId = ${this.instanceId}
4772+
AND JSON_UNQUOTE(JSON_EXTRACT(\`key\`, '$.remoteJid')) = ${remoteJid}
4773+
AND JSON_UNQUOTE(JSON_EXTRACT(\`key\`, '$.fromMe')) = 'false'
4774+
AND messageTimestamp <= ${timestamp}
4775+
AND (status IS NULL OR status = ${status[3]})
4776+
`;
4777+
} else {
4778+
// PostgreSQL version
4779+
result = await this.prismaRepository.$executeRaw`
4780+
UPDATE "Message"
4781+
SET "status" = ${status[4]}
4782+
WHERE "instanceId" = ${this.instanceId}
4783+
AND "key"->>'remoteJid' = ${remoteJid}
4784+
AND ("key"->>'fromMe')::boolean = false
4785+
AND "messageTimestamp" <= ${timestamp}
4786+
AND ("status" IS NULL OR "status" = ${status[3]})
4787+
`;
4788+
}
47474789

47484790
if (result) {
47494791
if (result > 0) {
@@ -4757,16 +4799,33 @@ export class BaileysStartupService extends ChannelStartupService {
47574799
}
47584800

47594801
private async updateChatUnreadMessages(remoteJid: string): Promise<number> {
4760-
const [chat, unreadMessages] = await Promise.all([
4761-
this.prismaRepository.chat.findFirst({ where: { remoteJid } }),
4762-
// Use raw SQL to avoid JSON path issues
4763-
this.prismaRepository.$queryRaw`
4802+
const provider = this.configService.get<Database>('DATABASE').PROVIDER;
4803+
4804+
let unreadMessagesPromise: Promise<number>;
4805+
4806+
if (provider === 'mysql') {
4807+
// MySQL version
4808+
unreadMessagesPromise = this.prismaRepository.$queryRaw`
4809+
SELECT COUNT(*) as count FROM Message
4810+
WHERE instanceId = ${this.instanceId}
4811+
AND JSON_UNQUOTE(JSON_EXTRACT(\`key\`, '$.remoteJid')) = ${remoteJid}
4812+
AND JSON_UNQUOTE(JSON_EXTRACT(\`key\`, '$.fromMe')) = 'false'
4813+
AND status = ${status[3]}
4814+
`.then((result: any[]) => Number(result[0]?.count) || 0);
4815+
} else {
4816+
// PostgreSQL version
4817+
unreadMessagesPromise = this.prismaRepository.$queryRaw`
47644818
SELECT COUNT(*)::int as count FROM "Message"
47654819
WHERE "instanceId" = ${this.instanceId}
47664820
AND "key"->>'remoteJid' = ${remoteJid}
47674821
AND ("key"->>'fromMe')::boolean = false
47684822
AND "status" = ${status[3]}
4769-
`.then((result: any[]) => result[0]?.count || 0),
4823+
`.then((result: any[]) => result[0]?.count || 0);
4824+
}
4825+
4826+
const [chat, unreadMessages] = await Promise.all([
4827+
this.prismaRepository.chat.findFirst({ where: { remoteJid } }),
4828+
unreadMessagesPromise,
47704829
]);
47714830

47724831
if (chat && chat.unreadMessages !== unreadMessages) {
@@ -4778,50 +4837,95 @@ export class BaileysStartupService extends ChannelStartupService {
47784837

47794838
private async addLabel(labelId: string, instanceId: string, chatId: string) {
47804839
const id = cuid();
4781-
4782-
await this.prismaRepository.$executeRawUnsafe(
4783-
`INSERT INTO "Chat" ("id", "instanceId", "remoteJid", "labels", "createdAt", "updatedAt")
4784-
VALUES ($4, $2, $3, to_jsonb(ARRAY[$1]::text[]), NOW(), NOW()) ON CONFLICT ("instanceId", "remoteJid")
4785-
DO
4786-
UPDATE
4787-
SET "labels" = (
4788-
SELECT to_jsonb(array_agg(DISTINCT elem))
4789-
FROM (
4790-
SELECT jsonb_array_elements_text("Chat"."labels") AS elem
4791-
UNION
4792-
SELECT $1::text AS elem
4793-
) sub
4794-
),
4795-
"updatedAt" = NOW();`,
4796-
labelId,
4797-
instanceId,
4798-
chatId,
4799-
id,
4800-
);
4840+
const provider = this.configService.get<Database>('DATABASE').PROVIDER;
4841+
4842+
if (provider === 'mysql') {
4843+
// MySQL version - use INSERT ... ON DUPLICATE KEY UPDATE
4844+
await this.prismaRepository.$executeRawUnsafe(
4845+
`INSERT INTO Chat (id, instanceId, remoteJid, labels, createdAt, updatedAt)
4846+
VALUES (?, ?, ?, JSON_ARRAY(?), NOW(), NOW())
4847+
ON DUPLICATE KEY UPDATE
4848+
labels = JSON_ARRAY_APPEND(
4849+
COALESCE(labels, JSON_ARRAY()),
4850+
'$',
4851+
?
4852+
),
4853+
updatedAt = NOW()`,
4854+
id,
4855+
instanceId,
4856+
chatId,
4857+
labelId,
4858+
labelId,
4859+
);
4860+
} else {
4861+
// PostgreSQL version
4862+
await this.prismaRepository.$executeRawUnsafe(
4863+
`INSERT INTO "Chat" ("id", "instanceId", "remoteJid", "labels", "createdAt", "updatedAt")
4864+
VALUES ($4, $2, $3, to_jsonb(ARRAY[$1]::text[]), NOW(), NOW()) ON CONFLICT ("instanceId", "remoteJid")
4865+
DO
4866+
UPDATE
4867+
SET "labels" = (
4868+
SELECT to_jsonb(array_agg(DISTINCT elem))
4869+
FROM (
4870+
SELECT jsonb_array_elements_text("Chat"."labels") AS elem
4871+
UNION
4872+
SELECT $1::text AS elem
4873+
) sub
4874+
),
4875+
"updatedAt" = NOW();`,
4876+
labelId,
4877+
instanceId,
4878+
chatId,
4879+
id,
4880+
);
4881+
}
48014882
}
48024883

48034884
private async removeLabel(labelId: string, instanceId: string, chatId: string) {
48044885
const id = cuid();
4805-
4806-
await this.prismaRepository.$executeRawUnsafe(
4807-
`INSERT INTO "Chat" ("id", "instanceId", "remoteJid", "labels", "createdAt", "updatedAt")
4808-
VALUES ($4, $2, $3, '[]'::jsonb, NOW(), NOW()) ON CONFLICT ("instanceId", "remoteJid")
4809-
DO
4810-
UPDATE
4811-
SET "labels" = COALESCE (
4812-
(
4813-
SELECT jsonb_agg(elem)
4814-
FROM jsonb_array_elements_text("Chat"."labels") AS elem
4815-
WHERE elem <> $1
4816-
),
4817-
'[]'::jsonb
4818-
),
4819-
"updatedAt" = NOW();`,
4820-
labelId,
4821-
instanceId,
4822-
chatId,
4823-
id,
4824-
);
4886+
const provider = this.configService.get<Database>('DATABASE').PROVIDER;
4887+
4888+
if (provider === 'mysql') {
4889+
// MySQL version - use INSERT ... ON DUPLICATE KEY UPDATE
4890+
await this.prismaRepository.$executeRawUnsafe(
4891+
`INSERT INTO Chat (id, instanceId, remoteJid, labels, createdAt, updatedAt)
4892+
VALUES (?, ?, ?, JSON_ARRAY(), NOW(), NOW())
4893+
ON DUPLICATE KEY UPDATE
4894+
labels = COALESCE(
4895+
JSON_REMOVE(
4896+
labels,
4897+
JSON_UNQUOTE(JSON_SEARCH(labels, 'one', ?))
4898+
),
4899+
JSON_ARRAY()
4900+
),
4901+
updatedAt = NOW()`,
4902+
id,
4903+
instanceId,
4904+
chatId,
4905+
labelId,
4906+
);
4907+
} else {
4908+
// PostgreSQL version
4909+
await this.prismaRepository.$executeRawUnsafe(
4910+
`INSERT INTO "Chat" ("id", "instanceId", "remoteJid", "labels", "createdAt", "updatedAt")
4911+
VALUES ($4, $2, $3, '[]'::jsonb, NOW(), NOW()) ON CONFLICT ("instanceId", "remoteJid")
4912+
DO
4913+
UPDATE
4914+
SET "labels" = COALESCE (
4915+
(
4916+
SELECT jsonb_agg(elem)
4917+
FROM jsonb_array_elements_text("Chat"."labels") AS elem
4918+
WHERE elem <> $1
4919+
),
4920+
'[]'::jsonb
4921+
),
4922+
"updatedAt" = NOW();`,
4923+
labelId,
4924+
instanceId,
4925+
chatId,
4926+
id,
4927+
);
4928+
}
48254929
}
48264930

48274931
public async baileysOnWhatsapp(jid: string) {

src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,18 +1617,36 @@ export class ChatwootService {
16171617
return;
16181618
}
16191619

1620-
// Use raw SQL to avoid JSON path issues
1621-
const result = await this.prismaRepository.$executeRaw`
1622-
UPDATE "Message"
1623-
SET
1624-
"chatwootMessageId" = ${chatwootMessageIds.messageId},
1625-
"chatwootConversationId" = ${chatwootMessageIds.conversationId},
1626-
"chatwootInboxId" = ${chatwootMessageIds.inboxId},
1627-
"chatwootContactInboxSourceId" = ${chatwootMessageIds.contactInboxSourceId},
1628-
"chatwootIsRead" = ${chatwootMessageIds.isRead || false}
1629-
WHERE "instanceId" = ${instance.instanceId}
1630-
AND "key"->>'id' = ${key.id}
1631-
`;
1620+
const provider = this.configService.get<Database>('DATABASE').PROVIDER;
1621+
let result: number;
1622+
1623+
if (provider === 'mysql') {
1624+
// MySQL version
1625+
result = await this.prismaRepository.$executeRaw`
1626+
UPDATE Message
1627+
SET
1628+
chatwootMessageId = ${chatwootMessageIds.messageId},
1629+
chatwootConversationId = ${chatwootMessageIds.conversationId},
1630+
chatwootInboxId = ${chatwootMessageIds.inboxId},
1631+
chatwootContactInboxSourceId = ${chatwootMessageIds.contactInboxSourceId},
1632+
chatwootIsRead = ${chatwootMessageIds.isRead || false}
1633+
WHERE instanceId = ${instance.instanceId}
1634+
AND JSON_UNQUOTE(JSON_EXTRACT(\`key\`, '$.id')) = ${key.id}
1635+
`;
1636+
} else {
1637+
// PostgreSQL version
1638+
result = await this.prismaRepository.$executeRaw`
1639+
UPDATE "Message"
1640+
SET
1641+
"chatwootMessageId" = ${chatwootMessageIds.messageId},
1642+
"chatwootConversationId" = ${chatwootMessageIds.conversationId},
1643+
"chatwootInboxId" = ${chatwootMessageIds.inboxId},
1644+
"chatwootContactInboxSourceId" = ${chatwootMessageIds.contactInboxSourceId},
1645+
"chatwootIsRead" = ${chatwootMessageIds.isRead || false}
1646+
WHERE "instanceId" = ${instance.instanceId}
1647+
AND "key"->>'id' = ${key.id}
1648+
`;
1649+
}
16321650

16331651
this.logger.verbose(`Update result: ${result} rows affected`);
16341652

@@ -1642,15 +1660,28 @@ export class ChatwootService {
16421660
}
16431661

16441662
private async getMessageByKeyId(instance: InstanceDto, keyId: string): Promise<MessageModel> {
1645-
// Use raw SQL query to avoid JSON path issues with Prisma
1646-
const messages = await this.prismaRepository.$queryRaw`
1647-
SELECT * FROM "Message"
1648-
WHERE "instanceId" = ${instance.instanceId}
1649-
AND "key"->>'id' = ${keyId}
1650-
LIMIT 1
1651-
`;
1652-
1653-
return (messages as MessageModel[])[0] || null;
1663+
const provider = this.configService.get<Database>('DATABASE').PROVIDER;
1664+
let messages: MessageModel[];
1665+
1666+
if (provider === 'mysql') {
1667+
// MySQL version
1668+
messages = await this.prismaRepository.$queryRaw`
1669+
SELECT * FROM Message
1670+
WHERE instanceId = ${instance.instanceId}
1671+
AND JSON_UNQUOTE(JSON_EXTRACT(\`key\`, '$.id')) = ${keyId}
1672+
LIMIT 1
1673+
`;
1674+
} else {
1675+
// PostgreSQL version
1676+
messages = await this.prismaRepository.$queryRaw`
1677+
SELECT * FROM "Message"
1678+
WHERE "instanceId" = ${instance.instanceId}
1679+
AND "key"->>'id' = ${keyId}
1680+
LIMIT 1
1681+
`;
1682+
}
1683+
1684+
return messages[0] || null;
16541685
}
16551686

16561687
private async getReplyToIds(

0 commit comments

Comments
 (0)