Compare commits

...

28 Commits

Author SHA1 Message Date
Davidson Gomes
cd800f2976 Merge branch 'release/2.3.7'
Some checks failed
Check Code Quality / check-lint-and-build (push) Has been cancelled
Build Docker image / Build and Deploy (push) Has been cancelled
Security Scan / CodeQL Analysis (javascript) (push) Has been cancelled
Security Scan / Dependency Review (push) Has been cancelled
2025-12-05 11:28:52 -03:00
Davidson Gomes
4f642e17a7 chore: changelog v2.3.7
Some checks failed
Check Code Quality / check-lint-and-build (push) Has been cancelled
Build Docker image / Build and Deploy (push) Has been cancelled
Security Scan / CodeQL Analysis (javascript) (push) Has been cancelled
Security Scan / Dependency Review (push) Has been cancelled
2025-12-05 11:28:40 -03:00
Davidson Gomes
afa6d633c6 chore(changelog): update version 2.3.7 with latest features and fixes 2025-12-05 11:13:17 -03:00
Davidson Gomes
2e3e752719 style(whatsapp): fix indentation and remove unnecessary blank lines in BaileysStartupService 2025-12-05 11:03:52 -03:00
Davidson Gomes
de11e6f9ca fix(websocket): improve host validation logic in WebsocketController 2025-12-05 11:03:52 -03:00
Davidson Gomes
26e7eefe51 Merge pull request #2259 from muriloleal13/fix/baileys-message-stub-placeholder
fix(baileys): prevent message loss from WhatsApp stub placeholders
2025-12-05 11:02:34 -03:00
Davidson Gomes
b55c9fcab7 Merge pull request #2250 from gabrielmouallem/fix/respect-database-save-data-contacts
fix: respect DATABASE_SAVE_DATA_CONTACTS in contact updates
2025-12-05 11:01:46 -03:00
Davidson Gomes
86b194af5f Merge pull request #2260 from alexandrereyes/feat/add-islatest-progress-to-messages-set
feat(events): add isLatest and progress to messages.set event
2025-12-05 11:01:21 -03:00
Davidson Gomes
3c1573c400 Merge pull request #2238 from jamesjhonatan123/feature/quote-message-n8n
Feature/quote message n8n
2025-12-05 11:00:54 -03:00
Davidson Gomes
178386594c Merge branch 'develop' into feature/quote-message-n8n 2025-12-05 11:00:40 -03:00
Davidson Gomes
cea1fa0979 Merge pull request #2247 from msantosjader/fix/postgres-chat-constraint
fix(prisma): add unique constraint to Chat model in Postgres
2025-12-05 10:59:22 -03:00
Davidson Gomes
38be0b49d9 Merge pull request #2280 from micaelmz/feature/wildcard-for-websocket-allowed-hosts
feat: add wildcard "*" to allow all hosts to connect via websocket
2025-12-05 10:59:03 -03:00
Alexandre Martins
04ac880fcc style: fix lint formatting issues 2025-12-05 10:58:42 -03:00
Davidson Gomes
3864366e75 Merge pull request #2273 from kay0ramon/fix/minio-messagecontextinfo-upload-error
fix: handle messageContextInfo in media upload to prevent MinIO errors
2025-12-05 10:57:55 -03:00
Davidson Gomes
2756d7e61c Merge pull request #2264 from lucascampuus/patch-1
Fix Typebot message routing for @lid JIDs
2025-12-05 10:57:31 -03:00
Davidson Gomes
bb36bfe424 Merge pull request #2249 from rodps/fix/fetch-messages-jid
fix: unify remoteJid filtering using OR with remoteJidAlt
2025-12-05 10:55:50 -03:00
micaelmz
abd0351f8f feat: add wildcard "*" to allow all hosts to connect via websocket 2025-12-02 18:01:19 -03:00
Kayo Ramon Oliveira
1c3a7ab027 fix: handle messageContextInfo in media upload to prevent MinIO errors 2025-11-28 15:59:09 -03:00
Alexandre Martins
930d32df3a fix(events): guard extra spread and prevent core field override
- Use (extra ?? {}) to handle undefined extra safely
- Spread extra first to prevent overriding core fields like event, instance, data
- Applied fix to all 7 event controllers

