import { INestApplication } from '@nestjs/common'; import { DocumentBuilder, OpenAPIObject, SwaggerModule } from '@nestjs/swagger'; import { DECORATORS } from '@nestjs/swagger/dist/constants'; import { BasicAuthFunction } from '@waha/core/auth/basicAuth'; import { DashboardConfigServiceCore } from '@waha/core/config/DashboardConfigServiceCore'; import { Logger } from 'nestjs-pino'; import { WhatsappConfigService } from '../config.service'; import { VERSION } from '../version'; import { SwaggerConfigServiceCore } from './config/SwaggerConfigServiceCore'; export class SwaggerConfiguratorCore { protected logger: any; private config: SwaggerConfigServiceCore; constructor(protected app: INestApplication) { this.logger = app.get(Logger); this.config = app.get(SwaggerConfigServiceCore); } get title() { return this.config.title || 'WAHA - WhatsApp HTTP API'; } get description() { if (this.config.description) { return this.config.description; } return ( 'WhatsApp HTTP API that you can run in a click!
' + '📊 Dashboard
' + '
' + 'Learn more:' + '' + '

Support the project and get WAHA Plus version!

' + '' ); } get externalDocUrl() { return this.config.externalDocUrl || 'https://waha.devlike.pro/'; } configure(webhooks: any[]) { if (!this.config.enabled) { return; } const credentials = this.config.credentials; if (credentials) { this.setUpAuth(credentials); } const app = this.app; const builder = new DocumentBuilder(); builder .setTitle(this.title) .setDescription(this.description) .setExternalDoc(this.title, this.externalDocUrl) .setVersion(VERSION.version) .addTag('🖥️ Sessions', 'Control WhatsApp sessions (accounts)') .addTag('🧩 Apps', 'Applications (built-in integrations)') .addTag('🔑 Auth', 'Authentication') .addTag('🆔 Profile', 'Your profile information') .addTag('🖼️ Screenshot', 'Get screenshot of WhatsApp and show QR code') .addTag('📤 Chatting', 'Chatting methods') .addTag('📢 Channels', 'Channels (newsletters) methods') .addTag('🟢 Status', 'Status (aka stories) methods') .addTag('💬 Chats', `Chats methods`) .addTag( '👤 Contacts', `Contacts methods.
Use phone number (without +) or phone number and \`@c.us\` at the end as \`contactId\`.
'E.g: \`12312312310\` OR \`12312312310@c.us\`
`, ) .addTag('👥 Groups', `Groups methods.
`) .addTag('✅ Presence', `Presence information`) .addTag('📅 Events', `Event Message`) .addTag( '🏷️ Labels', 'Labels - available only for WhatsApp Business accounts', ) .addTag('🖼️ Media', 'Media methods') .addTag('🔍 Observability', 'Other methods') .addTag('🗄️ Storage', 'Storage methods') .addApiKey({ type: 'apiKey', description: 'Your secret api key', name: 'X-Api-Key', }); const config = app.get(WhatsappConfigService); const swaggerConfig = app.get(SwaggerConfigServiceCore); if (swaggerConfig.advancedConfigEnabled) { builder.addServer('{protocol}://{host}:{port}/{baseUrl}', '', { protocol: { default: 'http', enum: ['http', 'https'], description: 'The protocol used to access the server.', }, host: { default: config.hostname, description: 'The hostname or IP address of the server.', }, port: { default: config.port, description: 'The port number on which the server is listening for requests', }, baseUrl: { default: '', description: 'The base URL path for all API endpoints. This can be used to group related endpoints together under a common path.', }, }); } const swaggerDocumentConfig = builder.build(); const swaggerDocumentOptions = { extraModels: webhooks, }; let document = SwaggerModule.createDocument( app, swaggerDocumentConfig, swaggerDocumentOptions, ); document = this.configureWebhooks(document, webhooks); SwaggerModule.setup('', app, document, { customSiteTitle: this.title, }); } private configureWebhooks(document: OpenAPIObject, supportedWebhooks) { document.openapi = '3.1.0'; const webhooks = {}; for (const webhook of supportedWebhooks) { const eventMetadata = Reflect.getMetadata( DECORATORS.API_MODEL_PROPERTIES, webhook.prototype, 'event', ); const event = new webhook().event; const schemaName = webhook.name; webhooks[event] = { post: { summary: eventMetadata.description, deprecated: eventMetadata.deprecated || false, requestBody: { content: { 'application/json': { schema: { $ref: `#/components/schemas/${schemaName}`, }, }, }, }, responses: { '200': { description: 'Return a 200 status to indicate that the data was received successfully', }, }, }, }; } // @ts-ignore document.webhooks = webhooks; return document; } setUpAuth(credentials: [string, string]): void { const [username, password] = credentials; const dashboardConfig = this.app.get(DashboardConfigServiceCore); const exclude = [ '/api/', dashboardConfig.dashboardUri, '/health', '/ws', '/webhooks/', ]; const authFunction = BasicAuthFunction(username, password, exclude); this.app.use(authFunction); } }