mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-16 04:02:54 -06:00
feat: send pix button
This commit is contained in:
parent
23640a71b8
commit
fbccf2eb2a
@ -73,6 +73,7 @@
|
|||||||
"jsonschema": "^1.4.1",
|
"jsonschema": "^1.4.1",
|
||||||
"link-preview-js": "^3.0.4",
|
"link-preview-js": "^3.0.4",
|
||||||
"long": "^5.2.3",
|
"long": "^5.2.3",
|
||||||
|
"mediainfo.js": "^0.3.2",
|
||||||
"mime": "^3.0.0",
|
"mime": "^3.0.0",
|
||||||
"minio": "^8.0.1",
|
"minio": "^8.0.1",
|
||||||
"multer": "^1.4.5-lts.1",
|
"multer": "^1.4.5-lts.1",
|
||||||
|
@ -141,9 +141,70 @@ import qrcodeTerminal from 'qrcode-terminal';
|
|||||||
import sharp from 'sharp';
|
import sharp from 'sharp';
|
||||||
import { PassThrough } from 'stream';
|
import { PassThrough } from 'stream';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
import { Readable } from 'stream';
|
||||||
|
|
||||||
const groupMetadataCache = new CacheService(new CacheEngine(configService, 'groups').getEngine());
|
const groupMetadataCache = new CacheService(new CacheEngine(configService, 'groups').getEngine());
|
||||||
|
|
||||||
|
// Adicione a função getVideoDuration no início do arquivo
|
||||||
|
async function getVideoDuration(input: Buffer | string | Readable): Promise<number> {
|
||||||
|
const MediaInfoFactory = (await import('mediainfo.js')).default;
|
||||||
|
const mediainfo = await MediaInfoFactory({ format: 'JSON' });
|
||||||
|
|
||||||
|
let fileSize: number;
|
||||||
|
let readChunk: (size: number, offset: number) => Promise<Buffer>;
|
||||||
|
|
||||||
|
if (Buffer.isBuffer(input)) {
|
||||||
|
fileSize = input.length;
|
||||||
|
readChunk = async (size: number, offset: number): Promise<Buffer> => {
|
||||||
|
return input.slice(offset, offset + size);
|
||||||
|
};
|
||||||
|
} else if (typeof input === 'string') {
|
||||||
|
const fs = await import('fs');
|
||||||
|
const stat = await fs.promises.stat(input);
|
||||||
|
fileSize = stat.size;
|
||||||
|
const fd = await fs.promises.open(input, 'r');
|
||||||
|
|
||||||
|
readChunk = async (size: number, offset: number): Promise<Buffer> => {
|
||||||
|
const buffer = Buffer.alloc(size);
|
||||||
|
await fd.read(buffer, 0, size, offset);
|
||||||
|
return buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await mediainfo.analyzeData(() => fileSize, readChunk);
|
||||||
|
const jsonResult = JSON.parse(result);
|
||||||
|
|
||||||
|
const generalTrack = jsonResult.media.track.find((t: any) => t['@type'] === 'General');
|
||||||
|
const duration = generalTrack.Duration;
|
||||||
|
|
||||||
|
return Math.round(parseFloat(duration));
|
||||||
|
} finally {
|
||||||
|
await fd.close();
|
||||||
|
}
|
||||||
|
} else if (input instanceof Readable) {
|
||||||
|
const chunks: Buffer[] = [];
|
||||||
|
for await (const chunk of input) {
|
||||||
|
chunks.push(chunk);
|
||||||
|
}
|
||||||
|
const data = Buffer.concat(chunks);
|
||||||
|
fileSize = data.length;
|
||||||
|
|
||||||
|
readChunk = async (size: number, offset: number): Promise<Buffer> => {
|
||||||
|
return data.slice(offset, offset + size);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
throw new Error('Tipo de entrada não suportado');
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await mediainfo.analyzeData(() => fileSize, readChunk);
|
||||||
|
const jsonResult = JSON.parse(result);
|
||||||
|
|
||||||
|
const generalTrack = jsonResult.media.track.find((t: any) => t['@type'] === 'General');
|
||||||
|
const duration = generalTrack.Duration;
|
||||||
|
|
||||||
|
return Math.round(parseFloat(duration));
|
||||||
|
}
|
||||||
|
|
||||||
export class BaileysStartupService extends ChannelStartupService {
|
export class BaileysStartupService extends ChannelStartupService {
|
||||||
constructor(
|
constructor(
|
||||||
public readonly configService: ConfigService,
|
public readonly configService: ConfigService,
|
||||||
@ -1101,6 +1162,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
received?.message?.stickerMessage ||
|
received?.message?.stickerMessage ||
|
||||||
received?.message?.documentMessage ||
|
received?.message?.documentMessage ||
|
||||||
received?.message?.documentWithCaptionMessage ||
|
received?.message?.documentWithCaptionMessage ||
|
||||||
|
received?.message?.ptvMessage ||
|
||||||
received?.message?.audioMessage;
|
received?.message?.audioMessage;
|
||||||
|
|
||||||
if (this.localSettings.readMessages && received.key.id !== 'status@broadcast') {
|
if (this.localSettings.readMessages && received.key.id !== 'status@broadcast') {
|
||||||
@ -2097,6 +2159,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
messageSent?.message?.ptvMessage ||
|
messageSent?.message?.ptvMessage ||
|
||||||
messageSent?.message?.documentMessage ||
|
messageSent?.message?.documentMessage ||
|
||||||
messageSent?.message?.documentWithCaptionMessage ||
|
messageSent?.message?.documentWithCaptionMessage ||
|
||||||
|
messageSent?.message?.ptvMessage ||
|
||||||
messageSent?.message?.audioMessage;
|
messageSent?.message?.audioMessage;
|
||||||
|
|
||||||
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED && this.localChatwoot?.enabled && !isIntegration) {
|
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED && this.localChatwoot?.enabled && !isIntegration) {
|
||||||
@ -2500,6 +2563,37 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
|
|
||||||
if (mediaMessage.mediatype === 'ptv') {
|
if (mediaMessage.mediatype === 'ptv') {
|
||||||
prepareMedia[mediaType] = prepareMedia[type + 'Message'];
|
prepareMedia[mediaType] = prepareMedia[type + 'Message'];
|
||||||
|
mimetype = 'video/mp4';
|
||||||
|
|
||||||
|
if (!prepareMedia[mediaType]) {
|
||||||
|
throw new Error('Failed to prepare video message');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let mediaInput;
|
||||||
|
if (isURL(mediaMessage.media)) {
|
||||||
|
mediaInput = mediaMessage.media;
|
||||||
|
} else {
|
||||||
|
const mediaBuffer = Buffer.from(mediaMessage.media, 'base64');
|
||||||
|
if (!mediaBuffer || mediaBuffer.length === 0) {
|
||||||
|
throw new Error('Invalid media buffer');
|
||||||
|
}
|
||||||
|
mediaInput = mediaBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
const duration = await getVideoDuration(mediaInput);
|
||||||
|
if (!duration || duration <= 0) {
|
||||||
|
throw new Error('Invalid media duration');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.verbose(`Video duration: ${duration} seconds`);
|
||||||
|
prepareMedia[mediaType].seconds = duration;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error('Error getting video duration:');
|
||||||
|
this.logger.error(error);
|
||||||
|
throw new Error(`Failed to get video duration: ${error.message}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareMedia[mediaType].caption = mediaMessage?.caption;
|
prepareMedia[mediaType].caption = mediaMessage?.caption;
|
||||||
|
@ -131,7 +131,7 @@ export declare namespace wa {
|
|||||||
export type StatusMessage = 'ERROR' | 'PENDING' | 'SERVER_ACK' | 'DELIVERY_ACK' | 'READ' | 'DELETED' | 'PLAYED';
|
export type StatusMessage = 'ERROR' | 'PENDING' | 'SERVER_ACK' | 'DELIVERY_ACK' | 'READ' | 'DELETED' | 'PLAYED';
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TypeMediaMessage = ['imageMessage', 'documentMessage', 'audioMessage', 'videoMessage', 'stickerMessage'];
|
export const TypeMediaMessage = ['imageMessage', 'documentMessage', 'audioMessage', 'videoMessage', 'stickerMessage', 'ptvMessage'];
|
||||||
|
|
||||||
export const MessageSubtype = [
|
export const MessageSubtype = [
|
||||||
'ephemeralMessage',
|
'ephemeralMessage',
|
||||||
|
Loading…
Reference in New Issue
Block a user