Rocket.Chat
Communication Tool
Rocket.Chat
Overview
Rocket.Chat is an open-source enterprise team collaboration platform. With a modern Slack-like UI while being completely operable in self-hosted environments, it's ideal for enterprises prioritizing data sovereignty. It offers rich API, Webhook integration features, custom app development through Apps-Engine, and Docker support for advanced customization.
Details
Rocket.Chat is an open-source team collaboration platform released in 2015. Developed in JavaScript (Meteor framework), it has gained adoption in enterprises and development teams as a self-hostable Slack alternative. It's particularly suitable for organizations prioritizing security and privacy.
In 2024-2025, major upgrades were made including migration to Node.js 20.x and Meteor 3.0, MongoDB 7.0 support addition, E2EE (End-to-End Encryption) enhancement, and introduction of a new bot and app development framework through Apps-Engine. Traditional Bots integration features are deprecated, and Apps-Engine-based development is now recommended.
Rocket.Chat API provides REST API, Realtime API, and Livechat API, enabling advanced integration with external systems through comprehensive Webhook functionality and custom script execution. With Docker & Docker Compose easy deployment, rich plugin ecosystem, and MongoDB integration, you can build scalable and extensible chat platforms.
Pros and Cons
Pros
- Completely Open Source: Source code availability, free customization
- Self-Host Support: Complete own-environment operation, data sovereignty assurance
- Rich APIs: REST API, Realtime API, Livechat API
- Apps-Engine: Powerful app and bot development framework
- E2EE Support: End-to-end encryption for security
- Webhook Features: Comprehensive webhook integration and custom scripts
- Docker Support: Easy deployment and containerization
- Cost Efficiency: Unlimited usage in self-hosted environments
Cons
- Operational Costs: Need for server construction and maintenance management
- Technical Requirements: Technical demands for setup and customization
- UI/UX: Usability challenges compared to Slack
- Plugin Ecosystem: Limited third-party integration scope
- Mobile Experience: Native app feature limitations
- Learning Curve: Learning costs for Apps-Engine development
Key Links
- Rocket.Chat Official Site
- Rocket.Chat Developer Portal
- Rocket.Chat API Reference
- GitHub Repository
- Documentation
- Apps-Engine Documentation
- Docker Official Image
Code Examples
Rocket.Chat Apps-Engine App Development
// apps/sample-app/SampleApp.ts - Apps-Engine app main
import {
IConfigurationExtend,
IEnvironmentRead,
ILogger,
IRead,
IModify,
IPersistence,
IHttp,
} from '@rocket.chat/apps-engine/definition/accessors';
import { App } from '@rocket.chat/apps-engine/definition/App';
import { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';
import {
IMessage,
IPreMessageSentPrevent,
IPostMessageSent,
} from '@rocket.chat/apps-engine/definition/messages';
import { ISlashCommand, SlashCommandContext } from '@rocket.chat/apps-engine/definition/slashcommands';
export class SampleApp extends App implements IPreMessageSentPrevent, IPostMessageSent {
constructor(info: IAppInfo, logger: ILogger) {
super(info, logger);
}
// App initialization configuration
public async initialize(configurationExtend: IConfigurationExtend, environmentRead: IEnvironmentRead): Promise<void> {
// Register slash command
await configurationExtend.slashCommands.provideSlashCommand(new SampleSlashCommand());
// Register API endpoint
await configurationExtend.api.provideApi({
visibility: ApiVisibility.PUBLIC,
security: ApiSecurity.UNSECURE,
endpoints: [new SampleEndpoint(this)],
});
}
// Pre-message processing
public async executePreMessageSentPrevent(
message: IMessage,
read: IRead,
http: IHttp,
persistence: IPersistence,
): Promise<boolean> {
// Block specific keywords
if (message.text && message.text.includes('blocked-word')) {
return true; // Block message
}
return false; // Allow message
}
// Post-message processing
public async executePostMessageSent(
message: IMessage,
read: IRead,
http: IHttp,
persistence: IPersistence,
modify: IModify,
): Promise<void> {
// Auto-response implementation
if (message.text && message.text.includes('help')) {
const messageBuilder = modify.getCreator().startMessage()
.setSender(await read.getUserReader().getById('rocket.cat'))
.setRoom(message.room)
.setText('🚀 Help information sent!');
await modify.getCreator().finish(messageBuilder);
}
// External API integration
if (message.text && message.text.includes('weather')) {
await this.sendWeatherInfo(message, modify, http, read);
}
}
private async sendWeatherInfo(
message: IMessage,
modify: IModify,
http: IHttp,
read: IRead,
): Promise<void> {
try {
// External weather API call
const response = await http.get('https://api.openweathermap.org/data/2.5/weather', {
params: {
q: 'Tokyo',
appid: 'your-api-key',
units: 'metric',
},
});
if (response.statusCode === 200 && response.data) {
const weather = response.data;
const messageBuilder = modify.getCreator().startMessage()
.setSender(await read.getUserReader().getById('rocket.cat'))
.setRoom(message.room)
.setText(`🌤️ Tokyo Weather: ${weather.weather[0].description}, Temperature: ${weather.main.temp}°C`);
await modify.getCreator().finish(messageBuilder);
}
} catch (error) {
console.error('Weather API error:', error);
}
}
}
// Slash command implementation
class SampleSlashCommand implements ISlashCommand {
public command = 'sample';
public i18nParamsExample = 'sample_params';
public i18nDescription = 'sample_description';
public providesPreview = false;
public async executor(context: SlashCommandContext, read: IRead, modify: IModify): Promise<void> {
const messageBuilder = modify.getCreator().startMessage()
.setSender(context.getSender())
.setRoom(context.getRoom())
.setText('🚀 Sample command executed!');
await modify.getCreator().finish(messageBuilder);
}
}
Webhook Integration Script
// Incoming Webhook script - GitHub integration example
class Script {
process_incoming_request({ request }) {
console.log('GitHub Webhook received:', request.content);
const eventType = request.headers['x-github-event'];
switch (eventType) {
case 'push':
return this.handlePushEvent(request.content);
case 'pull_request':
return this.handlePullRequestEvent(request.content);
case 'issues':
return this.handleIssueEvent(request.content);
default:
return this.handleUnknownEvent(eventType);
}
}
handlePushEvent(payload) {
const commits = payload.commits;
const repository = payload.repository;
const pusher = payload.pusher;
let commitMessages = commits.map(commit => {
const shortId = commit.id.substring(0, 7);
return `• [${shortId}](${commit.url}) ${commit.message}`;
}).join('\n');
return {
content: {
username: 'GitHub',
icon_url: 'https://github.com/fluidicon.png',
text: `🚀 **Push to ${repository.full_name}**`,
attachments: [{
color: '#28a745',
title: `${commits.length} commits pushed by ${pusher.name}`,
text: commitMessages,
title_link: payload.compare,
fields: [
{
title: 'Repository',
value: `[${repository.full_name}](${repository.html_url})`,
short: true
},
{
title: 'Branch',
value: payload.ref.split('/').pop(),
short: true
}
]
}]
}
};
}
handlePullRequestEvent(payload) {
const pr = payload.pull_request;
const action = payload.action;
const colors = {
opened: '#28a745',
closed: pr.merged ? '#6f42c1' : '#d73a49',
reopened: '#28a745'
};
const emoji = {
opened: '📝',
closed: pr.merged ? '🎉' : '❌',
reopened: '🔄'
};
return {
content: {
username: 'GitHub',
icon_url: payload.sender.avatar_url,
text: `${emoji[action]} **Pull Request ${action}**`,
attachments: [{
color: colors[action] || '#0366d6',
title: `#${pr.number} - ${pr.title}`,
title_link: pr.html_url,
text: pr.body,
author_name: pr.user.login,
author_link: pr.user.html_url,
author_icon: pr.user.avatar_url,
fields: [
{
title: 'Repository',
value: `[${payload.repository.full_name}](${payload.repository.html_url})`,
short: true
},
{
title: 'Branch',
value: `${pr.head.ref} → ${pr.base.ref}`,
short: true
}
]
}]
}
};
}
handleIssueEvent(payload) {
const issue = payload.issue;
const action = payload.action;
return {
content: {
username: 'GitHub',
icon_url: payload.sender.avatar_url,
text: `🐛 **Issue ${action}**`,
attachments: [{
color: action === 'closed' ? '#28a745' : '#d73a49',
title: `#${issue.number} - ${issue.title}`,
title_link: issue.html_url,
text: issue.body,
author_name: issue.user.login,
author_link: issue.user.html_url,
author_icon: issue.user.avatar_url
}]
}
};
}
handleUnknownEvent(eventType) {
return {
content: {
text: `⚠️ Unknown GitHub event: ${eventType}`
}
};
}
}
Outgoing Webhook Script
// Outgoing Webhook script - External service integration
class Script {
prepare_outgoing_request({ request }) {
const message = request.data.text;
const command = message.split(' ')[0];
switch (command) {
case '/weather':
return this.prepareWeatherRequest(request);
case '/translate':
return this.prepareTranslateRequest(request);
case '/jira':
return this.prepareJiraRequest(request);
case '/deploy':
return this.prepareDeployRequest(request);
default:
return this.prepareHelpResponse();
}
}
prepareWeatherRequest(request) {
const city = request.data.text.split(' ')[1] || 'Tokyo';
return {
url: 'https://api.openweathermap.org/data/2.5/weather',
method: 'GET',
params: {
q: city,
appid: 'your-weather-api-key',
units: 'metric'
}
};
}
prepareTranslateRequest(request) {
const text = request.data.text.replace('/translate', '').trim();
return {
url: 'https://api.mymemory.translated.net/get',
method: 'GET',
params: {
q: text,
langpair: 'ja|en'
}
};
}
prepareJiraRequest(request) {
const issueKey = request.data.text.split(' ')[1];
return {
url: `https://your-domain.atlassian.net/rest/api/2/issue/${issueKey}`,
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.JIRA_TOKEN}`,
'Content-Type': 'application/json'
}
};
}
prepareDeployRequest(request) {
const environment = request.data.text.split(' ')[1] || 'staging';
return {
url: 'https://api.your-deploy-service.com/deploy',
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.DEPLOY_TOKEN}`,
'Content-Type': 'application/json'
},
data: {
environment: environment,
branch: 'main',
user: request.data.user_name
}
};
}
process_outgoing_response({ request, response }) {
const originalMessage = request.data.text;
const command = originalMessage.split(' ')[0];
switch (command) {
case '/weather':
return this.processWeatherResponse(response);
case '/translate':
return this.processTranslateResponse(response);
case '/jira':
return this.processJiraResponse(response);
case '/deploy':
return this.processDeployResponse(response);
default:
return { content: { text: 'Unknown command response' } };
}
}
processWeatherResponse(response) {
if (response.status_code === 200) {
const weather = response.content;
return {
content: {
text: `🌤️ **Weather in ${weather.name}**`,
attachments: [{
color: '#87CEEB',
fields: [
{
title: 'Weather',
value: weather.weather[0].description,
short: true
},
{
title: 'Temperature',
value: `${weather.main.temp}°C`,
short: true
},
{
title: 'Humidity',
value: `${weather.main.humidity}%`,
short: true
},
{
title: 'Wind Speed',
value: `${weather.wind.speed} m/s`,
short: true
}
]
}]
}
};
} else {
return {
content: {
text: '❌ Failed to fetch weather information'
}
};
}
}
processTranslateResponse(response) {
if (response.status_code === 200) {
const translation = response.content.responseData.translatedText;
return {
content: {
text: `🔤 **Translation Result**: ${translation}`
}
};
} else {
return {
content: {
text: '❌ Translation failed'
}
};
}
}
processJiraResponse(response) {
if (response.status_code === 200) {
const issue = response.content;
return {
content: {
text: `🎫 **JIRA Issue: ${issue.key}**`,
attachments: [{
color: '#0052CC',
title: issue.fields.summary,
title_link: `https://your-domain.atlassian.net/browse/${issue.key}`,
text: issue.fields.description,
fields: [
{
title: 'Status',
value: issue.fields.status.name,
short: true
},
{
title: 'Assignee',
value: issue.fields.assignee?.displayName || 'Unassigned',
short: true
}
]
}]
}
};
} else {
return {
content: {
text: '❌ Failed to fetch JIRA issue'
}
};
}
}
processDeployResponse(response) {
if (response.status_code === 200) {
const deploy = response.content;
return {
content: {
text: `🚀 **Deployment Started**`,
attachments: [{
color: '#28a745',
fields: [
{
title: 'Environment',
value: deploy.environment,
short: true
},
{
title: 'Deploy ID',
value: deploy.id,
short: true
},
{
title: 'Status',
value: 'In Progress',
short: true
}
]
}]
}
};
} else {
return {
content: {
text: '❌ Failed to start deployment'
}
};
}
}
}
REST API Bot Development
// Node.js Rocket.Chat Bot implementation
const axios = require('axios');
class RocketChatBot {
constructor(serverUrl, username, password) {
this.serverUrl = serverUrl;
this.username = username;
this.password = password;
this.userId = null;
this.authToken = null;
}
// Login authentication
async login() {
try {
const response = await axios.post(`${this.serverUrl}/api/v1/login`, {
username: this.username,
password: this.password
});
this.userId = response.data.data.userId;
this.authToken = response.data.data.authToken;
console.log('✅ Bot login successful');
return true;
} catch (error) {
console.error('❌ Login failed:', error.response?.data || error.message);
return false;
}
}
// Send message
async sendMessage(roomId, message, attachments = []) {
try {
const response = await axios.post(
`${this.serverUrl}/api/v1/chat.postMessage`,
{
roomId: roomId,
text: message,
attachments: attachments
},
{
headers: {
'X-Auth-Token': this.authToken,
'X-User-Id': this.userId
}
}
);
return response.data;
} catch (error) {
console.error('Message send error:', error.response?.data || error.message);
throw error;
}
}
// Get channels list
async getChannels() {
try {
const response = await axios.get(
`${this.serverUrl}/api/v1/channels.list`,
{
headers: {
'X-Auth-Token': this.authToken,
'X-User-Id': this.userId
}
}
);
return response.data.channels;
} catch (error) {
console.error('Get channels error:', error.response?.data || error.message);
throw error;
}
}
// Get message history
async getMessages(roomId, count = 50) {
try {
const response = await axios.get(
`${this.serverUrl}/api/v1/channels.history`,
{
params: {
roomId: roomId,
count: count
},
headers: {
'X-Auth-Token': this.authToken,
'X-User-Id': this.userId
}
}
);
return response.data.messages;
} catch (error) {
console.error('Get messages error:', error.response?.data || error.message);
throw error;
}
}
// File upload
async uploadFile(roomId, filePath, description = '') {
const FormData = require('form-data');
const fs = require('fs');
const form = new FormData();
form.append('file', fs.createReadStream(filePath));
form.append('description', description);
try {
const response = await axios.post(
`${this.serverUrl}/api/v1/rooms.upload/${roomId}`,
form,
{
headers: {
...form.getHeaders(),
'X-Auth-Token': this.authToken,
'X-User-Id': this.userId
}
}
);
return response.data;
} catch (error) {
console.error('File upload error:', error.response?.data || error.message);
throw error;
}
}
// Real-time message monitoring (WebSocket)
startMessageListener() {
const WebSocket = require('ws');
const ws = new WebSocket(`${this.serverUrl.replace('http', 'ws')}/websocket`);
ws.on('open', () => {
console.log('WebSocket connected');
// Authentication
ws.send(JSON.stringify({
msg: 'connect',
version: '1',
support: ['1']
}));
ws.send(JSON.stringify({
msg: 'method',
method: 'login',
params: [{
resume: this.authToken
}],
id: '1'
}));
// Subscribe to message stream
ws.send(JSON.stringify({
msg: 'sub',
id: 'messages',
name: 'stream-notify-user',
params: [`${this.userId}/message`, false]
}));
});
ws.on('message', (data) => {
try {
const message = JSON.parse(data);
if (message.msg === 'changed' && message.collection === 'stream-notify-user') {
this.handleIncomingMessage(message.fields.args[1]);
}
} catch (error) {
console.error('WebSocket message parse error:', error);
}
});
return ws;
}
async handleIncomingMessage(messageData) {
// Ignore bot's own messages
if (messageData.u._id === this.userId) return;
const message = messageData.msg;
const roomId = messageData.rid;
const user = messageData.u;
console.log(`📥 Message from ${user.username}: ${message}`);
// Command processing
if (message.startsWith('!')) {
await this.processCommand(message, roomId, user);
}
// Keyword monitoring
if (message.toLowerCase().includes('help')) {
await this.sendHelpMessage(roomId);
}
}
async processCommand(message, roomId, user) {
const [command, ...args] = message.slice(1).split(' ');
switch (command.toLowerCase()) {
case 'status':
await this.sendSystemStatus(roomId);
break;
case 'weather':
await this.sendWeatherInfo(roomId, args[0] || 'Tokyo');
break;
case 'joke':
await this.sendRandomJoke(roomId);
break;
default:
await this.sendMessage(roomId, `❓ Unknown command: ${command}`);
}
}
async sendSystemStatus(roomId) {
const os = require('os');
const statusMessage = {
roomId: roomId,
text: '📊 **System Status**',
attachments: [{
color: '#28a745',
fields: [
{
title: 'Uptime',
value: `${Math.floor(os.uptime() / 3600)}h ${Math.floor((os.uptime() % 3600) / 60)}m`,
short: true
},
{
title: 'Memory Usage',
value: `${Math.round((os.totalmem() - os.freemem()) / os.totalmem() * 100)}%`,
short: true
},
{
title: 'Platform',
value: `${os.platform()} ${os.arch()}`,
short: true
},
{
title: 'Node Version',
value: process.version,
short: true
}
]
}]
};
await this.sendMessage(statusMessage.roomId, statusMessage.text, statusMessage.attachments);
}
async sendHelpMessage(roomId) {
const helpMessage = `
🤖 **Bot Commands**
\`!status\` - Display system status
\`!weather [city]\` - Get weather information
\`!joke\` - Display random joke
\`help\` - Show this help
**Other features:**
• Auto-response
• File monitoring
• External API integration
`;
await this.sendMessage(roomId, helpMessage);
}
}
// Bot usage example
async function startBot() {
const bot = new RocketChatBot(
'https://your-rocketchat.com',
'bot-username',
'bot-password'
);
if (await bot.login()) {
// Start WebSocket connection
bot.startMessageListener();
// Periodic task execution
setInterval(async () => {
const channels = await bot.getChannels();
const generalChannel = channels.find(c => c.name === 'general');
if (generalChannel) {
await bot.sendMessage(
generalChannel._id,
'⏰ Periodic report: System is operating normally'
);
}
}, 3600000); // Every hour
}
}
startBot().catch(console.error);
Docker Compose Configuration
# docker-compose.yml
version: '3.8'
services:
rocketchat:
image: registry.rocket.chat/rocketchat/rocket.chat:${RELEASE:-latest}
container_name: rocketchat
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.rocketchat.rule=Host(`${DOMAIN}`)"
- "traefik.http.routers.rocketchat.tls=true"
- "traefik.http.routers.rocketchat.entrypoints=https"
- "traefik.http.routers.rocketchat.tls.certresolver=le"
environment:
MONGO_URL: "mongodb://mongodb:27017/rocketchat"
MONGO_OPLOG_URL: "mongodb://mongodb:27017/local"
ROOT_URL: "https://${DOMAIN}"
PORT: 3000
DEPLOY_METHOD: docker
DEPLOY_PLATFORM: ${DEPLOY_PLATFORM:-}
REG_TOKEN: ${REG_TOKEN:-}
depends_on:
- mongodb
expose:
- 3000
volumes:
- rocketchat_uploads:/app/uploads
mongodb:
image: docker.io/bitnami/mongodb:${MONGODB_VERSION:-5.0}
container_name: mongodb
restart: unless-stopped
volumes:
- mongodb_data:/bitnami/mongodb
environment:
MONGODB_REPLICA_SET_MODE: primary
MONGODB_REPLICA_SET_NAME: rs0
MONGODB_PORT_NUMBER: 27017
MONGODB_INITIAL_PRIMARY_HOST: mongodb
MONGODB_INITIAL_PRIMARY_PORT_NUMBER: 27017
MONGODB_ADVERTISED_HOSTNAME: mongodb
MONGODB_ENABLE_JOURNAL: true
ALLOW_EMPTY_PASSWORD: yes
# Traefik reverse proxy
traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
command:
- "--api.dashboard=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.https.address=:443"
- "--certificatesresolvers.le.acme.tlschallenge=true"
- "--certificatesresolvers.le.acme.email=${LETSENCRYPT_EMAIL}"
- "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "traefik_letsencrypt:/letsencrypt"
volumes:
mongodb_data:
rocketchat_uploads:
traefik_letsencrypt:
networks:
default:
name: rocketchat_network
Environment Variables Configuration
# .env file
# Basic settings
DOMAIN=your-domain.com
[email protected]
RELEASE=6.0.0
MONGODB_VERSION=5.0
# Rocket.Chat settings
ROOT_URL=https://your-domain.com
PORT=3000
MONGO_URL=mongodb://mongodb:27017/rocketchat
MONGO_OPLOG_URL=mongodb://mongodb:27017/local
# Optional deployment settings
DEPLOY_METHOD=docker
DEPLOY_PLATFORM=
REG_TOKEN=
# API settings
ROCKETCHAT_URL=https://your-domain.com
ROCKETCHAT_USERNAME=admin
ROCKETCHAT_PASSWORD=your-admin-password
# Bot settings
BOT_USERNAME=automation-bot
BOT_PASSWORD=bot-password
# External API keys
WEATHER_API_KEY=your-weather-api-key
JIRA_TOKEN=your-jira-token
GITHUB_TOKEN=your-github-token
# Webhook URLs
SLACK_WEBHOOK_URL=your-slack-webhook-url
TEAMS_WEBHOOK_URL=your-teams-webhook-url
System Metrics Monitoring
// monitoring.js - System monitoring script
const { RocketChatBot } = require('./rocketchat-bot');
const os = require('os');
class SystemMonitor {
constructor(bot, alertChannelId) {
this.bot = bot;
this.alertChannelId = alertChannelId;
this.thresholds = {
cpu: 80,
memory: 85,
disk: 90
};
}
async startMonitoring() {
setInterval(async () => {
await this.checkSystemHealth();
}, 300000); // Every 5 minutes
console.log('🔍 System monitoring started');
}
async checkSystemHealth() {
const metrics = await this.getSystemMetrics();
if (this.shouldAlert(metrics)) {
await this.sendAlert(metrics);
}
// Daily report (once a day)
const now = new Date();
if (now.getHours() === 9 && now.getMinutes() < 5) {
await this.sendDailyReport(metrics);
}
}
async getSystemMetrics() {
const cpuUsage = await this.getCpuUsage();
const memoryUsage = this.getMemoryUsage();
const diskUsage = await this.getDiskUsage();
return {
cpu: cpuUsage,
memory: memoryUsage,
disk: diskUsage,
uptime: os.uptime(),
timestamp: new Date()
};
}
async getCpuUsage() {
const cpus = os.cpus();
let totalIdle = 0;
let totalTick = 0;
cpus.forEach(cpu => {
for (let type in cpu.times) {
totalTick += cpu.times[type];
}
totalIdle += cpu.times.idle;
});
return Math.round(100 - (totalIdle / totalTick) * 100);
}
getMemoryUsage() {
const total = os.totalmem();
const free = os.freemem();
return Math.round(((total - free) / total) * 100);
}
async getDiskUsage() {
const { exec } = require('child_process');
return new Promise((resolve) => {
exec("df -h / | awk 'NR==2{print $5}' | sed 's/%//'", (error, stdout) => {
resolve(error ? 0 : parseInt(stdout.trim()));
});
});
}
shouldAlert(metrics) {
return metrics.cpu > this.thresholds.cpu ||
metrics.memory > this.thresholds.memory ||
metrics.disk > this.thresholds.disk;
}
async sendAlert(metrics) {
const alertMessage = {
text: '🚨 **System Alert**',
attachments: [{
color: '#d73a49',
title: 'High resource usage detected',
fields: [
{
title: 'CPU Usage',
value: `${metrics.cpu}%`,
short: true
},
{
title: 'Memory Usage',
value: `${metrics.memory}%`,
short: true
},
{
title: 'Disk Usage',
value: `${metrics.disk}%`,
short: true
},
{
title: 'Uptime',
value: `${Math.floor(metrics.uptime / 3600)}h ${Math.floor((metrics.uptime % 3600) / 60)}m`,
short: true
}
],
timestamp: metrics.timestamp.toISOString()
}]
};
await this.bot.sendMessage(
this.alertChannelId,
alertMessage.text,
alertMessage.attachments
);
}
}
// Usage example
async function startMonitoring() {
const bot = new RocketChatBot(
process.env.ROCKETCHAT_URL,
process.env.BOT_USERNAME,
process.env.BOT_PASSWORD
);
if (await bot.login()) {
const channels = await bot.getChannels();
const alertChannel = channels.find(c => c.name === 'alerts');
if (alertChannel) {
const monitor = new SystemMonitor(bot, alertChannel._id);
await monitor.startMonitoring();
}
}
}
startMonitoring().catch(console.error);