mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-12-09 01:49:37 -06:00
160 lines
6.1 KiB
TypeScript
160 lines
6.1 KiB
TypeScript
import { authGuard } from '@api/guards/auth.guard';
|
|
import { instanceExistsGuard, instanceLoggedGuard } from '@api/guards/instance.guard';
|
|
import Telemetry from '@api/guards/telemetry.guard';
|
|
import { ChannelRouter } from '@api/integrations/channel/channel.router';
|
|
import { ChatbotRouter } from '@api/integrations/chatbot/chatbot.router';
|
|
import { EventRouter } from '@api/integrations/event/event.router';
|
|
import { StorageRouter } from '@api/integrations/storage/storage.router';
|
|
import { waMonitor } from '@api/server.module';
|
|
import { configService } from '@config/env.config';
|
|
import { fetchLatestWaWebVersion } from '@utils/fetchLatestWaWebVersion';
|
|
import { Router } from 'express';
|
|
import fs from 'fs';
|
|
import mimeTypes from 'mime-types';
|
|
import path from 'path';
|
|
|
|
import { BusinessRouter } from './business.router';
|
|
import { CallRouter } from './call.router';
|
|
import { ChatRouter } from './chat.router';
|
|
import { GroupRouter } from './group.router';
|
|
import { InstanceRouter } from './instance.router';
|
|
import { LabelRouter } from './label.router';
|
|
import { ProxyRouter } from './proxy.router';
|
|
import { MessageRouter } from './sendMessage.router';
|
|
import { SettingsRouter } from './settings.router';
|
|
import { TemplateRouter } from './template.router';
|
|
import { ViewsRouter } from './view.router';
|
|
|
|
enum HttpStatus {
|
|
OK = 200,
|
|
CREATED = 201,
|
|
NOT_FOUND = 404,
|
|
FORBIDDEN = 403,
|
|
BAD_REQUEST = 400,
|
|
UNAUTHORIZED = 401,
|
|
INTERNAL_SERVER_ERROR = 500,
|
|
}
|
|
|
|
const router: Router = Router();
|
|
const serverConfig = configService.get('SERVER');
|
|
const guards = [instanceExistsGuard, instanceLoggedGuard, authGuard['apikey']];
|
|
|
|
const telemetry = new Telemetry();
|
|
|
|
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
|
|
|
// Expose Prometheus metrics when enabled by env flag
|
|
if (process.env.PROMETHEUS_METRICS === 'true') {
|
|
router.get('/metrics', async (req, res) => {
|
|
res.set('Content-Type', 'text/plain; version=0.0.4; charset=utf-8');
|
|
res.set('Cache-Control', 'no-cache, no-store, must-revalidate');
|
|
|
|
const escapeLabel = (value: unknown) =>
|
|
String(value ?? '')
|
|
.replace(/\\/g, '\\\\')
|
|
.replace(/\n/g, '\\n')
|
|
.replace(/"/g, '\\"');
|
|
|
|
const lines: string[] = [];
|
|
|
|
const clientName = process.env.DATABASE_CONNECTION_CLIENT_NAME || 'unknown';
|
|
const serverUrl = serverConfig.URL || '';
|
|
|
|
// environment info
|
|
lines.push('# HELP evolution_environment_info Environment information');
|
|
lines.push('# TYPE evolution_environment_info gauge');
|
|
lines.push(
|
|
`evolution_environment_info{version="${escapeLabel(packageJson.version)}",clientName="${escapeLabel(
|
|
clientName,
|
|
)}",serverUrl="${escapeLabel(serverUrl)}"} 1`,
|
|
);
|
|
|
|
const instances = (waMonitor && waMonitor.waInstances) || {};
|
|
const instanceEntries = Object.entries(instances);
|
|
|
|
// total instances
|
|
lines.push('# HELP evolution_instances_total Total number of instances');
|
|
lines.push('# TYPE evolution_instances_total gauge');
|
|
lines.push(`evolution_instances_total ${instanceEntries.length}`);
|
|
|
|
// per-instance status
|
|
lines.push('# HELP evolution_instance_up 1 if instance state is open, else 0');
|
|
lines.push('# TYPE evolution_instance_up gauge');
|
|
lines.push('# HELP evolution_instance_state Instance state as a labelled metric');
|
|
lines.push('# TYPE evolution_instance_state gauge');
|
|
|
|
for (const [name, instance] of instanceEntries) {
|
|
const state = instance?.connectionStatus?.state || 'unknown';
|
|
const integration = instance?.integration || '';
|
|
const up = state === 'open' ? 1 : 0;
|
|
|
|
lines.push(
|
|
`evolution_instance_up{instance="${escapeLabel(name)}",integration="${escapeLabel(integration)}"} ${up}`,
|
|
);
|
|
lines.push(
|
|
`evolution_instance_state{instance="${escapeLabel(name)}",integration="${escapeLabel(
|
|
integration,
|
|
)}",state="${escapeLabel(state)}"} 1`,
|
|
);
|
|
}
|
|
|
|
res.send(lines.join('\n') + '\n');
|
|
});
|
|
}
|
|
|
|
if (!serverConfig.DISABLE_MANAGER) router.use('/manager', new ViewsRouter().router);
|
|
|
|
router.get('/assets/*', (req, res) => {
|
|
const fileName = req.params[0];
|
|
const basePath = path.join(process.cwd(), 'manager', 'dist');
|
|
|
|
const filePath = path.join(basePath, 'assets/', fileName);
|
|
|
|
if (fs.existsSync(filePath)) {
|
|
res.set('Content-Type', mimeTypes.lookup(filePath) || 'text/css');
|
|
res.send(fs.readFileSync(filePath));
|
|
} else {
|
|
res.status(404).send('File not found');
|
|
}
|
|
});
|
|
|
|
router
|
|
.use((req, res, next) => telemetry.collectTelemetry(req, res, next))
|
|
|
|
.get('/', async (req, res) => {
|
|
res.status(HttpStatus.OK).json({
|
|
status: HttpStatus.OK,
|
|
message: 'Welcome to the Evolution API, it is working!',
|
|
version: packageJson.version,
|
|
clientName: process.env.DATABASE_CONNECTION_CLIENT_NAME,
|
|
manager: !serverConfig.DISABLE_MANAGER ? `${req.protocol}://${req.get('host')}/manager` : undefined,
|
|
documentation: `https://doc.evolution-api.com`,
|
|
whatsappWebVersion: (await fetchLatestWaWebVersion({})).version.join('.'),
|
|
});
|
|
})
|
|
.post('/verify-creds', authGuard['apikey'], async (req, res) => {
|
|
return res.status(HttpStatus.OK).json({
|
|
status: HttpStatus.OK,
|
|
message: 'Credentials are valid',
|
|
facebookAppId: process.env.FACEBOOK_APP_ID,
|
|
facebookConfigId: process.env.FACEBOOK_CONFIG_ID,
|
|
facebookUserToken: process.env.FACEBOOK_USER_TOKEN,
|
|
});
|
|
})
|
|
.use('/instance', new InstanceRouter(configService, ...guards).router)
|
|
.use('/message', new MessageRouter(...guards).router)
|
|
.use('/call', new CallRouter(...guards).router)
|
|
.use('/chat', new ChatRouter(...guards).router)
|
|
.use('/business', new BusinessRouter(...guards).router)
|
|
.use('/group', new GroupRouter(...guards).router)
|
|
.use('/template', new TemplateRouter(configService, ...guards).router)
|
|
.use('/settings', new SettingsRouter(...guards).router)
|
|
.use('/proxy', new ProxyRouter(...guards).router)
|
|
.use('/label', new LabelRouter(...guards).router)
|
|
.use('', new ChannelRouter(configService, ...guards).router)
|
|
.use('', new EventRouter(configService, ...guards).router)
|
|
.use('', new ChatbotRouter(...guards).router)
|
|
.use('', new StorageRouter(...guards).router);
|
|
|
|
export { HttpStatus, router };
|