mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-17 04:59:41 +02:00
Complete GDPR-compliant bot suite for Matrix: matrix-stats-bot (port 3312): - Analytics reports from Umami - Commands: !stats, !today, !week, !realtime, !users - Scheduled daily/weekly reports to Matrix room matrix-project-doc-bot (port 3313): - Project documentation with photos, voice, text - Voice transcription via OpenAI Whisper - Blog generation with 5 styles (casual, technical, tutorial, social, story) - Commands: !new, !projects, !switch, !status, !generate, !export - Uses PostgreSQL + S3 (MinIO) for storage Changes: - docker-compose.macmini.yml: Added both Matrix bots - health-check.sh: Added health checks for both bots Environment variables required: - MATRIX_STATS_BOT_TOKEN, MATRIX_PROJECT_DOC_BOT_TOKEN - OPENAI_API_KEY (for Project Doc Bot) https://claude.ai/code/session_01E3r5aFW3YLAhEJfsL2ryhv
55 lines
1.7 KiB
TypeScript
55 lines
1.7 KiB
TypeScript
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
|
|
import { ConfigService } from '@nestjs/config';
|
|
import postgres from 'postgres';
|
|
|
|
interface UserStats {
|
|
total: number;
|
|
verified: number;
|
|
lastWeek: number;
|
|
lastMonth: number;
|
|
}
|
|
|
|
@Injectable()
|
|
export class UsersService implements OnModuleInit {
|
|
private readonly logger = new Logger(UsersService.name);
|
|
private sql: postgres.Sql | null = null;
|
|
|
|
constructor(private configService: ConfigService) {}
|
|
|
|
async onModuleInit() {
|
|
const databaseUrl = this.configService.get<string>('database.url');
|
|
if (databaseUrl) {
|
|
try {
|
|
this.sql = postgres(databaseUrl);
|
|
this.logger.log('Database connected for user stats');
|
|
} catch (error) {
|
|
this.logger.warn('Failed to connect to database:', error);
|
|
}
|
|
} else {
|
|
this.logger.warn('DATABASE_URL not configured - user stats disabled');
|
|
}
|
|
}
|
|
|
|
async getUserStats(): Promise<UserStats | null> {
|
|
if (!this.sql) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
const [totalResult] = await this.sql`SELECT COUNT(*) as count FROM "user"`;
|
|
const [verifiedResult] = await this.sql`SELECT COUNT(*) as count FROM "user" WHERE "emailVerified" = true`;
|
|
const [weekResult] = await this.sql`SELECT COUNT(*) as count FROM "user" WHERE "createdAt" > NOW() - INTERVAL '7 days'`;
|
|
const [monthResult] = await this.sql`SELECT COUNT(*) as count FROM "user" WHERE "createdAt" > NOW() - INTERVAL '30 days'`;
|
|
|
|
return {
|
|
total: parseInt(totalResult.count, 10),
|
|
verified: parseInt(verifiedResult.count, 10),
|
|
lastWeek: parseInt(weekResult.count, 10),
|
|
lastMonth: parseInt(monthResult.count, 10),
|
|
};
|
|
} catch (error) {
|
|
this.logger.error('Failed to get user stats:', error);
|
|
return null;
|
|
}
|
|
}
|
|
}
|