|
import { |
|
ConsoleLogger, |
|
Injectable, |
|
LogLevel, |
|
NotFoundException, |
|
UnprocessableEntityException, |
|
} from '@nestjs/common'; |
|
|
|
import { WhatsappConfigService } from '../config.service'; |
|
import { getLogLevels } from '../helpers'; |
|
import { WAHAEngine, WAHASessionStatus } from '../structures/enums.dto'; |
|
import { |
|
ProxyConfig, |
|
SessionDTO, |
|
SessionInfo, |
|
SessionLogoutRequest, |
|
SessionStartRequest, |
|
SessionStopRequest, |
|
} from '../structures/sessions.dto'; |
|
import { WebhookConfig } from '../structures/webhooks.config.dto'; |
|
import { SessionManager } from './abc/manager.abc'; |
|
import { SessionParams, WhatsappSession } from './abc/session.abc'; |
|
import { WhatsappSessionNoWebCore } from './engines/noweb/session.noweb.core'; |
|
import { WhatsappSessionVenomCore } from './engines/venom/session.venom.core'; |
|
import { WhatsappSessionWebJSCore } from './engines/webjs/session.webjs.core'; |
|
import { DOCS_URL } from './exceptions'; |
|
import { getProxyConfig } from './helpers.proxy'; |
|
import { CoreMediaManager, MediaStorageCore } from './media.core'; |
|
import { LocalSessionAuthRepository } from './storage/LocalSessionAuthRepository'; |
|
import { LocalSessionConfigRepository } from './storage/LocalSessionConfigRepository'; |
|
import { LocalStoreCore } from './storage/LocalStoreCore'; |
|
import { WebhookConductorCore } from './webhooks.core'; |
|
|
|
export class OnlyDefaultSessionIsAllowed extends UnprocessableEntityException { |
|
constructor() { |
|
super( |
|
`WAHA Core support only 'default' session. If you want to run more then one WhatsApp account - please get WAHA PLUS version. Check this out: ${DOCS_URL}`, |
|
); |
|
} |
|
} |
|
|
|
export function buildLogger(name: string, levels: LogLevel[]) { |
|
return new ConsoleLogger(name, { logLevels: levels }); |
|
} |
|
|
|
@Injectable() |
|
export class SessionManagerCore extends SessionManager { |
|
private session?: WhatsappSession; |
|
DEFAULT = 'default'; |
|
|
|
|
|
protected WebhookConductorClass = WebhookConductorCore; |
|
protected readonly EngineClass: typeof WhatsappSession; |
|
|
|
constructor( |
|
private config: WhatsappConfigService, |
|
private log: ConsoleLogger, |
|
) { |
|
super(); |
|
|
|
this.log.setContext('SessionManager'); |
|
this.session = undefined; |
|
const engineName = this.config.getDefaultEngineName(); |
|
this.EngineClass = this.getEngine(engineName); |
|
this.store = new LocalStoreCore(engineName.toLowerCase()); |
|
this.sessionAuthRepository = new LocalSessionAuthRepository(this.store); |
|
this.sessionConfigRepository = new LocalSessionConfigRepository(this.store); |
|
this.startPredefinedSessions(); |
|
} |
|
|
|
protected startPredefinedSessions() { |
|
const startSessions = this.config.startSessions; |
|
startSessions.forEach((sessionName) => { |
|
this.start({ name: sessionName }); |
|
}); |
|
} |
|
|
|
protected getEngine(engine: WAHAEngine): typeof WhatsappSession { |
|
if (engine === WAHAEngine.WEBJS) { |
|
return WhatsappSessionWebJSCore; |
|
} else if (engine === WAHAEngine.VENOM) { |
|
return WhatsappSessionVenomCore; |
|
} else if (engine === WAHAEngine.NOWEB) { |
|
return WhatsappSessionNoWebCore; |
|
} else { |
|
throw new NotFoundException(`Unknown whatsapp engine '${engine}'.`); |
|
} |
|
} |
|
|
|
private onlyDefault(name: string) { |
|
if (name !== this.DEFAULT) { |
|
throw new OnlyDefaultSessionIsAllowed(); |
|
} |
|
} |
|
|
|
async onApplicationShutdown(signal?: string) { |
|
if (!this.session) { |
|
return; |
|
} |
|
await this.stop({ name: this.DEFAULT, logout: false }); |
|
} |
|
|
|
|
|
|
|
|
|
async start(request: SessionStartRequest): Promise<SessionDTO> { |
|
this.onlyDefault(request.name); |
|
|
|
const name = request.name; |
|
this.log.log(`'${name}' - starting session...`); |
|
const levels = getLogLevels(request.config?.debug); |
|
const log = buildLogger(`WhatsappSession - ${name}`, levels); |
|
const mediaManager = new CoreMediaManager( |
|
new MediaStorageCore(), |
|
this.config.mimetypes, |
|
); |
|
const webhookLog = buildLogger(`Webhook - ${name}`, levels); |
|
const webhook = new this.WebhookConductorClass(webhookLog); |
|
const proxyConfig = this.getProxyConfig(request); |
|
const sessionConfig: SessionParams = { |
|
name, |
|
mediaManager, |
|
log, |
|
sessionStore: this.store, |
|
proxyConfig: proxyConfig, |
|
sessionConfig: request.config, |
|
}; |
|
await this.sessionAuthRepository.init(name); |
|
|
|
const session = new this.EngineClass(sessionConfig); |
|
this.session = session; |
|
|
|
|
|
const webhooks = this.getWebhooks(request); |
|
webhook.configure(session, webhooks); |
|
|
|
|
|
await session.start(); |
|
return { |
|
name: session.name, |
|
status: session.status, |
|
config: session.sessionConfig, |
|
}; |
|
} |
|
|
|
|
|
|
|
|
|
private getWebhooks(request: SessionStartRequest) { |
|
let webhooks: WebhookConfig[] = []; |
|
if (request.config?.webhooks) { |
|
webhooks = webhooks.concat(request.config.webhooks); |
|
} |
|
const globalWebhookConfig = this.config.getWebhookConfig(); |
|
if (globalWebhookConfig) { |
|
webhooks.push(globalWebhookConfig); |
|
} |
|
return webhooks; |
|
} |
|
|
|
|
|
|
|
|
|
protected getProxyConfig( |
|
request: SessionStartRequest, |
|
): ProxyConfig | undefined { |
|
if (request.config?.proxy) { |
|
return request.config.proxy; |
|
} |
|
if (!this.session) { |
|
return undefined; |
|
} |
|
const sessions = { [request.name]: this.session }; |
|
return getProxyConfig(this.config, sessions, request.name); |
|
} |
|
|
|
async stop(request: SessionStopRequest): Promise<void> { |
|
this.onlyDefault(request.name); |
|
|
|
const name = request.name; |
|
this.log.log(`Stopping ${name} session...`); |
|
const session = this.getSession(name); |
|
await session.stop(); |
|
this.log.log(`"${name}" has been stopped.`); |
|
this.session = undefined; |
|
} |
|
|
|
async logout(request: SessionLogoutRequest) { |
|
await this.sessionAuthRepository.clean(request.name); |
|
} |
|
|
|
getSession(name: string): WhatsappSession { |
|
this.onlyDefault(name); |
|
const session = this.session; |
|
if (!session) { |
|
throw new NotFoundException( |
|
`We didn't find a session with name '${name}'. Please start it first by using POST /sessions/start request`, |
|
); |
|
} |
|
return session; |
|
} |
|
|
|
async getSessions(all: boolean): Promise<SessionInfo[]> { |
|
if (!this.session) { |
|
if (!all) { |
|
return []; |
|
} |
|
return [ |
|
{ |
|
name: this.DEFAULT, |
|
status: WAHASessionStatus.STOPPED, |
|
config: undefined, |
|
me: null, |
|
}, |
|
]; |
|
} |
|
const me = await this.session.getSessionMeInfo().catch((err) => null); |
|
const engine = { |
|
engine: this.session?.engine, |
|
...(await this.session?.getEngineInfo().catch((err) => ({}))), |
|
}; |
|
return [ |
|
{ |
|
name: this.session.name, |
|
status: this.session.status, |
|
config: this.session.sessionConfig, |
|
me: me, |
|
engine: engine, |
|
}, |
|
]; |
|
} |
|
} |
|
|