mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-20 10:16:43 -06:00
fix: import contacts with image in chatwoot
This commit is contained in:
parent
55d37250aa
commit
4d9f6ef416
@ -117,9 +117,10 @@ TYPEBOT_SEND_MEDIA_BASE64=true
|
|||||||
TYPEBOT_API_VERSION=latest
|
TYPEBOT_API_VERSION=latest
|
||||||
|
|
||||||
CHATWOOT_ENABLED=false
|
CHATWOOT_ENABLED=false
|
||||||
CHATWOOT_MESSAGE_READ=false
|
CHATWOOT_MESSAGE_READ=true
|
||||||
CHATWOOT_IMPORT_DATABASE_CONNECTION_URI=postgresql://user:pass@host:5432/dbname
|
CHATWOOT_MESSAGE_DELETE=true
|
||||||
CHATWOOT_IMPORT_PLACEHOLDER_MEDIA_MESSAGE=false
|
CHATWOOT_IMPORT_DATABASE_CONNECTION_URI=postgresql://user:passwprd@host:5432/chatwoot?sslmode=disable
|
||||||
|
CHATWOOT_IMPORT_PLACEHOLDER_MEDIA_MESSAGE=true
|
||||||
|
|
||||||
OPENAI_ENABLED=false
|
OPENAI_ENABLED=false
|
||||||
OPENAI_API_KEY_GLOBAL=
|
OPENAI_API_KEY_GLOBAL=
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
# 2.0.9-rc (release candidate)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Import contacts with image in chatwoot
|
||||||
|
|
||||||
# 2.0.8-rc (2024-08-08 20:23)
|
# 2.0.8-rc (2024-08-08 20:23)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
@ -818,14 +818,25 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
|
|
||||||
if (updatedContacts.length > 0) {
|
if (updatedContacts.length > 0) {
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
updatedContacts.map((contact) =>
|
updatedContacts.map(async function (contact) {
|
||||||
this.prismaRepository.contact.updateMany({
|
const update = this.prismaRepository.contact.updateMany({
|
||||||
where: { remoteJid: contact.remoteJid, instanceId: this.instanceId },
|
where: { remoteJid: contact.remoteJid, instanceId: this.instanceId },
|
||||||
data: {
|
data: {
|
||||||
profilePicUrl: contact.profilePicUrl,
|
profilePicUrl: contact.profilePicUrl,
|
||||||
},
|
},
|
||||||
}),
|
});
|
||||||
),
|
|
||||||
|
const instance = { instanceName: this.instance.name, instanceId: this.instance.id };
|
||||||
|
|
||||||
|
const findParticipant = await this.findContact(instance, contact.remoteJid.split('@')[0]);
|
||||||
|
|
||||||
|
this.chatwootService.updateContact(instance, findParticipant.id, {
|
||||||
|
name: contact.pushName,
|
||||||
|
avatar_url: contact.profilePicUrl,
|
||||||
|
});
|
||||||
|
|
||||||
|
return update;
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -1636,10 +1647,12 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
public async profilePicture(number: string) {
|
public async profilePicture(number: string) {
|
||||||
const jid = this.createJid(number);
|
const jid = this.createJid(number);
|
||||||
|
|
||||||
|
const profilePictureUrl = await this.client.profilePictureUrl(jid, 'image');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return {
|
return {
|
||||||
wuid: jid,
|
wuid: jid,
|
||||||
profilePictureUrl: await this.client.profilePictureUrl(jid, 'image'),
|
profilePictureUrl,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return {
|
return {
|
||||||
|
@ -4,8 +4,9 @@ import EventEmitter2 from 'eventemitter2';
|
|||||||
import FormData from 'form-data';
|
import FormData from 'form-data';
|
||||||
import { createReadStream } from 'fs';
|
import { createReadStream } from 'fs';
|
||||||
import { getMIMEType } from 'node-mime-types';
|
import { getMIMEType } from 'node-mime-types';
|
||||||
|
import { join } from 'path';
|
||||||
|
|
||||||
import { Chatwoot, ConfigService, Database, Dify, Openai, Typebot, WaBusiness } from '../../../config/env.config';
|
import { Chatwoot, ConfigService, Database, Dify, Openai, S3, Typebot, WaBusiness } from '../../../config/env.config';
|
||||||
import { BadRequestException, InternalServerErrorException } from '../../../exceptions';
|
import { BadRequestException, InternalServerErrorException } from '../../../exceptions';
|
||||||
import { NumberBusiness } from '../../dto/chat.dto';
|
import { NumberBusiness } from '../../dto/chat.dto';
|
||||||
import {
|
import {
|
||||||
@ -22,6 +23,7 @@ import {
|
|||||||
SendTemplateDto,
|
SendTemplateDto,
|
||||||
SendTextDto,
|
SendTextDto,
|
||||||
} from '../../dto/sendMessage.dto';
|
} from '../../dto/sendMessage.dto';
|
||||||
|
import * as s3Service from '../../integrations/s3/libs/minio.server';
|
||||||
import { ProviderFiles } from '../../provider/sessions';
|
import { ProviderFiles } from '../../provider/sessions';
|
||||||
import { PrismaRepository } from '../../repository/repository.service';
|
import { PrismaRepository } from '../../repository/repository.service';
|
||||||
import { Events, wa } from '../../types/wa.types';
|
import { Events, wa } from '../../types/wa.types';
|
||||||
@ -316,20 +318,78 @@ export class BusinessStartupService extends ChannelStartupService {
|
|||||||
received?.messages[0].audio ||
|
received?.messages[0].audio ||
|
||||||
received?.messages[0].video
|
received?.messages[0].video
|
||||||
) {
|
) {
|
||||||
const buffer = await this.downloadMediaMessage(received?.messages[0]);
|
|
||||||
messageRaw = {
|
messageRaw = {
|
||||||
key,
|
key,
|
||||||
pushName,
|
pushName,
|
||||||
message: {
|
message: this.messageMediaJson(received),
|
||||||
...this.messageMediaJson(received),
|
|
||||||
base64: buffer ? buffer.toString('base64') : undefined,
|
|
||||||
},
|
|
||||||
contextInfo: this.messageMediaJson(received)?.contextInfo,
|
contextInfo: this.messageMediaJson(received)?.contextInfo,
|
||||||
messageType: this.renderMessageType(received.messages[0].type),
|
messageType: this.renderMessageType(received.messages[0].type),
|
||||||
messageTimestamp: parseInt(received.messages[0].timestamp) as number,
|
messageTimestamp: parseInt(received.messages[0].timestamp) as number,
|
||||||
source: 'unknown',
|
source: 'unknown',
|
||||||
instanceId: this.instanceId,
|
instanceId: this.instanceId,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (this.configService.get<S3>('S3').ENABLE) {
|
||||||
|
try {
|
||||||
|
const message: any = received;
|
||||||
|
|
||||||
|
const id = message[message.type].id;
|
||||||
|
let urlServer = this.configService.get<WaBusiness>('WA_BUSINESS').URL;
|
||||||
|
const version = this.configService.get<WaBusiness>('WA_BUSINESS').VERSION;
|
||||||
|
urlServer = `${urlServer}/${version}/${id}`;
|
||||||
|
const headers = { 'Content-Type': 'application/json', Authorization: `Bearer ${this.token}` };
|
||||||
|
const result = await axios.get(urlServer, { headers });
|
||||||
|
|
||||||
|
const buffer = await axios.get(result.data.url, { headers, responseType: 'arraybuffer' });
|
||||||
|
|
||||||
|
const mediaType = message.messages[0].document
|
||||||
|
? 'document'
|
||||||
|
: message.messages[0].image
|
||||||
|
? 'image'
|
||||||
|
: message.messages[0].audio
|
||||||
|
? 'audio'
|
||||||
|
: 'video';
|
||||||
|
|
||||||
|
const mimetype = result.headers['content-type'];
|
||||||
|
|
||||||
|
const contentDisposition = result.headers['content-disposition'];
|
||||||
|
let fileName = `${message.messages[0].id}.${mimetype.split('/')[1]}`;
|
||||||
|
if (contentDisposition) {
|
||||||
|
const match = contentDisposition.match(/filename="(.+?)"/);
|
||||||
|
if (match) {
|
||||||
|
fileName = match[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const size = result.headers['content-length'] || buffer.data.byteLength;
|
||||||
|
|
||||||
|
const fullName = join(`${this.instance.id}`, received.key.remoteJid, mediaType, fileName);
|
||||||
|
|
||||||
|
await s3Service.uploadFile(fullName, buffer.data, size, {
|
||||||
|
'Content-Type': mimetype,
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.prismaRepository.media.create({
|
||||||
|
data: {
|
||||||
|
messageId: received.messages[0].id,
|
||||||
|
instanceId: this.instanceId,
|
||||||
|
type: mediaType,
|
||||||
|
fileName: fullName,
|
||||||
|
mimetype,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const mediaUrl = await s3Service.getObjectUrl(fullName);
|
||||||
|
|
||||||
|
messageRaw.message.mediaUrl = mediaUrl;
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(['Error on upload file to minio', error?.message, error?.stack]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const buffer = await this.downloadMediaMessage(received?.messages[0]);
|
||||||
|
|
||||||
|
messageRaw.message.base64 = buffer.toString('base64');
|
||||||
|
}
|
||||||
} else if (received?.messages[0].interactive) {
|
} else if (received?.messages[0].interactive) {
|
||||||
messageRaw = {
|
messageRaw = {
|
||||||
key,
|
key,
|
||||||
@ -395,11 +455,7 @@ export class BusinessStartupService extends ChannelStartupService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.localSettings.readMessages && received.key.id !== 'status@broadcast') {
|
if (this.localSettings.readMessages) {
|
||||||
// await this.client.readMessages([received.key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.localSettings.readStatus && received.key.id === 'status@broadcast') {
|
|
||||||
// await this.client.readMessages([received.key]);
|
// await this.client.readMessages([received.key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ export interface TelemetryData {
|
|||||||
export const sendTelemetry = async (route: string): Promise<void> => {
|
export const sendTelemetry = async (route: string): Promise<void> => {
|
||||||
const enabled = process.env.TELEMETRY_ENABLED === undefined || process.env.TELEMETRY_ENABLED === 'true';
|
const enabled = process.env.TELEMETRY_ENABLED === undefined || process.env.TELEMETRY_ENABLED === 'true';
|
||||||
|
|
||||||
console.log('Telemetry enabled:', enabled);
|
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user