mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-14 01:41:24 -06:00
Merge branch 'release/1.1.4'
This commit is contained in:
commit
9b59895ad2
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,6 +2,8 @@
|
||||
/dist
|
||||
/node_modules
|
||||
|
||||
/Docker/.env
|
||||
|
||||
# Logs
|
||||
logs/**.json
|
||||
*.log
|
||||
@ -12,6 +14,7 @@ yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
/docker-compose-data
|
||||
/docker-data
|
||||
|
||||
# Package
|
||||
/yarn.lock
|
||||
|
16
CHANGELOG.md
16
CHANGELOG.md
@ -1,3 +1,19 @@
|
||||
# 1.1.4 (2023-07-08 11:01)
|
||||
|
||||
### Features
|
||||
|
||||
* Route to send status broadcast
|
||||
* Added verbose logs
|
||||
* Insert allContacts in payload of endpoint sendStatus
|
||||
|
||||
### Fixed
|
||||
|
||||
* Adjusted set in webhook to go empty when enabled false
|
||||
* Adjust in store files
|
||||
* Fixed the problem when do not save contacts when receive messages
|
||||
* Changed owner of the jid for instanceName
|
||||
* Create .env for installation in docker
|
||||
|
||||
# 1.1.3 (2023-07-06 11:43)
|
||||
|
||||
### Features
|
||||
|
91
Docker/.env.example
Normal file
91
Docker/.env.example
Normal file
@ -0,0 +1,91 @@
|
||||
CORS_ORIGIN='*' # Or separate by commas - ex.: 'yourdomain1.com, yourdomain2.com'
|
||||
CORS_METHODS='POST,GET,PUT,DELETE'
|
||||
CORS_CREDENTIALS=true
|
||||
|
||||
# Determine the logs to be displayed
|
||||
LOG_LEVEL='ERROR,WARN,DEBUG,INFO,LOG,VERBOSE,DARK,WEBHOOKS'
|
||||
LOG_COLOR=true
|
||||
LOG_BAILEYS=error # "fatal" | "error" | "warn" | "info" | "debug" | "trace"
|
||||
|
||||
# Determine how long the instance should be deleted from memory in case of no connection.
|
||||
# Default time: 5 minutes
|
||||
# If you don't even want an expiration, enter the value false
|
||||
DEL_INSTANCE=false
|
||||
|
||||
# Temporary data storage
|
||||
STORE_MESSAGES=true
|
||||
STORE_MESSAGE_UP=true
|
||||
STORE_CONTACTS=true
|
||||
STORE_CHATS=true
|
||||
CLEAN_STORE_CLEANING_INTERVAL=7200 # seconds === 2h
|
||||
CLEAN_STORE_MESSAGES=true
|
||||
CLEAN_STORE_MESSAGE_UP=true
|
||||
CLEAN_STORE_CONTACTS=true
|
||||
CLEAN_STORE_CHATS=true
|
||||
|
||||
# Permanent data storage
|
||||
DATABASE_ENABLED=false
|
||||
DATABASE_CONNECTION_URI=mongodb://root:root@mongodb:27017/?authSource=admin&readPreference=primary&ssl=false&directConnection=true
|
||||
DATABASE_CONNECTION_DB_PREFIX_NAME=evolution
|
||||
|
||||
# Choose the data you want to save in the application's database or store
|
||||
DATABASE_SAVE_DATA_INSTANCE=true
|
||||
DATABASE_SAVE_DATA_OLD_MESSAGE=false
|
||||
DATABASE_SAVE_DATA_NEW_MESSAGE=true
|
||||
DATABASE_SAVE_MESSAGE_UPDATE=true
|
||||
DATABASE_SAVE_DATA_CONTACTS=true
|
||||
DATABASE_SAVE_DATA_CHATS=true
|
||||
|
||||
REDIS_ENABLED=false
|
||||
REDIS_URI=redis://redis:6379/1
|
||||
REDIS_PREFIX_KEY=evolution
|
||||
|
||||
# Webhook Settings
|
||||
## Define a global webhook that will listen for enabled events from all instances
|
||||
WEBHOOK_GLOBAL_URL='<url>'
|
||||
WEBHOOK_GLOBAL_ENABLED=false
|
||||
# With this option activated, you work with a url per webhook event, respecting the global url and the name of each event
|
||||
WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS=false
|
||||
## Set the events you want to hear
|
||||
WEBHOOK_EVENTS_APPLICATION_STARTUP=false
|
||||
WEBHOOK_EVENTS_QRCODE_UPDATED=true
|
||||
WEBHOOK_EVENTS_MESSAGES_SET=true
|
||||
WEBHOOK_EVENTS_MESSAGES_UPSERT=true
|
||||
WEBHOOK_EVENTS_MESSAGES_UPDATE=true
|
||||
WEBHOOK_EVENTS_CONTACTS_SET=true
|
||||
WEBHOOK_EVENTS_CONTACTS_UPSERT=true
|
||||
WEBHOOK_EVENTS_CONTACTS_UPDATE=true
|
||||
WEBHOOK_EVENTS_PRESENCE_UPDATE=true
|
||||
WEBHOOK_EVENTS_CHATS_SET=true
|
||||
WEBHOOK_EVENTS_CHATS_UPSERT=true
|
||||
WEBHOOK_EVENTS_CHATS_UPDATE=true
|
||||
WEBHOOK_EVENTS_CHATS_DELETE=true
|
||||
WEBHOOK_EVENTS_GROUPS_UPSERT=true
|
||||
WEBHOOK_EVENTS_GROUPS_UPDATE=true
|
||||
WEBHOOK_EVENTS_GROUP_PARTICIPANTS_UPDATE=true
|
||||
WEBHOOK_EVENTS_CONNECTION_UPDATE=true
|
||||
# This event fires every time a new token is requested via the refresh route
|
||||
WEBHOOK_EVENTS_NEW_JWT_TOKEN=true
|
||||
|
||||
# Name that will be displayed on smartphone connection
|
||||
CONFIG_SESSION_PHONE_CLIENT=Evolution API
|
||||
CONFIG_SESSION_PHONE_NAME=chrome # chrome | firefox | edge | opera | safari
|
||||
|
||||
# Set qrcode display limit
|
||||
QRCODE_LIMIT=30
|
||||
|
||||
# Defines an authentication type for the api
|
||||
AUTHENTICATION_TYPE='apikey' # jwt or 'apikey'
|
||||
## Define a global apikey to access all instances.
|
||||
### OBS: This key must be inserted in the request header to create an instance.
|
||||
AUTHENTICATION_API_KEY='B6D711FCDE4D4FD5936544120E713976'
|
||||
AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES=true
|
||||
## Set the secret key to encrypt and decrypt your token and its expiration time
|
||||
AUTHENTICATION_JWT_EXPIRIN_IN=0 # seconds - 3600s ===1h | zero (0) - never expires
|
||||
AUTHENTICATION_JWT_SECRET='L0YWtjb2w554WFqPG'
|
||||
# Set the instance name and webhook url to create an instance in init the application
|
||||
# With this option activated, you work with a url per webhook event, respecting the local url and the name of each event
|
||||
AUTHENTICATION_INSTANCE_MODE=server # container or server
|
||||
# if you are using container mode, set the container name and the webhook url to default instance
|
||||
AUTHENTICATION_INSTANCE_NAME=evolution
|
||||
AUTHENTICATION_INSTANCE_WEBHOOK_URL=<url>
|
@ -7,16 +7,6 @@ networks:
|
||||
services:
|
||||
redis:
|
||||
image: redis:latest
|
||||
command: >
|
||||
redis-server
|
||||
--port 6379
|
||||
--appendonly yes
|
||||
--save 900 1
|
||||
--save 300 10
|
||||
--save 60 10000
|
||||
--appendfsync everysec
|
||||
volumes:
|
||||
- evolution_redis:/data
|
||||
container_name: redis
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
@ -48,6 +48,7 @@ ENV DATABASE_SAVE_DATA_CHATS=$DATABASE_SAVE_DATA_CHATS
|
||||
|
||||
ENV REDIS_ENABLED=$REDIS_ENABLED
|
||||
ENV REDIS_URI=$REDIS_URI
|
||||
ENV REDIS_PREFIX_KEY=$REDIS_PREFIX_KEY
|
||||
|
||||
ENV WEBHOOK_GLOBAL_URL=$WEBHOOK_GLOBAL_URL
|
||||
ENV WEBHOOK_GLOBAL_ENABLED=$WEBHOOK_GLOBAL_ENABLED
|
||||
|
@ -8,89 +8,14 @@ services:
|
||||
api:
|
||||
container_name: evolution_api
|
||||
image: evolution/api:local
|
||||
restart: always
|
||||
ports:
|
||||
- 8080:8080
|
||||
volumes:
|
||||
- evolution_instances:/evolution/instances
|
||||
- evolution_store:/evolution/store
|
||||
environment:
|
||||
- LOG_LEVEL=ERROR,WARN,DEBUG,INFO,LOG,VERBOSE,DARK,WEBHOOKS
|
||||
- LOG_BAILEYS=error
|
||||
# Determine how long the instance should be deleted from memory in case of no connection.
|
||||
# Default time: 5 minutes
|
||||
# If you don't even want an expiration, enter the value false
|
||||
- DEL_INSTANCE=false # 5 or false
|
||||
# Temporary data storage
|
||||
- STORE_MESSAGES=true
|
||||
- STORE_MESSAGE_UP=true
|
||||
- STORE_CONTACTS=true
|
||||
- STORE_CHATS=true
|
||||
- CLEAN_STORE_CLEANING_INTERVAL=7200 # seconds === 2h
|
||||
- CLEAN_STORE_MESSAGES=true
|
||||
- CLEAN_STORE_MESSAGE_UP=true
|
||||
- CLEAN_STORE_CONTACTS=true
|
||||
- CLEAN_STORE_CHATS=true
|
||||
# Permanent data storage
|
||||
- DATABASE_ENABLED=false
|
||||
- DATABASE_CONNECTION_URI=mongodb://root:root@mongodb:27017/?authSource=admin&readPreference=primary&ssl=false&directConnection=true
|
||||
- DATABASE_CONNECTION_DB_PREFIX_NAME=evolution
|
||||
# Choose the data you want to save in the application's database or store
|
||||
- DATABASE_SAVE_DATA_INSTANCE=true
|
||||
- DATABASE_SAVE_DATA_OLD_MESSAGE=false
|
||||
- DATABASE_SAVE_DATA_NEW_MESSAGE=true
|
||||
- DATABASE_SAVE_MESSAGE_UPDATE=true
|
||||
- DATABASE_SAVE_DATA_CONTACTS=true
|
||||
- DATABASE_SAVE_DATA_CHATS=true
|
||||
- REDIS_ENABLED=true
|
||||
- REDIS_URI=redis://redis:6379/1
|
||||
- REDIS_PREFIX_KEY=evolution
|
||||
# Webhook Settings
|
||||
# Define a global webhook that will listen for enabled events from all instances
|
||||
- WEBHOOK_GLOBAL_URL=<url>
|
||||
- WEBHOOK_GLOBAL_ENABLED=false
|
||||
# With this option activated, you work with a url per webhook event, respecting the global url and the name of each event
|
||||
- WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS=false
|
||||
# Automatically maps webhook paths
|
||||
# Set the events you want to hear
|
||||
- WEBHOOK_EVENTS_APPLICATION_STARTUP=false
|
||||
- WEBHOOK_EVENTS_QRCODE_UPDATED=true
|
||||
- WEBHOOK_EVENTS_MESSAGES_SET=true
|
||||
- WEBHOOK_EVENTS_MESSAGES_UPSERT=true
|
||||
- WEBHOOK_EVENTS_MESSAGES_UPDATE=true
|
||||
- WEBHOOK_EVENTS_CONTACTS_SET=true
|
||||
- WEBHOOK_EVENTS_CONTACTS_UPSERT=true
|
||||
- WEBHOOK_EVENTS_CONTACTS_UPDATE=true
|
||||
- WEBHOOK_EVENTS_PRESENCE_UPDATE=true
|
||||
- WEBHOOK_EVENTS_CHATS_SET=true
|
||||
- WEBHOOK_EVENTS_CHATS_UPSERT=true
|
||||
- WEBHOOK_EVENTS_CHATS_UPDATE=true
|
||||
- WEBHOOK_EVENTS_CHATS_DELETE=true
|
||||
- WEBHOOK_EVENTS_GROUPS_UPSERT=true
|
||||
- WEBHOOK_EVENTS_GROUPS_UPDATE=true
|
||||
- WEBHOOK_EVENTS_GROUP_PARTICIPANTS_UPDATE=true
|
||||
- WEBHOOK_EVENTS_CONNECTION_UPDATE=true
|
||||
# This event fires every time a new token is requested via the refresh route
|
||||
- WEBHOOK_EVENTS_NEW_JWT_TOKEN=true
|
||||
# Name that will be displayed on smartphone connection
|
||||
- CONFIG_SESSION_PHONE_CLIENT=Evolution API
|
||||
- CONFIG_SESSION_PHONE_NAME=chrome # chrome | firefox | edge | opera | safari
|
||||
# Set qrcode display limit
|
||||
- QRCODE_LIMIT=30
|
||||
# Defines an authentication type for the api
|
||||
- AUTHENTICATION_TYPE=apikey # jwt or apikey
|
||||
# Define a global apikey to access all instances
|
||||
# OBS: This key must be inserted in the request header to create an instance.
|
||||
- AUTHENTICATION_API_KEY=B6D711FCDE4D4FD5936544120E713976
|
||||
# Expose the api key on return from fetch instances
|
||||
- AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES=true
|
||||
# Set the secret key to encrypt and decrypt your token and its expiration time.
|
||||
- AUTHENTICATION_JWT_EXPIRIN_IN=0 # seconds - 3600s === 1h | zero (0) - never expires
|
||||
# Set the instance name and webhook url to create an instance in init the application
|
||||
# With this option activated, you work with a url per webhook event, respecting the local url and the name of each event
|
||||
- AUTHENTICATION_INSTANCE_MODE=server # container or server
|
||||
# if you are using container mode, set the container name and the webhook url to default instance
|
||||
- AUTHENTICATION_INSTANCE_NAME=evolution
|
||||
- AUTHENTICATION_INSTANCE_WEBHOOK_URL=<url>
|
||||
env_file:
|
||||
- ./Docker/.env
|
||||
command: ['node', './dist/src/main.js']
|
||||
networks:
|
||||
- evolution-net
|
||||
|
11
package.json
11
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "evolution-api",
|
||||
"version": "1.1.3",
|
||||
"version": "1.1.4",
|
||||
"description": "Rest api for communication with WhatsApp",
|
||||
"main": "./dist/src/main.js",
|
||||
"scripts": {
|
||||
@ -12,7 +12,7 @@
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/DavidsonGomes/evolution-api.git"
|
||||
"url": "git+https://github.com/EvolutionAPI/evolution-api.git"
|
||||
},
|
||||
"keywords": [
|
||||
"chat",
|
||||
@ -36,14 +36,14 @@
|
||||
},
|
||||
"license": "GPL-3.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/DavidsonGomes/evolution-api/issues"
|
||||
"url": "https://github.com/EvolutionAPI/evolution-api/issues"
|
||||
},
|
||||
"homepage": "https://github.com/DavidsonGomes/evolution-api#readme",
|
||||
"homepage": "https://github.com/EvolutionAPI/evolution-api#readme",
|
||||
"dependencies": {
|
||||
"@adiwajshing/keyed-db": "^0.2.4",
|
||||
"@ffmpeg-installer/ffmpeg": "^1.1.0",
|
||||
"@hapi/boom": "^10.0.1",
|
||||
"@whiskeysockets/baileys": "^6.3.0",
|
||||
"@whiskeysockets/baileys": "github:EvolutionAPI/Baileys",
|
||||
"axios": "^1.3.5",
|
||||
"class-validator": "^0.13.2",
|
||||
"compression": "^1.7.4",
|
||||
@ -65,6 +65,7 @@
|
||||
"node-cache": "^5.1.2",
|
||||
"node-mime-types": "^1.1.0",
|
||||
"pino": "^8.11.0",
|
||||
"proxy-agent": "^6.2.1",
|
||||
"qrcode": "^1.5.1",
|
||||
"qrcode-terminal": "^0.12.0",
|
||||
"redis": "^4.6.5",
|
||||
|
@ -4,3 +4,4 @@ export const ROOT_DIR = process.cwd();
|
||||
export const INSTANCE_DIR = join(ROOT_DIR, 'instances');
|
||||
export const SRC_DIR = join(ROOT_DIR, 'src');
|
||||
export const AUTH_DIR = join(ROOT_DIR, 'store', 'auth');
|
||||
export const STORE_DIR = join(ROOT_DIR, 'store');
|
||||
|
@ -104,9 +104,11 @@ export class RedisCache {
|
||||
public async delAll(hash?: string) {
|
||||
try {
|
||||
this.logger.verbose('instance delAll: ' + hash);
|
||||
return await this.client.del(
|
||||
const result = await this.client.del(
|
||||
hash || this.redisEnv.PREFIX_KEY + ':' + this.instanceName,
|
||||
);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ export const instanceNameSchema: JSONSchema7 = {
|
||||
webhook_by_events: { type: 'boolean' },
|
||||
events: {
|
||||
type: 'array',
|
||||
minItems: 1,
|
||||
minItems: 0,
|
||||
items: {
|
||||
type: 'string',
|
||||
enum: [
|
||||
@ -189,6 +189,37 @@ export const pollMessageSchema: JSONSchema7 = {
|
||||
required: ['pollMessage', 'number'],
|
||||
};
|
||||
|
||||
export const statusMessageSchema: JSONSchema7 = {
|
||||
$id: v4(),
|
||||
type: 'object',
|
||||
properties: {
|
||||
statusMessage: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
type: { type: 'string', enum: ['text', 'image', 'audio', 'video'] },
|
||||
content: { type: 'string' },
|
||||
caption: { type: 'string' },
|
||||
backgroundColor: { type: 'string' },
|
||||
font: { type: 'integer', minimum: 0, maximum: 5 },
|
||||
statusJidList: {
|
||||
type: 'array',
|
||||
minItems: 1,
|
||||
uniqueItems: true,
|
||||
items: {
|
||||
type: 'string',
|
||||
pattern: '^\\d+',
|
||||
description: '"statusJidList" must be an array of numeric strings',
|
||||
},
|
||||
},
|
||||
allContacts: { type: 'boolean', enum: [true, false] },
|
||||
},
|
||||
required: ['type', 'content'],
|
||||
...isNotEmpty('type', 'content'),
|
||||
},
|
||||
},
|
||||
required: ['statusMessage'],
|
||||
};
|
||||
|
||||
export const mediaMessageSchema: JSONSchema7 = {
|
||||
$id: v4(),
|
||||
type: 'object',
|
||||
@ -795,7 +826,7 @@ export const webhookSchema: JSONSchema7 = {
|
||||
enabled: { type: 'boolean', enum: [true, false] },
|
||||
events: {
|
||||
type: 'array',
|
||||
minItems: 1,
|
||||
minItems: 0,
|
||||
items: {
|
||||
type: 'string',
|
||||
enum: [
|
||||
|
@ -6,7 +6,8 @@ import { ROOT_DIR } from '../../config/path.config';
|
||||
export type IInsert = { insertCount: number };
|
||||
|
||||
export interface IRepository {
|
||||
insert(data: any, saveDb?: boolean): Promise<IInsert>;
|
||||
insert(data: any, instanceName: string, saveDb?: boolean): Promise<IInsert>;
|
||||
update(data: any, instanceName: string, saveDb?: boolean): Promise<IInsert>;
|
||||
find(query: any): Promise<any>;
|
||||
delete(query: any, force?: boolean): Promise<any>;
|
||||
|
||||
@ -45,9 +46,14 @@ export abstract class Repository implements IRepository {
|
||||
}
|
||||
};
|
||||
|
||||
public insert(data: any, saveDb = false): Promise<IInsert> {
|
||||
public insert(data: any, instanceName: string, saveDb = false): Promise<IInsert> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
public update(data: any, instanceName: string, saveDb = false): Promise<IInsert> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
public find(query: any): Promise<any> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
@ -16,31 +16,40 @@ import { ContactQuery } from '../repository/contact.repository';
|
||||
import { MessageQuery } from '../repository/message.repository';
|
||||
import { MessageUpQuery } from '../repository/messageUp.repository';
|
||||
import { WAMonitoringService } from '../services/monitor.service';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
|
||||
const logger = new Logger('ChatController');
|
||||
|
||||
export class ChatController {
|
||||
constructor(private readonly waMonitor: WAMonitoringService) {}
|
||||
|
||||
public async whatsappNumber({ instanceName }: InstanceDto, data: WhatsAppNumberDto) {
|
||||
logger.verbose('requested whatsappNumber from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].whatsappNumber(data);
|
||||
}
|
||||
|
||||
public async readMessage({ instanceName }: InstanceDto, data: ReadMessageDto) {
|
||||
logger.verbose('requested readMessage from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].markMessageAsRead(data);
|
||||
}
|
||||
|
||||
public async archiveChat({ instanceName }: InstanceDto, data: ArchiveChatDto) {
|
||||
logger.verbose('requested archiveChat from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].archiveChat(data);
|
||||
}
|
||||
|
||||
public async deleteMessage({ instanceName }: InstanceDto, data: DeleteMessage) {
|
||||
logger.verbose('requested deleteMessage from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].deleteMessage(data);
|
||||
}
|
||||
|
||||
public async fetchProfilePicture({ instanceName }: InstanceDto, data: NumberDto) {
|
||||
logger.verbose('requested fetchProfilePicture from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].profilePicture(data.number);
|
||||
}
|
||||
|
||||
public async fetchContacts({ instanceName }: InstanceDto, query: ContactQuery) {
|
||||
logger.verbose('requested fetchContacts from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].fetchContacts(query);
|
||||
}
|
||||
|
||||
@ -48,22 +57,29 @@ export class ChatController {
|
||||
{ instanceName }: InstanceDto,
|
||||
data: getBase64FromMediaMessageDto,
|
||||
) {
|
||||
logger.verbose(
|
||||
'requested getBase64FromMediaMessage from ' + instanceName + ' instance',
|
||||
);
|
||||
return await this.waMonitor.waInstances[instanceName].getBase64FromMediaMessage(data);
|
||||
}
|
||||
|
||||
public async fetchMessages({ instanceName }: InstanceDto, query: MessageQuery) {
|
||||
logger.verbose('requested fetchMessages from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].fetchMessages(query);
|
||||
}
|
||||
|
||||
public async fetchStatusMessage({ instanceName }: InstanceDto, query: MessageUpQuery) {
|
||||
logger.verbose('requested fetchStatusMessage from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].fetchStatusMessage(query);
|
||||
}
|
||||
|
||||
public async fetchChats({ instanceName }: InstanceDto) {
|
||||
logger.verbose('requested fetchChats from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].fetchChats();
|
||||
}
|
||||
|
||||
public async fetchPrivacySettings({ instanceName }: InstanceDto) {
|
||||
logger.verbose('requested fetchPrivacySettings from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].fetchPrivacySettings();
|
||||
}
|
||||
|
||||
@ -71,6 +87,7 @@ export class ChatController {
|
||||
{ instanceName }: InstanceDto,
|
||||
data: PrivacySettingDto,
|
||||
) {
|
||||
logger.verbose('requested updatePrivacySettings from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].updatePrivacySettings(data);
|
||||
}
|
||||
|
||||
@ -78,12 +95,14 @@ export class ChatController {
|
||||
{ instanceName }: InstanceDto,
|
||||
data: ProfilePictureDto,
|
||||
) {
|
||||
logger.verbose('requested fetchBusinessProfile from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].fetchBusinessProfile(
|
||||
data.number,
|
||||
);
|
||||
}
|
||||
|
||||
public async updateProfileName({ instanceName }: InstanceDto, data: ProfileNameDto) {
|
||||
logger.verbose('requested updateProfileName from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].updateProfileName(data.name);
|
||||
}
|
||||
|
||||
@ -91,6 +110,7 @@ export class ChatController {
|
||||
{ instanceName }: InstanceDto,
|
||||
data: ProfileStatusDto,
|
||||
) {
|
||||
logger.verbose('requested updateProfileStatus from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].updateProfileStatus(
|
||||
data.status,
|
||||
);
|
||||
@ -100,6 +120,7 @@ export class ChatController {
|
||||
{ instanceName }: InstanceDto,
|
||||
data: ProfilePictureDto,
|
||||
) {
|
||||
logger.verbose('requested updateProfilePicture from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].updateProfilePicture(
|
||||
data.picture,
|
||||
);
|
||||
@ -109,6 +130,7 @@ export class ChatController {
|
||||
{ instanceName }: InstanceDto,
|
||||
data: ProfilePictureDto,
|
||||
) {
|
||||
logger.verbose('requested removeProfilePicture from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].removeProfilePicture();
|
||||
}
|
||||
}
|
||||
|
@ -12,21 +12,31 @@ import {
|
||||
} from '../dto/group.dto';
|
||||
import { InstanceDto } from '../dto/instance.dto';
|
||||
import { WAMonitoringService } from '../services/monitor.service';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
|
||||
const logger = new Logger('ChatController');
|
||||
|
||||
export class GroupController {
|
||||
constructor(private readonly waMonitor: WAMonitoringService) {}
|
||||
|
||||
public async createGroup(instance: InstanceDto, create: CreateGroupDto) {
|
||||
logger.verbose('requested createGroup from ' + instance.instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instance.instanceName].createGroup(create);
|
||||
}
|
||||
|
||||
public async updateGroupPicture(instance: InstanceDto, update: GroupPictureDto) {
|
||||
logger.verbose(
|
||||
'requested updateGroupPicture from ' + instance.instanceName + ' instance',
|
||||
);
|
||||
return await this.waMonitor.waInstances[instance.instanceName].updateGroupPicture(
|
||||
update,
|
||||
);
|
||||
}
|
||||
|
||||
public async updateGroupSubject(instance: InstanceDto, update: GroupSubjectDto) {
|
||||
logger.verbose(
|
||||
'requested updateGroupSubject from ' + instance.instanceName + ' instance',
|
||||
);
|
||||
return await this.waMonitor.waInstances[instance.instanceName].updateGroupSubject(
|
||||
update,
|
||||
);
|
||||
@ -36,38 +46,54 @@ export class GroupController {
|
||||
instance: InstanceDto,
|
||||
update: GroupDescriptionDto,
|
||||
) {
|
||||
logger.verbose(
|
||||
'requested updateGroupDescription from ' + instance.instanceName + ' instance',
|
||||
);
|
||||
return await this.waMonitor.waInstances[instance.instanceName].updateGroupDescription(
|
||||
update,
|
||||
);
|
||||
}
|
||||
|
||||
public async findGroupInfo(instance: InstanceDto, groupJid: GroupJid) {
|
||||
logger.verbose('requested findGroupInfo from ' + instance.instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instance.instanceName].findGroup(groupJid);
|
||||
}
|
||||
|
||||
public async fetchAllGroups(instance: InstanceDto) {
|
||||
logger.verbose(
|
||||
'requested fetchAllGroups from ' + instance.instanceName + ' instance',
|
||||
);
|
||||
return await this.waMonitor.waInstances[instance.instanceName].fetchAllGroups();
|
||||
}
|
||||
|
||||
public async inviteCode(instance: InstanceDto, groupJid: GroupJid) {
|
||||
logger.verbose('requested inviteCode from ' + instance.instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instance.instanceName].inviteCode(groupJid);
|
||||
}
|
||||
|
||||
public async inviteInfo(instance: InstanceDto, inviteCode: GroupInvite) {
|
||||
logger.verbose('requested inviteInfo from ' + instance.instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instance.instanceName].inviteInfo(inviteCode);
|
||||
}
|
||||
|
||||
public async sendInvite(instance: InstanceDto, data: GroupSendInvite) {
|
||||
logger.verbose('requested sendInvite from ' + instance.instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instance.instanceName].sendInvite(data);
|
||||
}
|
||||
|
||||
public async revokeInviteCode(instance: InstanceDto, groupJid: GroupJid) {
|
||||
logger.verbose(
|
||||
'requested revokeInviteCode from ' + instance.instanceName + ' instance',
|
||||
);
|
||||
return await this.waMonitor.waInstances[instance.instanceName].revokeInviteCode(
|
||||
groupJid,
|
||||
);
|
||||
}
|
||||
|
||||
public async findParticipants(instance: InstanceDto, groupJid: GroupJid) {
|
||||
logger.verbose(
|
||||
'requested findParticipants from ' + instance.instanceName + ' instance',
|
||||
);
|
||||
return await this.waMonitor.waInstances[instance.instanceName].findParticipants(
|
||||
groupJid,
|
||||
);
|
||||
@ -77,22 +103,32 @@ export class GroupController {
|
||||
instance: InstanceDto,
|
||||
update: GroupUpdateParticipantDto,
|
||||
) {
|
||||
logger.verbose(
|
||||
'requested updateGParticipate from ' + instance.instanceName + ' instance',
|
||||
);
|
||||
return await this.waMonitor.waInstances[instance.instanceName].updateGParticipant(
|
||||
update,
|
||||
);
|
||||
}
|
||||
|
||||
public async updateGSetting(instance: InstanceDto, update: GroupUpdateSettingDto) {
|
||||
logger.verbose(
|
||||
'requested updateGSetting from ' + instance.instanceName + ' instance',
|
||||
);
|
||||
return await this.waMonitor.waInstances[instance.instanceName].updateGSetting(update);
|
||||
}
|
||||
|
||||
public async toggleEphemeral(instance: InstanceDto, update: GroupToggleEphemeralDto) {
|
||||
logger.verbose(
|
||||
'requested toggleEphemeral from ' + instance.instanceName + ' instance',
|
||||
);
|
||||
return await this.waMonitor.waInstances[instance.instanceName].toggleEphemeral(
|
||||
update,
|
||||
);
|
||||
}
|
||||
|
||||
public async leaveGroup(instance: InstanceDto, groupJid: GroupJid) {
|
||||
logger.verbose('requested leaveGroup from ' + instance.instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instance.instanceName].leaveGroup(groupJid);
|
||||
}
|
||||
}
|
||||
|
@ -33,9 +33,13 @@ export class InstanceController {
|
||||
qrcode,
|
||||
token,
|
||||
}: InstanceDto) {
|
||||
this.logger.verbose('requested createInstance from ' + instanceName + ' instance');
|
||||
|
||||
const mode = this.configService.get<Auth>('AUTHENTICATION').INSTANCE.MODE;
|
||||
|
||||
if (mode === 'container') {
|
||||
this.logger.verbose('container mode');
|
||||
|
||||
if (Object.keys(this.waMonitor.waInstances).length > 0) {
|
||||
throw new BadRequestException([
|
||||
'Instance already created',
|
||||
@ -43,8 +47,10 @@ export class InstanceController {
|
||||
]);
|
||||
}
|
||||
|
||||
this.logger.verbose('checking duplicate token');
|
||||
await this.authService.checkDuplicateToken(token);
|
||||
|
||||
this.logger.verbose('creating instance');
|
||||
const instance = new WAStartupService(
|
||||
this.configService,
|
||||
this.eventEmitter,
|
||||
@ -52,9 +58,12 @@ export class InstanceController {
|
||||
this.cache,
|
||||
);
|
||||
instance.instanceName = instanceName;
|
||||
this.logger.verbose('instance: ' + instance.instanceName + ' created');
|
||||
|
||||
this.waMonitor.waInstances[instance.instanceName] = instance;
|
||||
this.waMonitor.delInstanceTime(instance.instanceName);
|
||||
|
||||
this.logger.verbose('generating hash');
|
||||
const hash = await this.authService.generateHash(
|
||||
{
|
||||
instanceName: instance.instanceName,
|
||||
@ -62,9 +71,12 @@ export class InstanceController {
|
||||
token,
|
||||
);
|
||||
|
||||
this.logger.verbose('hash: ' + hash + ' generated');
|
||||
|
||||
let getEvents: string[];
|
||||
|
||||
if (webhook) {
|
||||
this.logger.verbose('creating webhook');
|
||||
try {
|
||||
this.webhookService.create(instance, {
|
||||
enabled: true,
|
||||
@ -79,6 +91,17 @@ export class InstanceController {
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.verbose('instance created');
|
||||
this.logger.verbose({
|
||||
instance: {
|
||||
instanceName: instance.instanceName,
|
||||
status: 'created',
|
||||
},
|
||||
hash,
|
||||
webhook,
|
||||
events: getEvents,
|
||||
});
|
||||
|
||||
return {
|
||||
instance: {
|
||||
instanceName: instance.instanceName,
|
||||
@ -89,8 +112,12 @@ export class InstanceController {
|
||||
events: getEvents,
|
||||
};
|
||||
} else {
|
||||
this.logger.verbose('server mode');
|
||||
|
||||
this.logger.verbose('checking duplicate token');
|
||||
await this.authService.checkDuplicateToken(token);
|
||||
|
||||
this.logger.verbose('creating instance');
|
||||
const instance = new WAStartupService(
|
||||
this.configService,
|
||||
this.eventEmitter,
|
||||
@ -98,9 +125,13 @@ export class InstanceController {
|
||||
this.cache,
|
||||
);
|
||||
instance.instanceName = instanceName;
|
||||
|
||||
this.logger.verbose('instance: ' + instance.instanceName + ' created');
|
||||
|
||||
this.waMonitor.waInstances[instance.instanceName] = instance;
|
||||
this.waMonitor.delInstanceTime(instance.instanceName);
|
||||
|
||||
this.logger.verbose('generating hash');
|
||||
const hash = await this.authService.generateHash(
|
||||
{
|
||||
instanceName: instance.instanceName,
|
||||
@ -108,9 +139,12 @@ export class InstanceController {
|
||||
token,
|
||||
);
|
||||
|
||||
this.logger.verbose('hash: ' + hash + ' generated');
|
||||
|
||||
let getEvents: string[];
|
||||
|
||||
if (webhook) {
|
||||
this.logger.verbose('creating webhook');
|
||||
try {
|
||||
this.webhookService.create(instance, {
|
||||
enabled: true,
|
||||
@ -128,11 +162,25 @@ export class InstanceController {
|
||||
let getQrcode: wa.QrCode;
|
||||
|
||||
if (qrcode) {
|
||||
this.logger.verbose('creating qrcode');
|
||||
await instance.connectToWhatsapp();
|
||||
await delay(2000);
|
||||
getQrcode = instance.qrCode;
|
||||
}
|
||||
|
||||
this.logger.verbose('instance created');
|
||||
this.logger.verbose({
|
||||
instance: {
|
||||
instanceName: instance.instanceName,
|
||||
status: 'created',
|
||||
},
|
||||
hash,
|
||||
webhook,
|
||||
webhook_by_events,
|
||||
events: getEvents,
|
||||
qrcode: getQrcode,
|
||||
});
|
||||
|
||||
return {
|
||||
instance: {
|
||||
instanceName: instance.instanceName,
|
||||
@ -149,11 +197,18 @@ export class InstanceController {
|
||||
|
||||
public async connectToWhatsapp({ instanceName }: InstanceDto) {
|
||||
try {
|
||||
this.logger.verbose(
|
||||
'requested connectToWhatsapp from ' + instanceName + ' instance',
|
||||
);
|
||||
|
||||
const instance = this.waMonitor.waInstances[instanceName];
|
||||
const state = instance?.connectionStatus?.state;
|
||||
|
||||
this.logger.verbose('state: ' + state);
|
||||
|
||||
switch (state) {
|
||||
case 'close':
|
||||
this.logger.verbose('connecting');
|
||||
await instance.connectToWhatsapp();
|
||||
await delay(2000);
|
||||
return instance.qrCode;
|
||||
@ -169,8 +224,12 @@ export class InstanceController {
|
||||
|
||||
public async restartInstance({ instanceName }: InstanceDto) {
|
||||
try {
|
||||
this.logger.verbose('requested restartInstance from ' + instanceName + ' instance');
|
||||
|
||||
this.logger.verbose('deleting instance: ' + instanceName);
|
||||
delete this.waMonitor.waInstances[instanceName];
|
||||
console.log(this.waMonitor.waInstances[instanceName]);
|
||||
|
||||
this.logger.verbose('creating instance: ' + instanceName);
|
||||
const instance = new WAStartupService(
|
||||
this.configService,
|
||||
this.eventEmitter,
|
||||
@ -179,6 +238,10 @@ export class InstanceController {
|
||||
);
|
||||
|
||||
instance.instanceName = instanceName;
|
||||
|
||||
this.logger.verbose('instance: ' + instance.instanceName + ' created');
|
||||
|
||||
this.logger.verbose('connecting instance: ' + instanceName);
|
||||
await instance.connectToWhatsapp();
|
||||
this.waMonitor.waInstances[instance.instanceName] = instance;
|
||||
|
||||
@ -189,11 +252,14 @@ export class InstanceController {
|
||||
}
|
||||
|
||||
public async connectionState({ instanceName }: InstanceDto) {
|
||||
this.logger.verbose('requested connectionState from ' + instanceName + ' instance');
|
||||
return this.waMonitor.waInstances[instanceName]?.connectionStatus;
|
||||
}
|
||||
|
||||
public async fetchInstances({ instanceName }: InstanceDto) {
|
||||
this.logger.verbose('requested fetchInstances from ' + instanceName + ' instance');
|
||||
if (instanceName) {
|
||||
this.logger.verbose('instanceName: ' + instanceName);
|
||||
return this.waMonitor.instanceInfo(instanceName);
|
||||
}
|
||||
|
||||
@ -201,11 +267,14 @@ export class InstanceController {
|
||||
}
|
||||
|
||||
public async logout({ instanceName }: InstanceDto) {
|
||||
this.logger.verbose('requested logout from ' + instanceName + ' instance');
|
||||
try {
|
||||
this.logger.verbose('logging out instance: ' + instanceName);
|
||||
await this.waMonitor.waInstances[instanceName]?.client?.logout(
|
||||
'Log out instance: ' + instanceName,
|
||||
);
|
||||
|
||||
this.logger.verbose('close connection instance: ' + instanceName);
|
||||
this.waMonitor.waInstances[instanceName]?.client?.ws?.close();
|
||||
|
||||
return { error: false, message: 'Instance logged out' };
|
||||
@ -215,7 +284,9 @@ export class InstanceController {
|
||||
}
|
||||
|
||||
public async deleteInstance({ instanceName }: InstanceDto) {
|
||||
this.logger.verbose('requested deleteInstance from ' + instanceName + ' instance');
|
||||
const stateConn = await this.connectionState({ instanceName });
|
||||
|
||||
if (stateConn.state === 'open') {
|
||||
throw new BadRequestException([
|
||||
'Deletion failed',
|
||||
@ -224,10 +295,14 @@ export class InstanceController {
|
||||
}
|
||||
try {
|
||||
if (stateConn.state === 'connecting') {
|
||||
this.logger.verbose('logging out instance: ' + instanceName);
|
||||
|
||||
await this.logout({ instanceName });
|
||||
delete this.waMonitor.waInstances[instanceName];
|
||||
return { error: false, message: 'Instance deleted' };
|
||||
} else {
|
||||
this.logger.verbose('deleting instance: ' + instanceName);
|
||||
|
||||
delete this.waMonitor.waInstances[instanceName];
|
||||
this.eventEmitter.emit('remove.instance', instanceName, 'inner');
|
||||
return { error: false, message: 'Instance deleted' };
|
||||
@ -238,6 +313,7 @@ export class InstanceController {
|
||||
}
|
||||
|
||||
public async refreshToken(_: InstanceDto, oldToken: OldToken) {
|
||||
this.logger.verbose('requested refreshToken');
|
||||
return await this.authService.refreshToken(oldToken);
|
||||
}
|
||||
}
|
||||
|
@ -11,22 +11,35 @@ import {
|
||||
SendMediaDto,
|
||||
SendPollDto,
|
||||
SendReactionDto,
|
||||
SendStatusDto,
|
||||
SendStickerDto,
|
||||
SendTextDto,
|
||||
} from '../dto/sendMessage.dto';
|
||||
import { WAMonitoringService } from '../services/monitor.service';
|
||||
|
||||
import { Logger } from '../../config/logger.config';
|
||||
|
||||
const logger = new Logger('MessageRouter');
|
||||
|
||||
export class SendMessageController {
|
||||
constructor(private readonly waMonitor: WAMonitoringService) {}
|
||||
|
||||
public async sendText({ instanceName }: InstanceDto, data: SendTextDto) {
|
||||
logger.verbose('requested sendText from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].textMessage(data);
|
||||
}
|
||||
|
||||
public async sendMedia({ instanceName }: InstanceDto, data: SendMediaDto) {
|
||||
logger.verbose('requested sendMedia from ' + instanceName + ' instance');
|
||||
if (isBase64(data?.mediaMessage?.media) && !data?.mediaMessage?.fileName) {
|
||||
throw new BadRequestException('For bse64 the file name must be informed.');
|
||||
}
|
||||
logger.verbose(
|
||||
'isURL: ' +
|
||||
isURL(data?.mediaMessage?.media) +
|
||||
', isBase64: ' +
|
||||
isBase64(data?.mediaMessage?.media),
|
||||
);
|
||||
if (isURL(data?.mediaMessage?.media) || isBase64(data?.mediaMessage?.media)) {
|
||||
return await this.waMonitor.waInstances[instanceName].mediaMessage(data);
|
||||
}
|
||||
@ -34,6 +47,14 @@ export class SendMessageController {
|
||||
}
|
||||
|
||||
public async sendSticker({ instanceName }: InstanceDto, data: SendStickerDto) {
|
||||
logger.verbose('requested sendSticker from ' + instanceName + ' instance');
|
||||
|
||||
logger.verbose(
|
||||
'isURL: ' +
|
||||
isURL(data?.stickerMessage?.image) +
|
||||
', isBase64: ' +
|
||||
isBase64(data?.stickerMessage?.image),
|
||||
);
|
||||
if (isURL(data.stickerMessage.image) || isBase64(data.stickerMessage.image)) {
|
||||
return await this.waMonitor.waInstances[instanceName].mediaSticker(data);
|
||||
}
|
||||
@ -41,6 +62,14 @@ export class SendMessageController {
|
||||
}
|
||||
|
||||
public async sendWhatsAppAudio({ instanceName }: InstanceDto, data: SendAudioDto) {
|
||||
logger.verbose('requested sendWhatsAppAudio from ' + instanceName + ' instance');
|
||||
|
||||
logger.verbose(
|
||||
'isURL: ' +
|
||||
isURL(data?.audioMessage?.audio) +
|
||||
', isBase64: ' +
|
||||
isBase64(data?.audioMessage?.audio),
|
||||
);
|
||||
if (isURL(data.audioMessage.audio) || isBase64(data.audioMessage.audio)) {
|
||||
return await this.waMonitor.waInstances[instanceName].audioWhatsapp(data);
|
||||
}
|
||||
@ -48,6 +77,7 @@ export class SendMessageController {
|
||||
}
|
||||
|
||||
public async sendButtons({ instanceName }: InstanceDto, data: SendButtonDto) {
|
||||
logger.verbose('requested sendButtons from ' + instanceName + ' instance');
|
||||
if (
|
||||
isBase64(data.buttonMessage.mediaMessage?.media) &&
|
||||
!data.buttonMessage.mediaMessage?.fileName
|
||||
@ -58,18 +88,22 @@ export class SendMessageController {
|
||||
}
|
||||
|
||||
public async sendLocation({ instanceName }: InstanceDto, data: SendLocationDto) {
|
||||
logger.verbose('requested sendLocation from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].locationMessage(data);
|
||||
}
|
||||
|
||||
public async sendList({ instanceName }: InstanceDto, data: SendListDto) {
|
||||
logger.verbose('requested sendList from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].listMessage(data);
|
||||
}
|
||||
|
||||
public async sendContact({ instanceName }: InstanceDto, data: SendContactDto) {
|
||||
logger.verbose('requested sendContact from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].contactMessage(data);
|
||||
}
|
||||
|
||||
public async sendReaction({ instanceName }: InstanceDto, data: SendReactionDto) {
|
||||
logger.verbose('requested sendReaction from ' + instanceName + ' instance');
|
||||
if (!data.reactionMessage.reaction.match(/[^\(\)\w\sà-ú"-\+]+/)) {
|
||||
throw new BadRequestException('"reaction" must be an emoji');
|
||||
}
|
||||
@ -77,10 +111,17 @@ export class SendMessageController {
|
||||
}
|
||||
|
||||
public async sendPoll({ instanceName }: InstanceDto, data: SendPollDto) {
|
||||
logger.verbose('requested sendPoll from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].pollMessage(data);
|
||||
}
|
||||
|
||||
public async sendStatus({ instanceName }: InstanceDto, data: SendStatusDto) {
|
||||
logger.verbose('requested sendStatus from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].statusMessage(data);
|
||||
}
|
||||
|
||||
public async sendLinkPreview({ instanceName }: InstanceDto, data: SendLinkPreviewDto) {
|
||||
logger.verbose('requested sendLinkPreview from ' + instanceName + ' instance');
|
||||
return await this.waMonitor.waInstances[instanceName].linkPreview(data);
|
||||
}
|
||||
}
|
||||
|
@ -3,18 +3,31 @@ import { BadRequestException } from '../../exceptions';
|
||||
import { InstanceDto } from '../dto/instance.dto';
|
||||
import { WebhookDto } from '../dto/webhook.dto';
|
||||
import { WebhookService } from '../services/webhook.service';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
|
||||
const logger = new Logger('WebhookController');
|
||||
|
||||
export class WebhookController {
|
||||
constructor(private readonly webhookService: WebhookService) {}
|
||||
|
||||
public async createWebhook(instance: InstanceDto, data: WebhookDto) {
|
||||
if (!isURL(data.url, { require_tld: false })) {
|
||||
logger.verbose('requested createWebhook from ' + instance.instanceName + ' instance');
|
||||
|
||||
if (data.enabled && !isURL(data.url, { require_tld: false })) {
|
||||
throw new BadRequestException('Invalid "url" property');
|
||||
}
|
||||
|
||||
if (!data.enabled) {
|
||||
logger.verbose('webhook disabled');
|
||||
data.url = '';
|
||||
data.events = [];
|
||||
}
|
||||
|
||||
return this.webhookService.create(instance, data);
|
||||
}
|
||||
|
||||
public async findWebhook(instance: InstanceDto) {
|
||||
logger.verbose('requested findWebhook from ' + instance.instanceName + ' instance');
|
||||
return this.webhookService.find(instance);
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,16 @@ class linkPreviewMessage {
|
||||
text: string;
|
||||
}
|
||||
|
||||
export class StatusMessage {
|
||||
type: string;
|
||||
content: string;
|
||||
statusJidList?: string[];
|
||||
allContacts?: boolean;
|
||||
caption?: string;
|
||||
backgroundColor?: string;
|
||||
font?: number;
|
||||
}
|
||||
|
||||
class PollMessage {
|
||||
name: string;
|
||||
selectableCount: number;
|
||||
@ -46,6 +56,10 @@ export class SendLinkPreviewDto extends Metadata {
|
||||
linkPreview: linkPreviewMessage;
|
||||
}
|
||||
|
||||
export class SendStatusDto extends Metadata {
|
||||
statusMessage: StatusMessage;
|
||||
}
|
||||
|
||||
export class SendPollDto extends Metadata {
|
||||
pollMessage: PollMessage;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import { IInsert, Repository } from '../abstract/abstract.repository';
|
||||
import { IAuthModel, AuthRaw } from '../models';
|
||||
import { readFileSync } from 'fs';
|
||||
import { AUTH_DIR } from '../../config/path.config';
|
||||
import { InstanceDto } from '../dto/instance.dto';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
|
||||
export class AuthRepository extends Repository {
|
||||
constructor(
|
||||
@ -16,24 +16,35 @@ export class AuthRepository extends Repository {
|
||||
}
|
||||
|
||||
private readonly auth: Auth;
|
||||
private readonly logger = new Logger('AuthRepository');
|
||||
|
||||
public async create(data: AuthRaw, instance: string): Promise<IInsert> {
|
||||
try {
|
||||
this.logger.verbose('creating auth');
|
||||
if (this.dbSettings.ENABLED) {
|
||||
this.logger.verbose('saving auth to db');
|
||||
const insert = await this.authModel.replaceOne(
|
||||
{ _id: instance },
|
||||
{ ...data },
|
||||
{ upsert: true },
|
||||
);
|
||||
|
||||
this.logger.verbose('auth saved to db: ' + insert.modifiedCount + ' auth');
|
||||
return { insertCount: insert.modifiedCount };
|
||||
}
|
||||
|
||||
this.logger.verbose('saving auth to store');
|
||||
|
||||
this.writeStore<AuthRaw>({
|
||||
path: join(AUTH_DIR, this.auth.TYPE),
|
||||
fileName: instance,
|
||||
data,
|
||||
});
|
||||
this.logger.verbose(
|
||||
'auth saved to store in path: ' + join(AUTH_DIR, this.auth.TYPE) + '/' + instance,
|
||||
);
|
||||
|
||||
this.logger.verbose('auth created');
|
||||
return { insertCount: 1 };
|
||||
} catch (error) {
|
||||
return { error } as any;
|
||||
@ -42,10 +53,14 @@ export class AuthRepository extends Repository {
|
||||
|
||||
public async find(instance: string): Promise<AuthRaw> {
|
||||
try {
|
||||
this.logger.verbose('finding auth');
|
||||
if (this.dbSettings.ENABLED) {
|
||||
this.logger.verbose('finding auth in db');
|
||||
return await this.authModel.findOne({ _id: instance });
|
||||
}
|
||||
|
||||
this.logger.verbose('finding auth in store');
|
||||
|
||||
return JSON.parse(
|
||||
readFileSync(join(AUTH_DIR, this.auth.TYPE, instance + '.json'), {
|
||||
encoding: 'utf-8',
|
||||
|
@ -3,6 +3,7 @@ import { ConfigService, StoreConf } from '../../config/env.config';
|
||||
import { IInsert, Repository } from '../abstract/abstract.repository';
|
||||
import { opendirSync, readFileSync, rmSync } from 'fs';
|
||||
import { ChatRaw, IChatModel } from '../models';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
|
||||
export class ChatQuery {
|
||||
where: ChatRaw;
|
||||
@ -16,31 +17,54 @@ export class ChatRepository extends Repository {
|
||||
super(configService);
|
||||
}
|
||||
|
||||
public async insert(data: ChatRaw[], saveDb = false): Promise<IInsert> {
|
||||
private readonly logger = new Logger('ChatRepository');
|
||||
|
||||
public async insert(
|
||||
data: ChatRaw[],
|
||||
instanceName: string,
|
||||
saveDb = false,
|
||||
): Promise<IInsert> {
|
||||
this.logger.verbose('inserting chats');
|
||||
if (data.length === 0) {
|
||||
this.logger.verbose('no chats to insert');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.logger.verbose('saving chats to store');
|
||||
if (this.dbSettings.ENABLED && saveDb) {
|
||||
this.logger.verbose('saving chats to db');
|
||||
const insert = await this.chatModel.insertMany([...data]);
|
||||
|
||||
this.logger.verbose('chats saved to db: ' + insert.length + ' chats');
|
||||
return { insertCount: insert.length };
|
||||
}
|
||||
|
||||
this.logger.verbose('saving chats to store');
|
||||
|
||||
const store = this.configService.get<StoreConf>('STORE');
|
||||
|
||||
if (store.CHATS) {
|
||||
this.logger.verbose('saving chats to store');
|
||||
data.forEach((chat) => {
|
||||
this.writeStore<ChatRaw>({
|
||||
path: join(this.storePath, 'chats', chat.owner),
|
||||
path: join(this.storePath, 'chats', instanceName),
|
||||
fileName: chat.id,
|
||||
data: chat,
|
||||
});
|
||||
this.logger.verbose(
|
||||
'chats saved to store in path: ' +
|
||||
join(this.storePath, 'chats', instanceName) +
|
||||
'/' +
|
||||
chat.id,
|
||||
);
|
||||
});
|
||||
|
||||
this.logger.verbose('chats saved to store');
|
||||
return { insertCount: data.length };
|
||||
}
|
||||
|
||||
this.logger.verbose('chats not saved to store');
|
||||
return { insertCount: 0 };
|
||||
} catch (error) {
|
||||
return error;
|
||||
@ -51,10 +75,14 @@ export class ChatRepository extends Repository {
|
||||
|
||||
public async find(query: ChatQuery): Promise<ChatRaw[]> {
|
||||
try {
|
||||
this.logger.verbose('finding chats');
|
||||
if (this.dbSettings.ENABLED) {
|
||||
this.logger.verbose('finding chats in db');
|
||||
return await this.chatModel.find({ owner: query.where.owner });
|
||||
}
|
||||
|
||||
this.logger.verbose('finding chats in store');
|
||||
|
||||
const chats: ChatRaw[] = [];
|
||||
const openDir = opendirSync(join(this.storePath, 'chats', query.where.owner));
|
||||
for await (const dirent of openDir) {
|
||||
@ -70,6 +98,7 @@ export class ChatRepository extends Repository {
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.verbose('chats found in store: ' + chats.length + ' chats');
|
||||
return chats;
|
||||
} catch (error) {
|
||||
return [];
|
||||
@ -78,10 +107,13 @@ export class ChatRepository extends Repository {
|
||||
|
||||
public async delete(query: ChatQuery) {
|
||||
try {
|
||||
this.logger.verbose('deleting chats');
|
||||
if (this.dbSettings.ENABLED) {
|
||||
this.logger.verbose('deleting chats in db');
|
||||
return await this.chatModel.deleteOne({ ...query.where });
|
||||
}
|
||||
|
||||
this.logger.verbose('deleting chats in store');
|
||||
rmSync(join(this.storePath, 'chats', query.where.owner, query.where.id + '.josn'), {
|
||||
force: true,
|
||||
recursive: true,
|
||||
|
@ -3,6 +3,7 @@ import { join } from 'path';
|
||||
import { ConfigService, StoreConf } from '../../config/env.config';
|
||||
import { ContactRaw, IContactModel } from '../models';
|
||||
import { IInsert, Repository } from '../abstract/abstract.repository';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
|
||||
export class ContactQuery {
|
||||
where: ContactRaw;
|
||||
@ -16,31 +17,121 @@ export class ContactRepository extends Repository {
|
||||
super(configService);
|
||||
}
|
||||
|
||||
public async insert(data: ContactRaw[], saveDb = false): Promise<IInsert> {
|
||||
private readonly logger = new Logger('ContactRepository');
|
||||
|
||||
public async insert(
|
||||
data: ContactRaw[],
|
||||
instanceName: string,
|
||||
saveDb = false,
|
||||
): Promise<IInsert> {
|
||||
this.logger.verbose('inserting contacts');
|
||||
|
||||
if (data.length === 0) {
|
||||
this.logger.verbose('no contacts to insert');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (this.dbSettings.ENABLED && saveDb) {
|
||||
this.logger.verbose('saving contacts to db');
|
||||
|
||||
const insert = await this.contactModel.insertMany([...data]);
|
||||
|
||||
this.logger.verbose('contacts saved to db: ' + insert.length + ' contacts');
|
||||
return { insertCount: insert.length };
|
||||
}
|
||||
|
||||
this.logger.verbose('saving contacts to store');
|
||||
|
||||
const store = this.configService.get<StoreConf>('STORE');
|
||||
|
||||
if (store.CONTACTS) {
|
||||
this.logger.verbose('saving contacts to store');
|
||||
data.forEach((contact) => {
|
||||
this.writeStore({
|
||||
path: join(this.storePath, 'contacts', contact.owner),
|
||||
path: join(this.storePath, 'contacts', instanceName),
|
||||
fileName: contact.id,
|
||||
data: contact,
|
||||
});
|
||||
this.logger.verbose(
|
||||
'contacts saved to store in path: ' +
|
||||
join(this.storePath, 'contacts', instanceName) +
|
||||
'/' +
|
||||
contact.id,
|
||||
);
|
||||
});
|
||||
|
||||
this.logger.verbose('contacts saved to store: ' + data.length + ' contacts');
|
||||
return { insertCount: data.length };
|
||||
}
|
||||
|
||||
this.logger.verbose('contacts not saved');
|
||||
return { insertCount: 0 };
|
||||
} catch (error) {
|
||||
return error;
|
||||
} finally {
|
||||
data = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
public async update(
|
||||
data: ContactRaw[],
|
||||
instanceName: string,
|
||||
saveDb = false,
|
||||
): Promise<IInsert> {
|
||||
try {
|
||||
this.logger.verbose('updating contacts');
|
||||
|
||||
if (data.length === 0) {
|
||||
this.logger.verbose('no contacts to update');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.dbSettings.ENABLED && saveDb) {
|
||||
this.logger.verbose('updating contacts in db');
|
||||
|
||||
const contacts = data.map((contact) => {
|
||||
return {
|
||||
updateOne: {
|
||||
filter: { id: contact.id },
|
||||
update: { ...contact },
|
||||
upsert: true,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const { nModified } = await this.contactModel.bulkWrite(contacts);
|
||||
|
||||
this.logger.verbose('contacts updated in db: ' + nModified + ' contacts');
|
||||
return { insertCount: nModified };
|
||||
}
|
||||
|
||||
this.logger.verbose('updating contacts in store');
|
||||
|
||||
const store = this.configService.get<StoreConf>('STORE');
|
||||
|
||||
if (store.CONTACTS) {
|
||||
this.logger.verbose('updating contacts in store');
|
||||
data.forEach((contact) => {
|
||||
this.writeStore({
|
||||
path: join(this.storePath, 'contacts', instanceName),
|
||||
fileName: contact.id,
|
||||
data: contact,
|
||||
});
|
||||
this.logger.verbose(
|
||||
'contacts updated in store in path: ' +
|
||||
join(this.storePath, 'contacts', instanceName) +
|
||||
'/' +
|
||||
contact.id,
|
||||
);
|
||||
});
|
||||
|
||||
this.logger.verbose('contacts updated in store: ' + data.length + ' contacts');
|
||||
|
||||
return { insertCount: data.length };
|
||||
}
|
||||
|
||||
this.logger.verbose('contacts not updated');
|
||||
return { insertCount: 0 };
|
||||
} catch (error) {
|
||||
return error;
|
||||
@ -51,11 +142,16 @@ export class ContactRepository extends Repository {
|
||||
|
||||
public async find(query: ContactQuery): Promise<ContactRaw[]> {
|
||||
try {
|
||||
this.logger.verbose('finding contacts');
|
||||
if (this.dbSettings.ENABLED) {
|
||||
this.logger.verbose('finding contacts in db');
|
||||
return await this.contactModel.find({ ...query.where });
|
||||
}
|
||||
|
||||
this.logger.verbose('finding contacts in store');
|
||||
const contacts: ContactRaw[] = [];
|
||||
if (query?.where?.id) {
|
||||
this.logger.verbose('finding contacts in store by id');
|
||||
contacts.push(
|
||||
JSON.parse(
|
||||
readFileSync(
|
||||
@ -70,6 +166,8 @@ export class ContactRepository extends Repository {
|
||||
),
|
||||
);
|
||||
} else {
|
||||
this.logger.verbose('finding contacts in store by owner');
|
||||
|
||||
const openDir = opendirSync(join(this.storePath, 'contacts', query.where.owner), {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
@ -86,6 +184,8 @@ export class ContactRepository extends Repository {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.verbose('contacts found in store: ' + contacts.length + ' contacts');
|
||||
return contacts;
|
||||
} catch (error) {
|
||||
return [];
|
||||
|
@ -3,6 +3,7 @@ import { join } from 'path';
|
||||
import { IMessageModel, MessageRaw } from '../models';
|
||||
import { IInsert, Repository } from '../abstract/abstract.repository';
|
||||
import { opendirSync, readFileSync } from 'fs';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
|
||||
export class MessageQuery {
|
||||
where: MessageRaw;
|
||||
@ -17,13 +18,23 @@ export class MessageRepository extends Repository {
|
||||
super(configService);
|
||||
}
|
||||
|
||||
public async insert(data: MessageRaw[], saveDb = false): Promise<IInsert> {
|
||||
private readonly logger = new Logger('MessageRepository');
|
||||
|
||||
public async insert(
|
||||
data: MessageRaw[],
|
||||
instanceName: string,
|
||||
saveDb = false,
|
||||
): Promise<IInsert> {
|
||||
this.logger.verbose('inserting messages');
|
||||
|
||||
if (!Array.isArray(data) || data.length === 0) {
|
||||
this.logger.verbose('no messages to insert');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (this.dbSettings.ENABLED && saveDb) {
|
||||
this.logger.verbose('saving messages to db');
|
||||
const cleanedData = data.map((obj) => {
|
||||
const cleanedObj = { ...obj };
|
||||
if ('extendedTextMessage' in obj.message) {
|
||||
@ -44,23 +55,37 @@ export class MessageRepository extends Repository {
|
||||
});
|
||||
|
||||
const insert = await this.messageModel.insertMany([...cleanedData]);
|
||||
|
||||
this.logger.verbose('messages saved to db: ' + insert.length + ' messages');
|
||||
return { insertCount: insert.length };
|
||||
}
|
||||
|
||||
this.logger.verbose('saving messages to store');
|
||||
|
||||
const store = this.configService.get<StoreConf>('STORE');
|
||||
|
||||
if (store.MESSAGES) {
|
||||
data.forEach((msg) =>
|
||||
this.writeStore<MessageRaw>({
|
||||
path: join(this.storePath, 'messages', msg.owner),
|
||||
fileName: msg.key.id,
|
||||
data: msg,
|
||||
}),
|
||||
);
|
||||
this.logger.verbose('saving messages to store');
|
||||
|
||||
data.forEach((message) => {
|
||||
this.writeStore({
|
||||
path: join(this.storePath, 'messages', instanceName),
|
||||
fileName: message.key.id,
|
||||
data: message,
|
||||
});
|
||||
this.logger.verbose(
|
||||
'messages saved to store in path: ' +
|
||||
join(this.storePath, 'messages', instanceName) +
|
||||
'/' +
|
||||
message.key.id,
|
||||
);
|
||||
});
|
||||
|
||||
this.logger.verbose('messages saved to store: ' + data.length + ' messages');
|
||||
return { insertCount: data.length };
|
||||
}
|
||||
|
||||
this.logger.verbose('messages not saved to store');
|
||||
return { insertCount: 0 };
|
||||
} catch (error) {
|
||||
console.log('ERROR: ', error);
|
||||
@ -72,21 +97,26 @@ export class MessageRepository extends Repository {
|
||||
|
||||
public async find(query: MessageQuery) {
|
||||
try {
|
||||
this.logger.verbose('finding messages');
|
||||
if (this.dbSettings.ENABLED) {
|
||||
this.logger.verbose('finding messages in db');
|
||||
if (query?.where?.key) {
|
||||
for (const [k, v] of Object.entries(query.where.key)) {
|
||||
query.where['key.' + k] = v;
|
||||
}
|
||||
delete query?.where?.key;
|
||||
}
|
||||
|
||||
return await this.messageModel
|
||||
.find({ ...query.where })
|
||||
.sort({ messageTimestamp: -1 })
|
||||
.limit(query?.limit ?? 0);
|
||||
}
|
||||
|
||||
this.logger.verbose('finding messages in store');
|
||||
const messages: MessageRaw[] = [];
|
||||
if (query?.where?.key?.id) {
|
||||
this.logger.verbose('finding messages in store by id');
|
||||
messages.push(
|
||||
JSON.parse(
|
||||
readFileSync(
|
||||
@ -101,6 +131,7 @@ export class MessageRepository extends Repository {
|
||||
),
|
||||
);
|
||||
} else {
|
||||
this.logger.verbose('finding messages in store by owner');
|
||||
const openDir = opendirSync(join(this.storePath, 'messages', query.where.owner), {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
@ -119,6 +150,7 @@ export class MessageRepository extends Repository {
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.verbose('messages found in store: ' + messages.length + ' messages');
|
||||
return messages
|
||||
.sort((x, y) => {
|
||||
return (y.messageTimestamp as number) - (x.messageTimestamp as number);
|
||||
|
@ -3,6 +3,7 @@ import { IMessageUpModel, MessageUpdateRaw } from '../models';
|
||||
import { IInsert, Repository } from '../abstract/abstract.repository';
|
||||
import { join } from 'path';
|
||||
import { opendirSync, readFileSync } from 'fs';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
|
||||
export class MessageUpQuery {
|
||||
where: MessageUpdateRaw;
|
||||
@ -17,31 +18,54 @@ export class MessageUpRepository extends Repository {
|
||||
super(configService);
|
||||
}
|
||||
|
||||
public async insert(data: MessageUpdateRaw[], saveDb?: boolean): Promise<IInsert> {
|
||||
private readonly logger = new Logger('MessageUpRepository');
|
||||
|
||||
public async insert(
|
||||
data: MessageUpdateRaw[],
|
||||
instanceName: string,
|
||||
saveDb?: boolean,
|
||||
): Promise<IInsert> {
|
||||
this.logger.verbose('inserting message up');
|
||||
|
||||
if (data.length === 0) {
|
||||
this.logger.verbose('no message up to insert');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (this.dbSettings.ENABLED && saveDb) {
|
||||
this.logger.verbose('saving message up to db');
|
||||
const insert = await this.messageUpModel.insertMany([...data]);
|
||||
|
||||
this.logger.verbose('message up saved to db: ' + insert.length + ' message up');
|
||||
return { insertCount: insert.length };
|
||||
}
|
||||
|
||||
this.logger.verbose('saving message up to store');
|
||||
|
||||
const store = this.configService.get<StoreConf>('STORE');
|
||||
|
||||
if (store.MESSAGE_UP) {
|
||||
this.logger.verbose('saving message up to store');
|
||||
data.forEach((update) => {
|
||||
this.writeStore<MessageUpdateRaw>({
|
||||
path: join(this.storePath, 'message-up', update.owner),
|
||||
path: join(this.storePath, 'message-up', instanceName),
|
||||
fileName: update.id,
|
||||
data: update,
|
||||
});
|
||||
this.logger.verbose(
|
||||
'message up saved to store in path: ' +
|
||||
join(this.storePath, 'message-up', instanceName) +
|
||||
'/' +
|
||||
update.id,
|
||||
);
|
||||
});
|
||||
|
||||
this.logger.verbose('message up saved to store: ' + data.length + ' message up');
|
||||
return { insertCount: data.length };
|
||||
}
|
||||
|
||||
this.logger.verbose('message up not saved to store');
|
||||
return { insertCount: 0 };
|
||||
} catch (error) {
|
||||
return error;
|
||||
@ -50,15 +74,21 @@ export class MessageUpRepository extends Repository {
|
||||
|
||||
public async find(query: MessageUpQuery) {
|
||||
try {
|
||||
this.logger.verbose('finding message up');
|
||||
if (this.dbSettings.ENABLED) {
|
||||
this.logger.verbose('finding message up in db');
|
||||
return await this.messageUpModel
|
||||
.find({ ...query.where })
|
||||
.sort({ datetime: -1 })
|
||||
.limit(query?.limit ?? 0);
|
||||
}
|
||||
|
||||
this.logger.verbose('finding message up in store');
|
||||
|
||||
const messageUpdate: MessageUpdateRaw[] = [];
|
||||
if (query?.where?.id) {
|
||||
this.logger.verbose('finding message up in store by id');
|
||||
|
||||
messageUpdate.push(
|
||||
JSON.parse(
|
||||
readFileSync(
|
||||
@ -73,6 +103,8 @@ export class MessageUpRepository extends Repository {
|
||||
),
|
||||
);
|
||||
} else {
|
||||
this.logger.verbose('finding message up in store by owner');
|
||||
|
||||
const openDir = opendirSync(
|
||||
join(this.storePath, 'message-up', query.where.owner),
|
||||
{ encoding: 'utf-8' },
|
||||
@ -92,6 +124,9 @@ export class MessageUpRepository extends Repository {
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.verbose(
|
||||
'message up found in store: ' + messageUpdate.length + ' message up',
|
||||
);
|
||||
return messageUpdate
|
||||
.sort((x, y) => {
|
||||
return y.datetime - x.datetime;
|
||||
|
@ -8,6 +8,7 @@ import { AuthRepository } from './auth.repository';
|
||||
import { Auth, ConfigService, Database } from '../../config/env.config';
|
||||
import { execSync } from 'child_process';
|
||||
import { join } from 'path';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
|
||||
export class RepositoryBroker {
|
||||
constructor(
|
||||
@ -20,19 +21,26 @@ export class RepositoryBroker {
|
||||
private configService: ConfigService,
|
||||
dbServer?: MongoClient,
|
||||
) {
|
||||
this.logger.verbose('initializing repository broker');
|
||||
this.dbClient = dbServer;
|
||||
this.__init_repo_without_db__();
|
||||
}
|
||||
|
||||
private dbClient?: MongoClient;
|
||||
private readonly logger = new Logger('RepositoryBroker');
|
||||
|
||||
public get dbServer() {
|
||||
return this.dbClient;
|
||||
}
|
||||
|
||||
private __init_repo_without_db__() {
|
||||
this.logger.verbose('initializing repository without db');
|
||||
if (!this.configService.get<Database>('DATABASE').ENABLED) {
|
||||
this.logger.verbose('database is disabled');
|
||||
|
||||
const storePath = join(process.cwd(), 'store');
|
||||
|
||||
this.logger.verbose('creating store path: ' + storePath);
|
||||
execSync(
|
||||
`mkdir -p ${join(
|
||||
storePath,
|
||||
@ -40,10 +48,20 @@ export class RepositoryBroker {
|
||||
this.configService.get<Auth>('AUTHENTICATION').TYPE,
|
||||
)}`,
|
||||
);
|
||||
|
||||
this.logger.verbose('creating chats path: ' + join(storePath, 'chats'));
|
||||
execSync(`mkdir -p ${join(storePath, 'chats')}`);
|
||||
|
||||
this.logger.verbose('creating contacts path: ' + join(storePath, 'contacts'));
|
||||
execSync(`mkdir -p ${join(storePath, 'contacts')}`);
|
||||
|
||||
this.logger.verbose('creating messages path: ' + join(storePath, 'messages'));
|
||||
execSync(`mkdir -p ${join(storePath, 'messages')}`);
|
||||
|
||||
this.logger.verbose('creating message-up path: ' + join(storePath, 'message-up'));
|
||||
execSync(`mkdir -p ${join(storePath, 'message-up')}`);
|
||||
|
||||
this.logger.verbose('creating webhook path: ' + join(storePath, 'webhook'));
|
||||
execSync(`mkdir -p ${join(storePath, 'webhook')}`);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import { ConfigService } from '../../config/env.config';
|
||||
import { join } from 'path';
|
||||
import { readFileSync } from 'fs';
|
||||
import { IWebhookModel, WebhookRaw } from '../models';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
|
||||
export class WebhookRepository extends Repository {
|
||||
constructor(
|
||||
@ -12,23 +13,39 @@ export class WebhookRepository extends Repository {
|
||||
super(configService);
|
||||
}
|
||||
|
||||
private readonly logger = new Logger('WebhookRepository');
|
||||
|
||||
public async create(data: WebhookRaw, instance: string): Promise<IInsert> {
|
||||
try {
|
||||
this.logger.verbose('creating webhook');
|
||||
if (this.dbSettings.ENABLED) {
|
||||
this.logger.verbose('saving webhook to db');
|
||||
const insert = await this.webhookModel.replaceOne(
|
||||
{ _id: instance },
|
||||
{ ...data },
|
||||
{ upsert: true },
|
||||
);
|
||||
|
||||
this.logger.verbose('webhook saved to db: ' + insert.modifiedCount + ' webhook');
|
||||
return { insertCount: insert.modifiedCount };
|
||||
}
|
||||
|
||||
this.logger.verbose('saving webhook to store');
|
||||
|
||||
this.writeStore<WebhookRaw>({
|
||||
path: join(this.storePath, 'webhook'),
|
||||
fileName: instance,
|
||||
data,
|
||||
});
|
||||
|
||||
this.logger.verbose(
|
||||
'webhook saved to store in path: ' +
|
||||
join(this.storePath, 'webhook') +
|
||||
'/' +
|
||||
instance,
|
||||
);
|
||||
|
||||
this.logger.verbose('webhook created');
|
||||
return { insertCount: 1 };
|
||||
} catch (error) {
|
||||
return error;
|
||||
@ -37,10 +54,13 @@ export class WebhookRepository extends Repository {
|
||||
|
||||
public async find(instance: string): Promise<WebhookRaw> {
|
||||
try {
|
||||
this.logger.verbose('finding webhook');
|
||||
if (this.dbSettings.ENABLED) {
|
||||
this.logger.verbose('finding webhook in db');
|
||||
return await this.webhookModel.findOne({ _id: instance });
|
||||
}
|
||||
|
||||
this.logger.verbose('finding webhook in store');
|
||||
return JSON.parse(
|
||||
readFileSync(join(this.storePath, 'webhook', instance + '.json'), {
|
||||
encoding: 'utf-8',
|
||||
|
@ -32,12 +32,22 @@ import { HttpStatus } from './index.router';
|
||||
import { MessageUpQuery } from '../repository/messageUp.repository';
|
||||
import { proto } from '@whiskeysockets/baileys';
|
||||
import { InstanceDto } from '../dto/instance.dto';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
|
||||
const logger = new Logger('ChatRouter');
|
||||
|
||||
export class ChatRouter extends RouterBroker {
|
||||
constructor(...guards: RequestHandler[]) {
|
||||
super();
|
||||
this.router
|
||||
.post(this.routerPath('whatsappNumbers'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in whatsappNumbers');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.dataValidate<WhatsAppNumberDto>({
|
||||
request: req,
|
||||
schema: whatsappNumberSchema,
|
||||
@ -48,6 +58,13 @@ export class ChatRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.put(this.routerPath('markMessageAsRead'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in markMessageAsRead');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.dataValidate<ReadMessageDto>({
|
||||
request: req,
|
||||
schema: readMessageSchema,
|
||||
@ -58,6 +75,13 @@ export class ChatRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.put(this.routerPath('archiveChat'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in archiveChat');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.dataValidate<ArchiveChatDto>({
|
||||
request: req,
|
||||
schema: archiveChatSchema,
|
||||
@ -71,6 +95,13 @@ export class ChatRouter extends RouterBroker {
|
||||
this.routerPath('deleteMessageForEveryone'),
|
||||
...guards,
|
||||
async (req, res) => {
|
||||
logger.verbose('request received in deleteMessageForEveryone');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.dataValidate<DeleteMessage>({
|
||||
request: req,
|
||||
schema: deleteMessageSchema,
|
||||
@ -82,6 +113,13 @@ export class ChatRouter extends RouterBroker {
|
||||
},
|
||||
)
|
||||
.post(this.routerPath('fetchProfilePictureUrl'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in fetchProfilePictureUrl');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.dataValidate<NumberDto>({
|
||||
request: req,
|
||||
schema: profilePictureSchema,
|
||||
@ -92,6 +130,13 @@ export class ChatRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.post(this.routerPath('findContacts'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in findContacts');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.dataValidate<ContactQuery>({
|
||||
request: req,
|
||||
schema: contactValidateSchema,
|
||||
@ -102,6 +147,13 @@ export class ChatRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.post(this.routerPath('getBase64FromMediaMessage'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in getBase64FromMediaMessage');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.dataValidate<getBase64FromMediaMessageDto>({
|
||||
request: req,
|
||||
schema: null,
|
||||
@ -113,6 +165,13 @@ export class ChatRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.post(this.routerPath('findMessages'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in findMessages');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.dataValidate<MessageQuery>({
|
||||
request: req,
|
||||
schema: messageValidateSchema,
|
||||
@ -123,6 +182,13 @@ export class ChatRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.post(this.routerPath('findStatusMessage'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in findStatusMessage');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.dataValidate<MessageUpQuery>({
|
||||
request: req,
|
||||
schema: messageUpSchema,
|
||||
@ -133,6 +199,13 @@ export class ChatRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.get(this.routerPath('findChats'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in findChats');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.dataValidate<InstanceDto>({
|
||||
request: req,
|
||||
schema: null,
|
||||
@ -144,6 +217,13 @@ export class ChatRouter extends RouterBroker {
|
||||
})
|
||||
// Profile routes
|
||||
.get(this.routerPath('fetchPrivacySettings'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in fetchPrivacySettings');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.dataValidate<InstanceDto>({
|
||||
request: req,
|
||||
schema: null,
|
||||
@ -154,6 +234,13 @@ export class ChatRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.put(this.routerPath('updatePrivacySettings'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in updatePrivacySettings');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.dataValidate<PrivacySettingDto>({
|
||||
request: req,
|
||||
schema: privacySettingsSchema,
|
||||
@ -165,6 +252,13 @@ export class ChatRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.post(this.routerPath('fetchBusinessProfile'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in fetchBusinessProfile');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.dataValidate<ProfilePictureDto>({
|
||||
request: req,
|
||||
schema: profilePictureSchema,
|
||||
@ -176,6 +270,13 @@ export class ChatRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.post(this.routerPath('updateProfileName'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in updateProfileName');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.dataValidate<ProfileNameDto>({
|
||||
request: req,
|
||||
schema: profileNameSchema,
|
||||
@ -186,6 +287,13 @@ export class ChatRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.post(this.routerPath('updateProfileStatus'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in updateProfileStatus');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.dataValidate<ProfileStatusDto>({
|
||||
request: req,
|
||||
schema: profileStatusSchema,
|
||||
@ -196,6 +304,13 @@ export class ChatRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.put(this.routerPath('updateProfilePicture'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in updateProfilePicture');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.dataValidate<ProfilePictureDto>({
|
||||
request: req,
|
||||
schema: profilePictureSchema,
|
||||
@ -207,6 +322,13 @@ export class ChatRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.delete(this.routerPath('removeProfilePicture'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in removeProfilePicture');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.dataValidate<ProfilePictureDto>({
|
||||
request: req,
|
||||
schema: profilePictureSchema,
|
||||
|
@ -26,12 +26,21 @@ import {
|
||||
} from '../dto/group.dto';
|
||||
import { groupController } from '../whatsapp.module';
|
||||
import { HttpStatus } from './index.router';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
|
||||
const logger = new Logger('GroupRouter');
|
||||
|
||||
export class GroupRouter extends RouterBroker {
|
||||
constructor(...guards: RequestHandler[]) {
|
||||
super();
|
||||
this.router
|
||||
.post(this.routerPath('create'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in createGroup');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<CreateGroupDto>({
|
||||
request: req,
|
||||
schema: createGroupSchema,
|
||||
@ -42,6 +51,13 @@ export class GroupRouter extends RouterBroker {
|
||||
res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.put(this.routerPath('updateGroupSubject'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in updateGroupSubject');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
|
||||
const response = await this.groupValidate<GroupSubjectDto>({
|
||||
request: req,
|
||||
schema: updateGroupSubjectSchema,
|
||||
@ -52,6 +68,12 @@ export class GroupRouter extends RouterBroker {
|
||||
res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.put(this.routerPath('updateGroupPicture'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in updateGroupPicture');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.groupValidate<GroupPictureDto>({
|
||||
request: req,
|
||||
schema: updateGroupPictureSchema,
|
||||
@ -62,6 +84,12 @@ export class GroupRouter extends RouterBroker {
|
||||
res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.put(this.routerPath('updateGroupDescription'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in updateGroupDescription');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.groupValidate<GroupDescriptionDto>({
|
||||
request: req,
|
||||
schema: updateGroupDescriptionSchema,
|
||||
@ -73,6 +101,12 @@ export class GroupRouter extends RouterBroker {
|
||||
res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.get(this.routerPath('findGroupInfos'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in findGroupInfos');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.groupValidate<GroupJid>({
|
||||
request: req,
|
||||
schema: groupJidSchema,
|
||||
@ -83,6 +117,12 @@ export class GroupRouter extends RouterBroker {
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.get(this.routerPath('fetchAllGroups'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in fetchAllGroups');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.groupNoValidate<GroupJid>({
|
||||
request: req,
|
||||
schema: {},
|
||||
@ -93,6 +133,12 @@ export class GroupRouter extends RouterBroker {
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.get(this.routerPath('participants'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in participants');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.groupValidate<GroupJid>({
|
||||
request: req,
|
||||
schema: groupJidSchema,
|
||||
@ -103,6 +149,12 @@ export class GroupRouter extends RouterBroker {
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.get(this.routerPath('inviteCode'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in inviteCode');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.groupValidate<GroupJid>({
|
||||
request: req,
|
||||
schema: groupJidSchema,
|
||||
@ -113,6 +165,12 @@ export class GroupRouter extends RouterBroker {
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.get(this.routerPath('inviteInfo'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in inviteInfo');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.inviteCodeValidate<GroupInvite>({
|
||||
request: req,
|
||||
schema: groupInviteSchema,
|
||||
@ -123,6 +181,12 @@ export class GroupRouter extends RouterBroker {
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.post(this.routerPath('sendInvite'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in sendInvite');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.groupNoValidate<GroupSendInvite>({
|
||||
request: req,
|
||||
schema: groupSendInviteSchema,
|
||||
@ -133,6 +197,12 @@ export class GroupRouter extends RouterBroker {
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.put(this.routerPath('revokeInviteCode'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in revokeInviteCode');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.groupValidate<GroupJid>({
|
||||
request: req,
|
||||
schema: groupJidSchema,
|
||||
@ -143,6 +213,12 @@ export class GroupRouter extends RouterBroker {
|
||||
res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.put(this.routerPath('updateParticipant'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in updateParticipant');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.groupValidate<GroupUpdateParticipantDto>({
|
||||
request: req,
|
||||
schema: updateParticipantsSchema,
|
||||
@ -153,6 +229,12 @@ export class GroupRouter extends RouterBroker {
|
||||
res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.put(this.routerPath('updateSetting'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in updateSetting');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.groupValidate<GroupUpdateSettingDto>({
|
||||
request: req,
|
||||
schema: updateSettingsSchema,
|
||||
@ -163,6 +245,12 @@ export class GroupRouter extends RouterBroker {
|
||||
res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.put(this.routerPath('toggleEphemeral'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in toggleEphemeral');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.groupValidate<GroupToggleEphemeralDto>({
|
||||
request: req,
|
||||
schema: toggleEphemeralSchema,
|
||||
@ -173,6 +261,12 @@ export class GroupRouter extends RouterBroker {
|
||||
res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.delete(this.routerPath('leaveGroup'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in leaveGroup');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.groupValidate<GroupJid>({
|
||||
request: req,
|
||||
schema: {},
|
||||
|
@ -7,6 +7,9 @@ import { HttpStatus } from './index.router';
|
||||
import { OldToken } from '../services/auth.service';
|
||||
import { Auth, ConfigService, Database } from '../../config/env.config';
|
||||
import { dbserver } from '../../db/db.connect';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
|
||||
const logger = new Logger('InstanceRouter');
|
||||
|
||||
export class InstanceRouter extends RouterBroker {
|
||||
constructor(readonly configService: ConfigService, ...guards: RequestHandler[]) {
|
||||
@ -14,6 +17,12 @@ export class InstanceRouter extends RouterBroker {
|
||||
const auth = configService.get<Auth>('AUTHENTICATION');
|
||||
this.router
|
||||
.post('/create', ...guards, async (req, res) => {
|
||||
logger.verbose('request received in createInstance');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<InstanceDto>({
|
||||
request: req,
|
||||
schema: instanceNameSchema,
|
||||
@ -24,6 +33,12 @@ export class InstanceRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.put(this.routerPath('restart'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in restartInstance');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<InstanceDto>({
|
||||
request: req,
|
||||
schema: instanceNameSchema,
|
||||
@ -34,6 +49,12 @@ export class InstanceRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.get(this.routerPath('connect'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in connectInstance');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<InstanceDto>({
|
||||
request: req,
|
||||
schema: instanceNameSchema,
|
||||
@ -44,6 +65,12 @@ export class InstanceRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.get(this.routerPath('connectionState'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in connectionState');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<InstanceDto>({
|
||||
request: req,
|
||||
schema: instanceNameSchema,
|
||||
@ -54,6 +81,12 @@ export class InstanceRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.get(this.routerPath('fetchInstances', false), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in fetchInstances');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<InstanceDto>({
|
||||
request: req,
|
||||
schema: null,
|
||||
@ -64,6 +97,12 @@ export class InstanceRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.delete(this.routerPath('logout'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in logoutInstances');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<InstanceDto>({
|
||||
request: req,
|
||||
schema: instanceNameSchema,
|
||||
@ -74,6 +113,12 @@ export class InstanceRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.delete(this.routerPath('delete'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in deleteInstances');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<InstanceDto>({
|
||||
request: req,
|
||||
schema: instanceNameSchema,
|
||||
@ -86,6 +131,12 @@ export class InstanceRouter extends RouterBroker {
|
||||
|
||||
if (auth.TYPE === 'jwt') {
|
||||
this.router.put('/refreshToken', async (req, res) => {
|
||||
logger.verbose('request received in refreshToken');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<OldToken>({
|
||||
request: req,
|
||||
schema: oldTokenSchema,
|
||||
@ -98,6 +149,12 @@ export class InstanceRouter extends RouterBroker {
|
||||
}
|
||||
|
||||
this.router.delete('/deleteDatabase', async (req, res) => {
|
||||
logger.verbose('request received in deleteDatabase');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const db = this.configService.get<Database>('DATABASE');
|
||||
if (db.ENABLED) {
|
||||
try {
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
mediaMessageSchema,
|
||||
pollMessageSchema,
|
||||
reactionMessageSchema,
|
||||
statusMessageSchema,
|
||||
stickerMessageSchema,
|
||||
textMessageSchema,
|
||||
} from '../../validate/validate.schema';
|
||||
@ -22,18 +23,28 @@ import {
|
||||
SendMediaDto,
|
||||
SendPollDto,
|
||||
SendReactionDto,
|
||||
SendStatusDto,
|
||||
SendStickerDto,
|
||||
SendTextDto,
|
||||
} from '../dto/sendMessage.dto';
|
||||
import { sendMessageController } from '../whatsapp.module';
|
||||
import { RouterBroker } from '../abstract/abstract.router';
|
||||
import { HttpStatus } from './index.router';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
|
||||
const logger = new Logger('MessageRouter');
|
||||
|
||||
export class MessageRouter extends RouterBroker {
|
||||
constructor(...guards: RequestHandler[]) {
|
||||
super();
|
||||
this.router
|
||||
.post(this.routerPath('sendText'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in sendText');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<SendTextDto>({
|
||||
request: req,
|
||||
schema: textMessageSchema,
|
||||
@ -44,6 +55,12 @@ export class MessageRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.post(this.routerPath('sendMedia'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in sendMedia');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<SendMediaDto>({
|
||||
request: req,
|
||||
schema: mediaMessageSchema,
|
||||
@ -54,6 +71,12 @@ export class MessageRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.post(this.routerPath('sendWhatsAppAudio'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in sendWhatsAppAudio');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<SendAudioDto>({
|
||||
request: req,
|
||||
schema: audioMessageSchema,
|
||||
@ -65,6 +88,12 @@ export class MessageRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.post(this.routerPath('sendButtons'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in sendButtons');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<SendButtonDto>({
|
||||
request: req,
|
||||
schema: buttonMessageSchema,
|
||||
@ -75,6 +104,12 @@ export class MessageRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.post(this.routerPath('sendLocation'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in sendLocation');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<SendLocationDto>({
|
||||
request: req,
|
||||
schema: locationMessageSchema,
|
||||
@ -85,6 +120,12 @@ export class MessageRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.post(this.routerPath('sendList'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in sendList');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<SendListDto>({
|
||||
request: req,
|
||||
schema: listMessageSchema,
|
||||
@ -95,6 +136,12 @@ export class MessageRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.post(this.routerPath('sendContact'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in sendContact');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<SendContactDto>({
|
||||
request: req,
|
||||
schema: contactMessageSchema,
|
||||
@ -105,6 +152,12 @@ export class MessageRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.post(this.routerPath('sendReaction'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in sendReaction');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<SendReactionDto>({
|
||||
request: req,
|
||||
schema: reactionMessageSchema,
|
||||
@ -115,6 +168,12 @@ export class MessageRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.post(this.routerPath('sendPoll'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in sendPoll');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<SendPollDto>({
|
||||
request: req,
|
||||
schema: pollMessageSchema,
|
||||
@ -124,7 +183,29 @@ export class MessageRouter extends RouterBroker {
|
||||
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.post(this.routerPath('sendStatus'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in sendStatus');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<SendStatusDto>({
|
||||
request: req,
|
||||
schema: statusMessageSchema,
|
||||
ClassRef: SendStatusDto,
|
||||
execute: (instance, data) => sendMessageController.sendStatus(instance, data),
|
||||
});
|
||||
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.post(this.routerPath('sendLinkPreview'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in sendLinkPreview');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<SendLinkPreviewDto>({
|
||||
request: req,
|
||||
schema: linkPreviewSchema,
|
||||
@ -136,6 +217,12 @@ export class MessageRouter extends RouterBroker {
|
||||
return res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.post(this.routerPath('sendSticker'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in sendSticker');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<SendStickerDto>({
|
||||
request: req,
|
||||
schema: stickerMessageSchema,
|
||||
|
@ -5,12 +5,21 @@ import { InstanceDto } from '../dto/instance.dto';
|
||||
import { WebhookDto } from '../dto/webhook.dto';
|
||||
import { webhookController } from '../whatsapp.module';
|
||||
import { HttpStatus } from './index.router';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
|
||||
const logger = new Logger('WebhookRouter');
|
||||
|
||||
export class WebhookRouter extends RouterBroker {
|
||||
constructor(...guards: RequestHandler[]) {
|
||||
super();
|
||||
this.router
|
||||
.post(this.routerPath('set'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in setWebhook');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<WebhookDto>({
|
||||
request: req,
|
||||
schema: webhookSchema,
|
||||
@ -21,6 +30,12 @@ export class WebhookRouter extends RouterBroker {
|
||||
res.status(HttpStatus.CREATED).json(response);
|
||||
})
|
||||
.get(this.routerPath('find'), ...guards, async (req, res) => {
|
||||
logger.verbose('request received in findWebhook');
|
||||
logger.verbose('request body: ');
|
||||
logger.verbose(req.body);
|
||||
|
||||
logger.verbose('request query: ');
|
||||
logger.verbose(req.query);
|
||||
const response = await this.dataValidate<InstanceDto>({
|
||||
request: req,
|
||||
schema: instanceNameSchema,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { opendirSync, readdirSync, rmSync } from 'fs';
|
||||
import { WAStartupService } from './whatsapp.service';
|
||||
import { INSTANCE_DIR } from '../../config/path.config';
|
||||
import { INSTANCE_DIR, STORE_DIR } from '../../config/path.config';
|
||||
import EventEmitter2 from 'eventemitter2';
|
||||
import { join } from 'path';
|
||||
import { Logger } from '../../config/logger.config';
|
||||
@ -16,6 +16,7 @@ import { NotFoundException } from '../../exceptions';
|
||||
import { Db } from 'mongodb';
|
||||
import { initInstance } from '../whatsapp.module';
|
||||
import { RedisCache } from '../../db/redis.client';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
export class WAMonitoringService {
|
||||
constructor(
|
||||
@ -216,6 +217,24 @@ export class WAMonitoringService {
|
||||
rmSync(join(INSTANCE_DIR, instanceName), { recursive: true, force: true });
|
||||
}
|
||||
|
||||
public async cleaningStoreFiles(instanceName: string) {
|
||||
this.logger.verbose('cleaning store files instance: ' + instanceName);
|
||||
|
||||
if (!this.db.ENABLED) {
|
||||
const instance = this.waInstances[instanceName];
|
||||
|
||||
rmSync(join(INSTANCE_DIR, instanceName), { recursive: true, force: true });
|
||||
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'chats', instanceName)}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'contacts', instanceName)}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'message-up', instanceName)}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'messages', instanceName)}`);
|
||||
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'auth', 'apikey', instanceName + '.json')}`);
|
||||
execSync(`rm -rf ${join(STORE_DIR, 'webhook', instanceName + '.json')}`);
|
||||
}
|
||||
}
|
||||
|
||||
public async loadInstance() {
|
||||
this.logger.verbose('load instances');
|
||||
const set = async (name: string) => {
|
||||
@ -300,6 +319,7 @@ export class WAMonitoringService {
|
||||
try {
|
||||
this.logger.verbose('request cleaning up instance: ' + instanceName);
|
||||
this.cleaningUp(instanceName);
|
||||
this.cleaningStoreFiles(instanceName);
|
||||
} finally {
|
||||
this.logger.warn(`Instance "${instanceName}" - REMOVED`);
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import makeWASocket, {
|
||||
WAMessageUpdate,
|
||||
WASocket,
|
||||
getAggregateVotesInPollMessage,
|
||||
Browsers,
|
||||
} from '@whiskeysockets/baileys';
|
||||
import {
|
||||
Auth,
|
||||
@ -77,6 +78,8 @@ import {
|
||||
SendPollDto,
|
||||
SendLinkPreviewDto,
|
||||
SendStickerDto,
|
||||
SendStatusDto,
|
||||
StatusMessage,
|
||||
} from '../dto/sendMessage.dto';
|
||||
import { arrayUnique, isBase64, isURL } from 'class-validator';
|
||||
import {
|
||||
@ -117,6 +120,7 @@ import { useMultiFileAuthStateRedisDb } from '../../utils/use-multi-file-auth-st
|
||||
import sharp from 'sharp';
|
||||
import { RedisCache } from '../../db/redis.client';
|
||||
import { Log } from '../../config/env.config';
|
||||
import ProxyAgent from 'proxy-agent';
|
||||
|
||||
export class WAStartupService {
|
||||
constructor(
|
||||
@ -505,7 +509,7 @@ export class WAStartupService {
|
||||
this.logger.verbose('Getting message with key: ' + JSON.stringify(key));
|
||||
try {
|
||||
const webMessageInfo = (await this.repository.message.find({
|
||||
where: { owner: this.instance.wuid, key: { id: key.id } },
|
||||
where: { owner: this.instance.name, key: { id: key.id } },
|
||||
})) as unknown as proto.IWebMessageInfo[];
|
||||
if (full) {
|
||||
this.logger.verbose('Returning full message');
|
||||
@ -551,14 +555,14 @@ export class WAStartupService {
|
||||
`rm -rf ${join(
|
||||
this.storePath,
|
||||
key.toLowerCase().replace('_', '-'),
|
||||
this.instance.wuid,
|
||||
this.instance.name,
|
||||
)}/*.json`,
|
||||
);
|
||||
this.logger.verbose(
|
||||
`Cleaned ${join(
|
||||
this.storePath,
|
||||
key.toLowerCase().replace('_', '-'),
|
||||
this.instance.wuid,
|
||||
this.instance.name,
|
||||
)}/*.json`,
|
||||
);
|
||||
}
|
||||
@ -598,7 +602,8 @@ export class WAStartupService {
|
||||
const { version } = await fetchLatestBaileysVersion();
|
||||
this.logger.verbose('Baileys version: ' + version);
|
||||
const session = this.configService.get<ConfigSessionPhone>('CONFIG_SESSION_PHONE');
|
||||
const browser: WABrowserDescription = [session.CLIENT, session.NAME, release()];
|
||||
// const browser: WABrowserDescription = [session.CLIENT, session.NAME, release()];
|
||||
const browser: WABrowserDescription = Browsers.appropriate(session.CLIENT);
|
||||
this.logger.verbose('Browser: ' + JSON.stringify(browser));
|
||||
|
||||
const socketConfig: UserFacingSocketConfig = {
|
||||
@ -672,7 +677,7 @@ export class WAStartupService {
|
||||
|
||||
this.logger.verbose('Finding chats in database');
|
||||
const chatsRepository = await this.repository.chat.find({
|
||||
where: { owner: this.instance.wuid },
|
||||
where: { owner: this.instance.name },
|
||||
});
|
||||
|
||||
this.logger.verbose('Verifying if chats exists in database to insert');
|
||||
@ -689,7 +694,11 @@ export class WAStartupService {
|
||||
await this.sendDataWebhook(Events.CHATS_UPSERT, chatsRaw);
|
||||
|
||||
this.logger.verbose('Inserting chats in database');
|
||||
await this.repository.chat.insert(chatsRaw, database.SAVE_DATA.CHATS);
|
||||
await this.repository.chat.insert(
|
||||
chatsRaw,
|
||||
this.instance.name,
|
||||
database.SAVE_DATA.CHATS,
|
||||
);
|
||||
},
|
||||
|
||||
'chats.update': async (
|
||||
@ -717,7 +726,7 @@ export class WAStartupService {
|
||||
chats.forEach(
|
||||
async (chat) =>
|
||||
await this.repository.chat.delete({
|
||||
where: { owner: this.instance.wuid, id: chat },
|
||||
where: { owner: this.instance.name, id: chat },
|
||||
}),
|
||||
);
|
||||
|
||||
@ -732,7 +741,7 @@ export class WAStartupService {
|
||||
|
||||
this.logger.verbose('Finding contacts in database');
|
||||
const contactsRepository = await this.repository.contact.find({
|
||||
where: { owner: this.instance.wuid },
|
||||
where: { owner: this.instance.name },
|
||||
});
|
||||
|
||||
this.logger.verbose('Verifying if contacts exists in database to insert');
|
||||
@ -746,7 +755,7 @@ export class WAStartupService {
|
||||
id: contact.id,
|
||||
pushName: contact?.name || contact?.verifiedName,
|
||||
profilePictureUrl: (await this.profilePicture(contact.id)).profilePictureUrl,
|
||||
owner: this.instance.wuid,
|
||||
owner: this.instance.name,
|
||||
});
|
||||
}
|
||||
|
||||
@ -754,10 +763,14 @@ export class WAStartupService {
|
||||
await this.sendDataWebhook(Events.CONTACTS_UPSERT, contactsRaw);
|
||||
|
||||
this.logger.verbose('Inserting contacts in database');
|
||||
await this.repository.contact.insert(contactsRaw, database.SAVE_DATA.CONTACTS);
|
||||
await this.repository.contact.insert(
|
||||
contactsRaw,
|
||||
this.instance.name,
|
||||
database.SAVE_DATA.CONTACTS,
|
||||
);
|
||||
},
|
||||
|
||||
'contacts.update': async (contacts: Partial<Contact>[]) => {
|
||||
'contacts.update': async (contacts: Partial<Contact>[], database: Database) => {
|
||||
this.logger.verbose('Event received: contacts.update');
|
||||
|
||||
this.logger.verbose('Verifying if contacts exists in database to update');
|
||||
@ -767,12 +780,19 @@ export class WAStartupService {
|
||||
id: contact.id,
|
||||
pushName: contact?.name ?? contact?.verifiedName,
|
||||
profilePictureUrl: (await this.profilePicture(contact.id)).profilePictureUrl,
|
||||
owner: this.instance.wuid,
|
||||
owner: this.instance.name,
|
||||
});
|
||||
}
|
||||
|
||||
this.logger.verbose('Sending data to webhook in event CONTACTS_UPDATE');
|
||||
await this.sendDataWebhook(Events.CONTACTS_UPDATE, contactsRaw);
|
||||
|
||||
this.logger.verbose('Updating contacts in database');
|
||||
await this.repository.contact.update(
|
||||
contactsRaw,
|
||||
this.instance.name,
|
||||
database.SAVE_DATA.CONTACTS,
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@ -796,7 +816,7 @@ export class WAStartupService {
|
||||
const chatsRaw: ChatRaw[] = chats.map((chat) => {
|
||||
return {
|
||||
id: chat.id,
|
||||
owner: this.instance.wuid,
|
||||
owner: this.instance.name,
|
||||
lastMsgTimestamp: chat.lastMessageRecvTimestamp,
|
||||
};
|
||||
});
|
||||
@ -805,12 +825,16 @@ export class WAStartupService {
|
||||
await this.sendDataWebhook(Events.CHATS_SET, chatsRaw);
|
||||
|
||||
this.logger.verbose('Inserting chats in database');
|
||||
await this.repository.chat.insert(chatsRaw, database.SAVE_DATA.CHATS);
|
||||
await this.repository.chat.insert(
|
||||
chatsRaw,
|
||||
this.instance.name,
|
||||
database.SAVE_DATA.CHATS,
|
||||
);
|
||||
}
|
||||
|
||||
const messagesRaw: MessageRaw[] = [];
|
||||
const messagesRepository = await this.repository.message.find({
|
||||
where: { owner: this.instance.wuid },
|
||||
where: { owner: this.instance.name },
|
||||
});
|
||||
for await (const [, m] of Object.entries(messages)) {
|
||||
if (!m.message) {
|
||||
@ -818,7 +842,7 @@ export class WAStartupService {
|
||||
}
|
||||
if (
|
||||
messagesRepository.find(
|
||||
(mr) => mr.owner === this.instance.wuid && mr.key.id === m.key.id,
|
||||
(mr) => mr.owner === this.instance.name && mr.key.id === m.key.id,
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
@ -835,7 +859,7 @@ export class WAStartupService {
|
||||
message: { ...m.message },
|
||||
messageType: getContentType(m.message),
|
||||
messageTimestamp: m.messageTimestamp as number,
|
||||
owner: this.instance.wuid,
|
||||
owner: this.instance.name,
|
||||
});
|
||||
}
|
||||
|
||||
@ -877,7 +901,7 @@ export class WAStartupService {
|
||||
message: { ...received.message },
|
||||
messageType: getContentType(received.message),
|
||||
messageTimestamp: received.messageTimestamp as number,
|
||||
owner: this.instance.wuid,
|
||||
owner: this.instance.name,
|
||||
source: getDevice(received.key.id),
|
||||
};
|
||||
|
||||
@ -887,7 +911,63 @@ export class WAStartupService {
|
||||
await this.sendDataWebhook(Events.MESSAGES_UPSERT, messageRaw);
|
||||
|
||||
this.logger.verbose('Inserting message in database');
|
||||
await this.repository.message.insert([messageRaw], database.SAVE_DATA.NEW_MESSAGE);
|
||||
await this.repository.message.insert(
|
||||
[messageRaw],
|
||||
this.instance.name,
|
||||
database.SAVE_DATA.NEW_MESSAGE,
|
||||
);
|
||||
|
||||
this.logger.verbose('Verifying contact from message');
|
||||
const contact = await this.repository.contact.find({
|
||||
where: { owner: this.instance.name, id: received.key.remoteJid },
|
||||
});
|
||||
|
||||
const contactRaw: ContactRaw = {
|
||||
id: received.key.remoteJid,
|
||||
pushName: received.pushName,
|
||||
profilePictureUrl: (await this.profilePicture(received.key.remoteJid))
|
||||
.profilePictureUrl,
|
||||
owner: this.instance.name,
|
||||
};
|
||||
|
||||
if (contactRaw.id === 'status@broadcast') {
|
||||
this.logger.verbose('Contact is status@broadcast');
|
||||
return;
|
||||
}
|
||||
|
||||
if (contact?.length) {
|
||||
this.logger.verbose('Contact found in database');
|
||||
const contactRaw: ContactRaw = {
|
||||
id: received.key.remoteJid,
|
||||
pushName: contact[0].pushName,
|
||||
profilePictureUrl: (await this.profilePicture(received.key.remoteJid))
|
||||
.profilePictureUrl,
|
||||
owner: this.instance.name,
|
||||
};
|
||||
|
||||
this.logger.verbose('Sending data to webhook in event CONTACTS_UPDATE');
|
||||
await this.sendDataWebhook(Events.CONTACTS_UPDATE, contactRaw);
|
||||
|
||||
this.logger.verbose('Updating contact in database');
|
||||
await this.repository.contact.update(
|
||||
[contactRaw],
|
||||
this.instance.name,
|
||||
database.SAVE_DATA.CONTACTS,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.verbose('Contact not found in database');
|
||||
|
||||
this.logger.verbose('Sending data to webhook in event CONTACTS_UPSERT');
|
||||
await this.sendDataWebhook(Events.CONTACTS_UPSERT, contactRaw);
|
||||
|
||||
this.logger.verbose('Inserting contact in database');
|
||||
await this.repository.contact.insert(
|
||||
[contactRaw],
|
||||
this.instance.name,
|
||||
database.SAVE_DATA.CONTACTS,
|
||||
);
|
||||
},
|
||||
|
||||
'messages.update': async (args: WAMessageUpdate[], database: Database) => {
|
||||
@ -921,7 +1001,7 @@ export class WAStartupService {
|
||||
...key,
|
||||
status: status[update.status],
|
||||
datetime: Date.now(),
|
||||
owner: this.instance.wuid,
|
||||
owner: this.instance.name,
|
||||
pollUpdates,
|
||||
};
|
||||
|
||||
@ -931,6 +1011,7 @@ export class WAStartupService {
|
||||
this.logger.verbose('Inserting message in database');
|
||||
await this.repository.messageUpdate.insert(
|
||||
[message],
|
||||
this.instance.name,
|
||||
database.SAVE_DATA.MESSAGE_UPDATE,
|
||||
);
|
||||
}
|
||||
@ -1050,7 +1131,7 @@ export class WAStartupService {
|
||||
if (events['contacts.update']) {
|
||||
this.logger.verbose('Listening event: contacts.update');
|
||||
const payload = events['contacts.update'];
|
||||
this.contactHandle['contacts.update'](payload);
|
||||
this.contactHandle['contacts.update'](payload, database);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1098,6 +1179,11 @@ export class WAStartupService {
|
||||
return number;
|
||||
}
|
||||
|
||||
if (number.includes('@broadcast')) {
|
||||
this.logger.verbose('Number already contains @broadcast');
|
||||
return number;
|
||||
}
|
||||
|
||||
const formattedBRNumber = this.formatBRNumber(number);
|
||||
if (formattedBRNumber !== number) {
|
||||
this.logger.verbose(
|
||||
@ -1152,7 +1238,7 @@ export class WAStartupService {
|
||||
|
||||
const jid = this.createJid(number);
|
||||
const isWA = (await this.whatsappNumber({ numbers: [jid] }))[0];
|
||||
if (!isWA.exists && !isJidGroup(isWA.jid)) {
|
||||
if (!isWA.exists && !isJidGroup(isWA.jid) && !isWA.jid.includes('@broadcast')) {
|
||||
throw new BadRequestException(isWA);
|
||||
}
|
||||
|
||||
@ -1229,7 +1315,8 @@ export class WAStartupService {
|
||||
!message['audio'] &&
|
||||
!message['poll'] &&
|
||||
!message['linkPreview'] &&
|
||||
!message['sticker']
|
||||
!message['sticker'] &&
|
||||
!sender.includes('@broadcast')
|
||||
) {
|
||||
if (!message['audio']) {
|
||||
this.logger.verbose('Sending message');
|
||||
@ -1258,6 +1345,20 @@ export class WAStartupService {
|
||||
);
|
||||
}
|
||||
|
||||
if (sender.includes('@broadcast')) {
|
||||
this.logger.verbose('Sending message');
|
||||
console.log(message['status']);
|
||||
return await this.client.sendMessage(
|
||||
sender,
|
||||
message['status'].content as unknown as AnyMessageContent,
|
||||
{
|
||||
backgroundColor: message['status'].option.backgroundColor,
|
||||
font: message['status'].option.font,
|
||||
statusJidList: message['status'].option.statusJidList,
|
||||
} as unknown as MiscMessageGenerationOptions,
|
||||
);
|
||||
}
|
||||
|
||||
this.logger.verbose('Sending message');
|
||||
return await this.client.sendMessage(
|
||||
sender,
|
||||
@ -1335,6 +1436,131 @@ export class WAStartupService {
|
||||
);
|
||||
}
|
||||
|
||||
private async formatStatusMessage(status: StatusMessage) {
|
||||
this.logger.verbose('Formatting status message');
|
||||
|
||||
if (!status.type) {
|
||||
throw new BadRequestException('Type is required');
|
||||
}
|
||||
|
||||
if (!status.content) {
|
||||
throw new BadRequestException('Content is required');
|
||||
}
|
||||
|
||||
if (status.allContacts) {
|
||||
this.logger.verbose('All contacts defined as true');
|
||||
|
||||
this.logger.verbose('Getting contacts from database');
|
||||
const contacts = await this.repository.contact.find({
|
||||
where: { owner: this.instance.name },
|
||||
});
|
||||
|
||||
if (!contacts.length) {
|
||||
throw new BadRequestException('Contacts not found');
|
||||
}
|
||||
|
||||
this.logger.verbose('Getting contacts with push name');
|
||||
status.statusJidList = contacts
|
||||
.filter((contact) => contact.pushName)
|
||||
.map((contact) => contact.id);
|
||||
|
||||
this.logger.verbose(status.statusJidList);
|
||||
}
|
||||
|
||||
if (!status.statusJidList?.length && !status.allContacts) {
|
||||
throw new BadRequestException('StatusJidList is required');
|
||||
}
|
||||
|
||||
if (status.type === 'text') {
|
||||
this.logger.verbose('Type defined as text');
|
||||
|
||||
if (!status.backgroundColor) {
|
||||
throw new BadRequestException('Background color is required');
|
||||
}
|
||||
|
||||
if (!status.font) {
|
||||
throw new BadRequestException('Font is required');
|
||||
}
|
||||
|
||||
return {
|
||||
content: {
|
||||
text: status.content,
|
||||
},
|
||||
option: {
|
||||
backgroundColor: status.backgroundColor,
|
||||
font: status.font,
|
||||
statusJidList: status.statusJidList,
|
||||
},
|
||||
};
|
||||
}
|
||||
if (status.type === 'image') {
|
||||
this.logger.verbose('Type defined as image');
|
||||
|
||||
return {
|
||||
content: {
|
||||
image: {
|
||||
url: status.content,
|
||||
},
|
||||
caption: status.caption,
|
||||
},
|
||||
option: {
|
||||
statusJidList: status.statusJidList,
|
||||
},
|
||||
};
|
||||
}
|
||||
if (status.type === 'video') {
|
||||
this.logger.verbose('Type defined as video');
|
||||
|
||||
return {
|
||||
content: {
|
||||
video: {
|
||||
url: status.content,
|
||||
},
|
||||
caption: status.caption,
|
||||
},
|
||||
option: {
|
||||
statusJidList: status.statusJidList,
|
||||
},
|
||||
};
|
||||
}
|
||||
if (status.type === 'audio') {
|
||||
this.logger.verbose('Type defined as audio');
|
||||
|
||||
this.logger.verbose('Processing audio');
|
||||
const convert = await this.processAudio(status.content, 'status@broadcast');
|
||||
if (typeof convert === 'string') {
|
||||
this.logger.verbose('Audio processed');
|
||||
const audio = fs.readFileSync(convert).toString('base64');
|
||||
|
||||
const result = {
|
||||
content: {
|
||||
audio: Buffer.from(audio, 'base64'),
|
||||
ptt: true,
|
||||
mimetype: 'audio/mp4',
|
||||
},
|
||||
option: {
|
||||
statusJidList: status.statusJidList,
|
||||
},
|
||||
};
|
||||
|
||||
fs.unlinkSync(convert);
|
||||
|
||||
return result;
|
||||
} else {
|
||||
throw new InternalServerErrorException(convert);
|
||||
}
|
||||
}
|
||||
|
||||
throw new BadRequestException('Type not found');
|
||||
}
|
||||
|
||||
public async statusMessage(data: SendStatusDto) {
|
||||
this.logger.verbose('Sending status message');
|
||||
return await this.sendMessageWithTyping('status@broadcast', {
|
||||
status: await this.formatStatusMessage(data.statusMessage),
|
||||
});
|
||||
}
|
||||
|
||||
private async prepareMediaMessage(mediaMessage: MediaMessage) {
|
||||
try {
|
||||
this.logger.verbose('Preparing media message');
|
||||
@ -1890,11 +2116,11 @@ export class WAStartupService {
|
||||
public async fetchContacts(query: ContactQuery) {
|
||||
this.logger.verbose('Fetching contacts');
|
||||
if (query?.where) {
|
||||
query.where.owner = this.instance.wuid;
|
||||
query.where.owner = this.instance.name;
|
||||
} else {
|
||||
query = {
|
||||
where: {
|
||||
owner: this.instance.wuid,
|
||||
owner: this.instance.name,
|
||||
},
|
||||
};
|
||||
}
|
||||
@ -1904,11 +2130,11 @@ export class WAStartupService {
|
||||
public async fetchMessages(query: MessageQuery) {
|
||||
this.logger.verbose('Fetching messages');
|
||||
if (query?.where) {
|
||||
query.where.owner = this.instance.wuid;
|
||||
query.where.owner = this.instance.name;
|
||||
} else {
|
||||
query = {
|
||||
where: {
|
||||
owner: this.instance.wuid,
|
||||
owner: this.instance.name,
|
||||
},
|
||||
limit: query?.limit,
|
||||
};
|
||||
@ -1919,11 +2145,11 @@ export class WAStartupService {
|
||||
public async fetchStatusMessage(query: MessageUpQuery) {
|
||||
this.logger.verbose('Fetching status messages');
|
||||
if (query?.where) {
|
||||
query.where.owner = this.instance.wuid;
|
||||
query.where.owner = this.instance.name;
|
||||
} else {
|
||||
query = {
|
||||
where: {
|
||||
owner: this.instance.wuid,
|
||||
owner: this.instance.name,
|
||||
},
|
||||
limit: query?.limit,
|
||||
};
|
||||
@ -1933,7 +2159,7 @@ export class WAStartupService {
|
||||
|
||||
public async fetchChats() {
|
||||
this.logger.verbose('Fetching chats');
|
||||
return await this.repository.chat.find({ where: { owner: this.instance.wuid } });
|
||||
return await this.repository.chat.find({ where: { owner: this.instance.name } });
|
||||
}
|
||||
|
||||
public async fetchPrivacySettings() {
|
||||
|
Loading…
Reference in New Issue
Block a user