Addresses Sourcery AI review feedback.
2025-11-26 15:48:53 -03:00
Alexandre Martins
fa6b5c28a6 feat(events): add isLatest and progress to messages.set event
- Add extra field to EmitData type for additional payload properties
- Update EventManager and sendDataWebhook to support extra parameters
- Update all event controllers (webhook, rabbitmq, sqs, websocket, pusher, kafka, nats) to include extra fields in payload
- Pass isLatest and progress from Baileys messaging-history.set to messages.set webhook

This allows consumers to know when the history sync is complete (isLatest=true) and track sync progress percentage.
2025-11-26 15:44:18 -03:00
Murilo Leal
8e7f348c12 fix(baileys): prevent message loss from WhatsApp stub placeholders
Mensagens do WhatsApp estavam sendo perdidas e não eram salvas no banco de dados, especialmente mensagens de canais/newsletters (@lid) e mensagens com criptografia complexa.

O WhatsApp/Baileys envia mensagens criptografadas em duas etapas:

1. Primeiro: Envia um stub (placeholder) com messageStubParameters: ['Message absent from node'] enquanto descriptografa a mensagem

2. Depois: Envia a mensagem real com o conteúdo descriptografado

O problema ocorria porque:

- O stub chegava primeiro e era adicionado ao cache de mensagens duplicadas

- O stub era descartado (corretamente) por não ter conteúdo (!received?.message)

- A mensagem real chegava depois, mas era ignorada como duplicata porque o ID já estava no cache

- Resultado: mensagem nunca era salva no banco de dados

Solução:

- Detectar stubs do WhatsApp através de messageStubParameters contendo 'Message absent from node'

- Não adicionar stubs ao cache de mensagens duplicadas

- Permitir que a mensagem real seja processada quando chegar

