mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-12-27 15:47:45 -06:00
Compare commits
28 Commits
6277c5d084
...
2.3.7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd800f2976 | ||
|
|
4f642e17a7 | ||
|
|
afa6d633c6 | ||
|
|
2e3e752719 | ||
|
|
de11e6f9ca | ||
|
|
26e7eefe51 | ||
|
|
b55c9fcab7 | ||
|
|
86b194af5f | ||
|
|
3c1573c400 | ||
|
|
178386594c | ||
|
|
cea1fa0979 | ||
|
|
38be0b49d9 | ||
|
|
04ac880fcc | ||
|
|
3864366e75 | ||
|
|
2756d7e61c | ||
|
|
bb36bfe424 | ||
|
|
abd0351f8f | ||
|
|
1c3a7ab027 | ||
|
|
930d32df3a | ||
|
|
fa6b5c28a6 | ||
|
|
8e7f348c12 | ||
|
|
08a4795016 | ||
|
|
53a94af3f7 | ||
|
|
302e219f7f | ||
|
|
1e036ba3ae | ||
|
|
377993e4b0 | ||
|
|
f2c2a6a64a | ||
|
|
e5a249109c |
85
CHANGELOG.md
85
CHANGELOG.md
@@ -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
6
package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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");
|
||||
@@ -132,6 +132,7 @@ model Chat {
|
||||
instanceId String
|
||||
unreadMessages Int @default(0)
|
||||
|
||||
@@unique([instanceId, remoteJid])
|
||||
@@index([instanceId])
|
||||
@@index([remoteJid])
|
||||
}
|
||||
|
||||
@@ -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: [
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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}`;
|
||||
|
||||
Reference in New Issue
Block a user