- Manter o descarte do stub para evitar salvar placeholders vazios
2025-11-26 13:29:31 -03:00
Gabriel Mouallem
08a4795016 fix: respect DATABASE_SAVE_DATA_CONTACTS in contact updates
- Added missing conditional checks for `DATABASE_SAVE_DATA_CONTACTS` in `contacts.upsert` and `contacts.update` handlers.
- Fixed an issue where profile picture updates were attempting to save to the database even when disabled.
- Fixed an unawaited promise in `contacts.upsert` to ensure database operations complete correctly.
2025-11-23 23:09:42 -03:00
Gabriel Mouallem
53a94af3f7 fix: respect DATABASE_SAVE_DATA_CONTACTS in contact updates 2025-11-23 22:59:18 -03:00
Rodrigo da Silva
302e219f7f fix: unify remoteJid filtering using OR with remoteJidAlt 2025-11-23 18:46:06 -03:00
Jader Santos
1e036ba3ae fix(migration): add deduplication step before creating index 2025-11-21 22:09:15 -03:00
Jader Santos
377993e4b0 fix(prisma): add unique constraint to Chat model in Postgres
Generated migration to add unique index on instanceId and remoteJid.
2025-11-21 21:40:27 -03:00
Jonatas
f2c2a6a64a refactor: improve formatting and consistency in makeProxyAgent functions 2025-11-18 23:58:18 -03:00
Jonatas
e5a249109c feat: add quotedMessage to payload in sendMessageToBot on N8N 2025-11-18 23:52:36 -03:00
18 changed files with 183 additions and 33 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -1,4 +1,4 @@
# 2.3.7 (develop)
# 2.3.7 (2025-12-05)
### Features
@@ -7,6 +7,24 @@
- Added DTOs and validation schemas for template management
- Enhanced template lifecycle management capabilities
* **Events API**: Add isLatest and progress to messages.set event
- Allows consumers to know when history sync is complete (isLatest=true)
- Track sync progress percentage through webhooks
- Added extra field to EmitData type for additional payload properties
- Updated all event controllers (webhook, rabbitmq, sqs, websocket, pusher, kafka, nats)
* **N8N Integration**: Add quotedMessage to payload in sendMessageToBot
- Support for quoted messages in N8N chatbot integration
- Enhanced message context information
* **WebSocket**: Add wildcard "*" to allow all hosts to connect via websocket
- More flexible host configuration for WebSocket connections
- Improved host validation logic in WebsocketController
* **Pix Support**: Handle interactive button message for pix
- Support for interactive Pix button messages
- Enhanced payment flow integration
### Fixed
* **Baileys Message Processor**: Fix incoming message events not working after reconnection
@@ -60,11 +78,76 @@
- Fixed integration issues between Chatwoot and Baileys services
- Improved message handling and delivery
* **Baileys Message Loss**: Prevent message loss from WhatsApp stub placeholders
- Fixed messages being lost and not saved to database, especially for channels/newsletters (@lid)
- Detects WhatsApp stubs through messageStubParameters containing 'Message absent from node'
- Prevents adding stubs to duplicate message cache
- Allows real message to be processed when it arrives after decryption
- Maintains stub discard to avoid saving empty placeholders
* **Database Contacts**: Respect DATABASE_SAVE_DATA_CONTACTS in contact updates
- Added missing conditional checks for DATABASE_SAVE_DATA_CONTACTS configuration
- Fixed profile picture updates attempting to save when database save is disabled
- Fixed unawaited promise in contacts.upsert handler
* **Prisma/PostgreSQL**: Add unique constraint to Chat model
- Generated migration to add unique index on instanceId and remoteJid
- Added deduplication step before creating index to prevent constraint violations
- Prevents chat duplication in database
* **MinIO Upload**: Handle messageContextInfo in media upload to prevent MinIO errors
- Prevents errors when uploading media with messageContextInfo metadata
- Improved error handling for media storage operations
* **Typebot**: Fix message routing for @lid JIDs
- Typebot now responds to messages from JIDs ending with @lid
- Maintains complete JID for @lid instead of extracting only number
- Fixed condition: `remoteJid.includes('@lid') ? remoteJid : remoteJid.split('@')[0]`
- Handles both @s.whatsapp.net and @lid message formats
* **Message Filtering**: Unify remoteJid filtering using OR with remoteJidAlt
- Improved message filtering with alternative JID support
- Better handling of messages with different JID formats
* **@lid Integration**: Multiple fixes for @lid problems, message events and chatwoot errors
- Reorganized imports and improved message handling in BaileysStartupService
- Enhanced remoteJid processing to handle @lid cases
- Improved jid normalization and type safety in Chatwoot integration
- Streamlined message handling logic and cache management
- Refactored message handling and polling updates with decryption logic for poll votes
- Improved event processing flow for various message types
* **Chatwoot Contacts**: Fix contact duplication error on import
- Resolved 'ON CONFLICT DO UPDATE command cannot affect row a second time' error
- Removed attempt to update identifier field in conflict (part of constraint)
- Changed to update only updated_at field: `updated_at = NOW()`
- Allows duplicate contacts to be updated correctly without errors
* **Chatwoot Service**: Fix async handling in update_last_seen method
- Added missing await for chatwootRequest in read message processing
- Prevents service failure when processing read messages
* **Metrics Access**: Fix IP validation including x-forwarded-for
- Uses all IPs including x-forwarded-for header when checking metrics access
- Improved security and access control for metrics endpoint
### Dependencies
* **Baileys**: Updated to version 7.0.0-rc.9
- Latest release candidate with multiple improvements and bug fixes
* **AWS SDK**: Updated packages to version 3.936.0
- Enhanced functionality and compatibility
- Performance improvements
### Code Quality & Refactoring
* **Template Management**: Remove unused template edit/delete DTOs after refactoring
* **Proxy Utilities**: Improve makeProxyAgent for Undici compatibility
* **Code Formatting**: Enhance code formatting and consistency across services
* **BaileysStartupService**: Fix indentation and remove unnecessary blank lines
* **Event Controllers**: Guard extra spread and prevent core field override in all event controllers
* **Import Organization**: Reorganize imports for better code structure and maintainability
# 2.3.6 (2025-10-21)

6
package-lock.json generated
View File

@@ -8589,12 +8589,6 @@
"undici": ">=6"
}
},
"node_modules/fflate": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==",
"license": "MIT"
},
"node_modules/figures": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",

View File

@@ -0,0 +1,16 @@
-- 1. Cleanup: Remove duplicate chats, keeping the most recently updated one
DELETE FROM "Chat"
WHERE id IN (
SELECT id FROM (
SELECT id,
ROW_NUMBER() OVER (
PARTITION BY "instanceId", "remoteJid"
ORDER BY "updatedAt" DESC
) as row_num
FROM "Chat"
) t
WHERE t.row_num > 1
);
-- 2. Create the unique index (Constraint)
CREATE UNIQUE INDEX "Chat_instanceId_remoteJid_key" ON "Chat"("instanceId", "remoteJid");

View File

@@ -132,6 +132,7 @@ model Chat {
instanceId String
unreadMessages Int @default(0)
@@unique([instanceId, remoteJid])
@@index([instanceId])
@@index([remoteJid])
}

View File

@@ -861,10 +861,12 @@ export class BaileysStartupService extends ChannelStartupService {
this.sendDataWebhook(Events.CONTACTS_UPDATE, updatedContacts);
await Promise.all(
updatedContacts.map(async (contact) => {
const update = this.prismaRepository.contact.updateMany({
where: { remoteJid: contact.remoteJid, instanceId: this.instanceId },
data: { profilePicUrl: contact.profilePicUrl },
});
if (this.configService.get<Database>('DATABASE').SAVE_DATA.CONTACTS) {
await this.prismaRepository.contact.updateMany({
where: { remoteJid: contact.remoteJid, instanceId: this.instanceId },
data: { profilePicUrl: contact.profilePicUrl },
});
}
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED && this.localChatwoot?.enabled) {
const instance = { instanceName: this.instance.name, instanceId: this.instance.id };
@@ -883,8 +885,6 @@ export class BaileysStartupService extends ChannelStartupService {
avatar_url: contact.profilePicUrl,
});
}
return update;
}),
);
}
@@ -908,14 +908,16 @@ export class BaileysStartupService extends ChannelStartupService {
this.sendDataWebhook(Events.CONTACTS_UPDATE, contactsRaw);
const updateTransactions = contactsRaw.map((contact) =>
this.prismaRepository.contact.upsert({
where: { remoteJid_instanceId: { remoteJid: contact.remoteJid, instanceId: contact.instanceId } },
create: contact,
update: contact,
}),
);
await this.prismaRepository.$transaction(updateTransactions);
if (this.configService.get<Database>('DATABASE').SAVE_DATA.CONTACTS) {
const updateTransactions = contactsRaw.map((contact) =>
this.prismaRepository.contact.upsert({
where: { remoteJid_instanceId: { remoteJid: contact.remoteJid, instanceId: contact.instanceId } },
create: contact,
update: contact,
}),
);
await this.prismaRepository.$transaction(updateTransactions);
}
//const usersContacts = contactsRaw.filter((c) => c.remoteJid.includes('@s.whatsapp'));
},
@@ -1044,7 +1046,10 @@ export class BaileysStartupService extends ChannelStartupService {
messagesRaw.push(this.prepareMessage(m));
}
this.sendDataWebhook(Events.MESSAGES_SET, [...messagesRaw]);
this.sendDataWebhook(Events.MESSAGES_SET, [...messagesRaw], true, undefined, {
isLatest,
progress,
});
if (this.configService.get<Database>('DATABASE').SAVE_DATA.HISTORIC) {
await this.prismaRepository.message.createMany({ data: messagesRaw, skipDuplicates: true });
@@ -1090,6 +1095,7 @@ export class BaileysStartupService extends ChannelStartupService {
'Invalid PreKey ID',
'No session record',
'No session found to decrypt message',
'Message absent from node',
].some((err) => param?.includes?.(err)),
)
) {
@@ -1397,6 +1403,11 @@ export class BaileysStartupService extends ChannelStartupService {
} else {
const media = await this.getBase64FromMediaMessage({ message }, true);
if (!media) {
this.logger.verbose('No valid media to upload (messageContextInfo only), skipping MinIO');
return;
}
const { buffer, mediaType, fileName, size } = media;
const mimetype = mimeTypes.lookup(fileName).toString();
const fullName = join(
@@ -2463,6 +2474,11 @@ export class BaileysStartupService extends ChannelStartupService {
} else {
const media = await this.getBase64FromMediaMessage({ message }, true);
if (!media) {
this.logger.verbose('No valid media to upload (messageContextInfo only), skipping MinIO');
return;
}
const { buffer, mediaType, fileName, size } = media;
const mimetype = mimeTypes.lookup(fileName).toString();
@@ -3836,7 +3852,8 @@ export class BaileysStartupService extends ChannelStartupService {
}
if ('messageContextInfo' in msg.message && Object.keys(msg.message).length === 1) {
throw 'The message is messageContextInfo';
this.logger.verbose('Message contains only messageContextInfo, skipping media processing');
return null;
}
let mediaMessage: any;
@@ -5019,7 +5036,6 @@ export class BaileysStartupService extends ChannelStartupService {
AND: [
keyFilters?.id ? { key: { path: ['id'], equals: keyFilters?.id } } : {},
keyFilters?.fromMe ? { key: { path: ['fromMe'], equals: keyFilters?.fromMe } } : {},
keyFilters?.remoteJid ? { key: { path: ['remoteJid'], equals: keyFilters?.remoteJid } } : {},
keyFilters?.participant ? { key: { path: ['participant'], equals: keyFilters?.participant } } : {},
{
OR: [
@@ -5049,7 +5065,6 @@ export class BaileysStartupService extends ChannelStartupService {
AND: [
keyFilters?.id ? { key: { path: ['id'], equals: keyFilters?.id } } : {},
keyFilters?.fromMe ? { key: { path: ['fromMe'], equals: keyFilters?.fromMe } } : {},
keyFilters?.remoteJid ? { key: { path: ['remoteJid'], equals: keyFilters?.remoteJid } } : {},
keyFilters?.participant ? { key: { path: ['participant'], equals: keyFilters?.participant } } : {},
{
OR: [

View File

@@ -51,6 +51,7 @@ export class N8nService extends BaseChatbotService<N8n, N8nSetting> {
pushName: pushName,
keyId: msg?.key?.id,
fromMe: msg?.key?.fromMe,
quotedMessage: msg?.contextInfo?.quotedMessage,
instanceName: instance.instanceName,
serverUrl: this.configService.get<HttpServer>('SERVER').URL,
apiKey: instance.token,

View File

@@ -14,12 +14,24 @@ export type EmitData = {
apiKey?: string;
local?: boolean;
integration?: string[];
extra?: Record<string, any>;
};
export interface EventControllerInterface {
set(instanceName: string, data: any): Promise<any>;
get(instanceName: string): Promise<any>;
emit({ instanceName, origin, event, data, serverUrl, dateTime, sender, apiKey, local }: EmitData): Promise<void>;
emit({
instanceName,
origin,
event,
data,
serverUrl,
dateTime,
sender,
apiKey,
local,
extra,
}: EmitData): Promise<void>;
}
export class EventController {

View File

@@ -123,6 +123,7 @@ export class EventManager {
apiKey?: string;
local?: boolean;
integration?: string[];
extra?: Record<string, any>;
}): Promise<void> {
await this.websocket.emit(eventData);
await this.rabbitmq.emit(eventData);

View File

@@ -262,6 +262,7 @@ export class KafkaController extends EventController implements EventControllerI
sender,
apiKey,
integration,
extra,
}: EmitData): Promise<void> {
if (integration && !integration.includes('kafka')) {
return;
@@ -284,6 +285,7 @@ export class KafkaController extends EventController implements EventControllerI
const logEnabled = configService.get<Log>('LOG').LEVEL.includes('WEBHOOKS');
const message = {
...(extra ?? {}),
event,
instance: instanceName,
data,

View File

@@ -47,6 +47,7 @@ export class NatsController extends EventController implements EventControllerIn
sender,
apiKey,
integration,
extra,
}: EmitData): Promise<void> {
if (integration && !integration.includes('nats')) {
return;
@@ -65,6 +66,7 @@ export class NatsController extends EventController implements EventControllerIn
const logEnabled = configService.get<Log>('LOG').LEVEL.includes('WEBHOOKS');
const message = {
...(extra ?? {}),
event,
instance: instanceName,
data,

View File

@@ -121,6 +121,7 @@ export class PusherController extends EventController implements EventController
apiKey,
local,
integration,
extra,
}: EmitData): Promise<void> {
if (integration && !integration.includes('pusher')) {
return;
@@ -133,6 +134,7 @@ export class PusherController extends EventController implements EventController
const enabledLog = configService.get<Log>('LOG').LEVEL.includes('WEBHOOKS');
const eventName = event.replace(/_/g, '.').toLowerCase();
const pusherData = {
...(extra ?? {}),
event,
instance: instanceName,
data,

View File

@@ -209,6 +209,7 @@ export class RabbitmqController extends EventController implements EventControll
sender,
apiKey,
integration,
extra,
}: EmitData): Promise<void> {
if (integration && !integration.includes('rabbitmq')) {
return;
@@ -233,6 +234,7 @@ export class RabbitmqController extends EventController implements EventControll
const logEnabled = configService.get<Log>('LOG').LEVEL.includes('WEBHOOKS');
const message = {
...(extra ?? {}),
event,
instance: instanceName,
data,

View File

@@ -93,6 +93,7 @@ export class SqsController extends EventController implements EventControllerInt
sender,
apiKey,
integration,
extra,
}: EmitData): Promise<void> {
if (integration && !integration.includes('sqs')) {
return;
@@ -128,6 +129,7 @@ export class SqsController extends EventController implements EventControllerInt
const sqsUrl = `https://sqs.${sqsConfig.REGION}.amazonaws.com/${sqsConfig.ACCOUNT_ID}/${queueName}`;
const message = {
...(extra ?? {}),
event,
instance: instanceName,
dataType: 'json',

View File

@@ -65,6 +65,7 @@ export class WebhookController extends EventController implements EventControlle
apiKey,
local,
integration,
extra,
}: EmitData): Promise<void> {
if (integration && !integration.includes('webhook')) {
return;
@@ -90,6 +91,7 @@ export class WebhookController extends EventController implements EventControlle
const regex = /^(https?:\/\/)/;
const webhookData = {
...(extra ?? {}),
event,
instance: instanceName,
data,

View File

@@ -33,10 +33,13 @@ export class WebsocketController extends EventController implements EventControl
const { remoteAddress } = req.socket;
const websocketConfig = configService.get<Websocket>('WEBSOCKET');
const allowedHosts = websocketConfig.ALLOWED_HOSTS || '127.0.0.1,::1,::ffff:127.0.0.1';
const isAllowedHost = allowedHosts
.split(',')
.map((h) => h.trim())
.includes(remoteAddress);
const allowAllHosts = allowedHosts.trim() === '*';
const isAllowedHost =
allowAllHosts ||
allowedHosts
.split(',')
.map((h) => h.trim())
.includes(remoteAddress);
if (params.has('EIO') && isAllowedHost) {
return callback(null, true);
@@ -115,6 +118,7 @@ export class WebsocketController extends EventController implements EventControl
sender,
apiKey,
integration,
extra,
}: EmitData): Promise<void> {
if (integration && !integration.includes('websocket')) {
return;
@@ -127,6 +131,7 @@ export class WebsocketController extends EventController implements EventControl
const configEv = event.replace(/[.-]/gm, '_').toUpperCase();
const logEnabled = configService.get<Log>('LOG').LEVEL.includes('WEBSOCKET');
const message = {
...(extra ?? {}),
event,
instance: instanceName,
data,

View File

@@ -432,7 +432,13 @@ export class ChannelStartupService {
return data;
}
public async sendDataWebhook<T extends object = any>(event: Events, data: T, local = true, integration?: string[]) {
public async sendDataWebhook<T extends object = any>(
event: Events,
data: T,
local = true,
integration?: string[],
extra?: Record<string, any>,
) {
const serverUrl = this.configService.get<HttpServer>('SERVER').URL;
const tzoffset = new Date().getTimezoneOffset() * 60000; //offset in milliseconds
const localISOTime = new Date(Date.now() - tzoffset).toISOString();
@@ -453,6 +459,7 @@ export class ChannelStartupService {
apiKey: expose && instanceApikey ? instanceApikey : null,
local,
integration,
extra,
});
}

View File

@@ -56,7 +56,7 @@ export function makeProxyAgent(proxy: Proxy | string): HttpsProxyAgent<string> |
return selectProxyAgent(proxyUrl);
}
export function makeProxyAgentUndici(proxy: Proxy | string) {
export function makeProxyAgentUndici(proxy: Proxy | string): ProxyAgent {
let proxyUrl: string;
let protocol: string;
@@ -67,7 +67,10 @@ export function makeProxyAgentUndici(proxy: Proxy | string) {
} else {
const { host, password, port, protocol: proto, username } = proxy;
protocol = (proto || 'http').replace(':', '');
if (protocol === 'socks') protocol = 'socks5';
if (protocol === 'socks') {
protocol = 'socks5';
}
const auth = username && password ? `${username}:${password}@` : '';
proxyUrl = `${protocol}://${auth}${host}:${port}`;