mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 21:41:09 +02:00
🐛 fix(matrix-web): handle Matrix SSO loginToken callback
Add loginWithLoginToken function to exchange Matrix SSO loginToken for credentials. The app layout now detects the loginToken URL parameter and completes the SSO flow. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
9e9db590dc
commit
dc0d425f61
53 changed files with 1550 additions and 230 deletions
|
|
@ -1,7 +1,7 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { MatrixService } from './matrix.service';
|
||||
import { CalendarModule } from '../calendar/calendar.module';
|
||||
import { TranscriptionModule } from '@manacore/bot-services';
|
||||
import { TranscriptionModule, SessionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -9,6 +9,8 @@ import { TranscriptionModule } from '@manacore/bot-services';
|
|||
TranscriptionModule.register({
|
||||
sttUrl: process.env.STT_URL || 'http://localhost:3020',
|
||||
}),
|
||||
SessionModule.forRoot(),
|
||||
CreditModule.forRoot(),
|
||||
],
|
||||
providers: [MatrixService],
|
||||
exports: [MatrixService],
|
||||
|
|
|
|||
|
|
@ -7,10 +7,12 @@ import {
|
|||
KeywordCommandDetector,
|
||||
COMMON_KEYWORDS,
|
||||
} from '@manacore/matrix-bot-common';
|
||||
import { TranscriptionService } from '@manacore/bot-services';
|
||||
import { TranscriptionService, SessionService, CreditService } from '@manacore/bot-services';
|
||||
import { CalendarService, CalendarEvent } from '../calendar/calendar.service';
|
||||
import { HELP_TEXT, WELCOME_TEXT, BOT_INTRODUCTION } from '../config/configuration';
|
||||
|
||||
const EVENT_CREATE_CREDITS = 0.02;
|
||||
|
||||
@Injectable()
|
||||
export class MatrixService extends BaseMatrixService {
|
||||
private readonly keywordDetector = new KeywordCommandDetector(
|
||||
|
|
@ -29,7 +31,9 @@ export class MatrixService extends BaseMatrixService {
|
|||
constructor(
|
||||
configService: ConfigService,
|
||||
private readonly transcriptionService: TranscriptionService,
|
||||
private calendarService: CalendarService
|
||||
private calendarService: CalendarService,
|
||||
private sessionService: SessionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
}
|
||||
|
|
@ -157,6 +161,14 @@ export class MatrixService extends BaseMatrixService {
|
|||
await this.handlePinHelp(roomId, event);
|
||||
break;
|
||||
|
||||
case 'login':
|
||||
await this.handleLogin(roomId, event, userId, args);
|
||||
break;
|
||||
|
||||
case 'logout':
|
||||
await this.handleLogout(roomId, event, userId);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unknown command - ignore silently
|
||||
break;
|
||||
|
|
@ -237,6 +249,21 @@ export class MatrixService extends BaseMatrixService {
|
|||
return;
|
||||
}
|
||||
|
||||
// Validate credits if user is logged in
|
||||
const token = this.sessionService.getToken(userId);
|
||||
if (token) {
|
||||
const validation = await this.creditService.validateCredits(token, EVENT_CREATE_CREDITS);
|
||||
if (!validation.hasCredits) {
|
||||
const errorMsg = this.creditService.formatInsufficientCreditsError(
|
||||
EVENT_CREATE_CREDITS,
|
||||
validation.availableCredits,
|
||||
'Termin erstellen'
|
||||
);
|
||||
await this.sendReply(roomId, event, errorMsg.text);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const { title, startTime, endTime, isAllDay } = this.calendarService.parseEventInput(input);
|
||||
|
||||
if (!startTime || !endTime) {
|
||||
|
|
@ -264,7 +291,15 @@ export class MatrixService extends BaseMatrixService {
|
|||
);
|
||||
|
||||
const timeStr = this.calendarService.formatEventTime(calendarEvent);
|
||||
await this.sendReply(roomId, event, `✅ Termin erstellt: **${title}**\n📆 ${timeStr}`);
|
||||
let response = `✅ Termin erstellt: **${title}**\n📆 ${timeStr}`;
|
||||
|
||||
// Show credit deduction if logged in
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
response += `\n⚡ -${EVENT_CREATE_CREDITS} Credits (${balance.balance.toFixed(2)} verbleibend)`;
|
||||
}
|
||||
|
||||
await this.sendReply(roomId, event, response);
|
||||
}
|
||||
|
||||
private async handleEventDetails(roomId: string, event: MatrixRoomEvent, userId: string, args: string) {
|
||||
|
|
@ -339,16 +374,71 @@ export class MatrixService extends BaseMatrixService {
|
|||
const events = await this.calendarService.getUpcomingEvents(userId, 7);
|
||||
const todayEvents = await this.calendarService.getTodayEvents(userId);
|
||||
|
||||
const response = `📊 **Status**
|
||||
// Check login status and credits
|
||||
const token = this.sessionService.getToken(userId);
|
||||
const session = this.sessionService.getSession(userId);
|
||||
|
||||
• Termine heute: ${todayEvents.length}
|
||||
• Termine nächste 7 Tage: ${events.length}
|
||||
let response = `📊 **Status**\n\n`;
|
||||
response += `• Termine heute: ${todayEvents.length}\n`;
|
||||
response += `• Termine nächste 7 Tage: ${events.length}\n\n`;
|
||||
|
||||
Bot: ✅ Online`;
|
||||
if (token && session) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
response += `👤 Angemeldet als: ${session.email}\n`;
|
||||
response += `⚡ Credits: ${balance.balance.toFixed(2)}\n\n`;
|
||||
} else {
|
||||
response += `👤 Nicht angemeldet\n`;
|
||||
response += `💡 Login: \`!login email passwort\`\n\n`;
|
||||
}
|
||||
|
||||
response += `Bot: ✅ Online`;
|
||||
|
||||
await this.sendReply(roomId, event, response);
|
||||
}
|
||||
|
||||
private async handleLogin(roomId: string, event: MatrixRoomEvent, userId: string, args: string) {
|
||||
const parts = args.trim().split(/\s+/);
|
||||
if (parts.length < 2) {
|
||||
await this.sendReply(
|
||||
roomId,
|
||||
event,
|
||||
'❌ Bitte gib Email und Passwort an.\n\nBeispiel: `!login email@example.com passwort`'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const [email, password] = parts;
|
||||
const result = await this.sessionService.login(userId, email, password);
|
||||
|
||||
if (!result.success) {
|
||||
await this.sendReply(roomId, event, `❌ Login fehlgeschlagen: ${result.error}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const token = this.sessionService.getToken(userId);
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
await this.sendReply(
|
||||
roomId,
|
||||
event,
|
||||
`✅ Erfolgreich angemeldet als **${email}**\n⚡ Credits: ${balance.balance.toFixed(2)}`
|
||||
);
|
||||
} else {
|
||||
await this.sendReply(roomId, event, `✅ Erfolgreich angemeldet als **${email}**`);
|
||||
}
|
||||
}
|
||||
|
||||
private async handleLogout(roomId: string, event: MatrixRoomEvent, userId: string) {
|
||||
const session = this.sessionService.getSession(userId);
|
||||
if (!session) {
|
||||
await this.sendReply(roomId, event, '❌ Du bist nicht angemeldet.');
|
||||
return;
|
||||
}
|
||||
|
||||
this.sessionService.logout(userId);
|
||||
await this.sendReply(roomId, event, '✅ Erfolgreich abgemeldet.');
|
||||
}
|
||||
|
||||
private async handlePinHelp(roomId: string, event: MatrixRoomEvent) {
|
||||
try {
|
||||
// Send help message
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { MatrixService } from './matrix.service';
|
||||
import { ChatModule } from '../chat/chat.module';
|
||||
import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
||||
import { SessionModule, TranscriptionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -10,6 +10,7 @@ import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
|||
TranscriptionModule.register({
|
||||
sttUrl: process.env.STT_URL || 'http://localhost:3020',
|
||||
}),
|
||||
CreditModule.forRoot(),
|
||||
],
|
||||
providers: [MatrixService],
|
||||
exports: [MatrixService],
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
COMMON_KEYWORDS,
|
||||
} from '@manacore/matrix-bot-common';
|
||||
import { ChatService, Conversation } from '../chat/chat.service';
|
||||
import { SessionService, TranscriptionService } from '@manacore/bot-services';
|
||||
import { SessionService, TranscriptionService, CreditService, CreditErrorCode } from '@manacore/bot-services';
|
||||
import { HELP_MESSAGE, BRANCH_ICONS } from '../config/configuration';
|
||||
|
||||
@Injectable()
|
||||
|
|
@ -27,7 +27,8 @@ export class MatrixService extends BaseMatrixService {
|
|||
configService: ConfigService,
|
||||
private readonly transcriptionService: TranscriptionService,
|
||||
private chatService: ChatService,
|
||||
private sessionService: SessionService
|
||||
private sessionService: SessionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
}
|
||||
|
|
@ -136,7 +137,7 @@ export class MatrixService extends BaseMatrixService {
|
|||
break;
|
||||
|
||||
case 'status':
|
||||
response = this.handleStatus(sender);
|
||||
response = await this.handleStatus(sender);
|
||||
break;
|
||||
|
||||
case 'chat':
|
||||
|
|
@ -248,21 +249,38 @@ export class MatrixService extends BaseMatrixService {
|
|||
return 'Erfolgreich abgemeldet.';
|
||||
}
|
||||
|
||||
private handleStatus(sender: string): string {
|
||||
private async handleStatus(sender: string): Promise<string> {
|
||||
const isLoggedIn = this.sessionService.isLoggedIn(sender);
|
||||
const email = this.sessionService.getEmail(sender);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
const currentConv = this.getCurrentConversation(sender);
|
||||
const selectedModel = this.getSelectedModel(sender);
|
||||
|
||||
let status = `**Bot Status**\n`;
|
||||
status += `- Angemeldet: ${isLoggedIn ? 'Ja' : 'Nein'}\n`;
|
||||
// Get credit balance if logged in
|
||||
let creditBalance = { balance: 0, hasCredits: false };
|
||||
if (token) {
|
||||
creditBalance = await this.creditService.getBalance(token);
|
||||
}
|
||||
|
||||
const additionalInfo: Record<string, string> = {};
|
||||
if (currentConv) {
|
||||
status += `- Aktuelles Gespraech: ${currentConv.substring(0, 8)}...\n`;
|
||||
additionalInfo['🗨️ Gespraech'] = `${currentConv.substring(0, 8)}...`;
|
||||
}
|
||||
if (selectedModel) {
|
||||
status += `- Gewaehltes Modell: ${selectedModel.substring(0, 8)}...\n`;
|
||||
additionalInfo['🧠 Modell'] = `${selectedModel.substring(0, 8)}...`;
|
||||
}
|
||||
status += `- Aktive Sessions: ${this.sessionService.getSessionCount()}`;
|
||||
return status;
|
||||
|
||||
if (!isLoggedIn) {
|
||||
return `🤖 **Bot Status**\n\n❌ Nicht angemeldet.\n\nNutze \`!login email passwort\` zum Anmelden.`;
|
||||
}
|
||||
|
||||
const statusMessage = this.creditService.formatStatusMessage(
|
||||
email || 'Unbekannt',
|
||||
creditBalance,
|
||||
additionalInfo
|
||||
);
|
||||
|
||||
return statusMessage.text;
|
||||
}
|
||||
|
||||
// Quick chat (stateless)
|
||||
|
|
@ -292,6 +310,16 @@ export class MatrixService extends BaseMatrixService {
|
|||
);
|
||||
|
||||
if (result.error) {
|
||||
// Handle 402 Payment Required (insufficient credits)
|
||||
if (result.statusCode === 402) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
const errorMsg = this.creditService.formatInsufficientCreditsError(
|
||||
2, // AI Chat costs ~2 credits
|
||||
balance.balance,
|
||||
'AI Chat'
|
||||
);
|
||||
return errorMsg.text;
|
||||
}
|
||||
return `Fehler: ${result.error}`;
|
||||
}
|
||||
|
||||
|
|
@ -465,6 +493,16 @@ Nutze \`!senden [nachricht]\` um zu chatten oder \`!verlauf\` fuer den Nachricht
|
|||
// Get AI response
|
||||
const completionResult = await this.chatService.createCompletion(token, messages, convResult.data!.modelId);
|
||||
if (completionResult.error) {
|
||||
// Handle 402 Payment Required (insufficient credits)
|
||||
if (completionResult.statusCode === 402) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
const errorMsg = this.creditService.formatInsufficientCreditsError(
|
||||
2, // AI Chat costs ~2 credits
|
||||
balance.balance,
|
||||
'AI Chat'
|
||||
);
|
||||
return errorMsg.text;
|
||||
}
|
||||
return `Fehler bei AI-Antwort: ${completionResult.error}`;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ export class ChatService {
|
|||
path: string,
|
||||
token: string,
|
||||
options: RequestInit = {}
|
||||
): Promise<{ data?: T; error?: string }> {
|
||||
): Promise<{ data?: T; error?: string; statusCode?: number }> {
|
||||
try {
|
||||
const response = await fetch(this.getUrl(path), {
|
||||
...options,
|
||||
|
|
@ -72,7 +72,10 @@ export class ChatService {
|
|||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
return { error: errorData.message || `HTTP ${response.status}` };
|
||||
return {
|
||||
error: errorData.message || `HTTP ${response.status}`,
|
||||
statusCode: response.status,
|
||||
};
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
|
@ -118,7 +121,7 @@ export class ChatService {
|
|||
messages: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>,
|
||||
modelId: string,
|
||||
options?: { temperature?: number; maxTokens?: number }
|
||||
): Promise<{ data?: ChatCompletionResponse; error?: string }> {
|
||||
): Promise<{ data?: ChatCompletionResponse; error?: string; statusCode?: number }> {
|
||||
return this.request<ChatCompletionResponse>('/chat/completions', token, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { MatrixService } from './matrix.service';
|
||||
import { ClockModule } from '../clock/clock.module';
|
||||
import { TranscriptionModule } from '@manacore/bot-services';
|
||||
import { TranscriptionModule, SessionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [ClockModule, TranscriptionModule.forRoot()],
|
||||
imports: [ClockModule, TranscriptionModule.forRoot(), SessionModule.forRoot(), CreditModule.forRoot()],
|
||||
providers: [MatrixService],
|
||||
exports: [MatrixService],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
COMMON_KEYWORDS,
|
||||
} from '@manacore/matrix-bot-common';
|
||||
import { ClockService } from '../clock/clock.service';
|
||||
import { TranscriptionService } from '@manacore/bot-services';
|
||||
import { TranscriptionService, SessionService, CreditService } from '@manacore/bot-services';
|
||||
import { HELP_TEXT, WELCOME_TEXT } from '../config/configuration';
|
||||
|
||||
@Injectable()
|
||||
|
|
@ -28,7 +28,9 @@ export class MatrixService extends BaseMatrixService {
|
|||
constructor(
|
||||
configService: ConfigService,
|
||||
private clockService: ClockService,
|
||||
private transcriptionService: TranscriptionService
|
||||
private transcriptionService: TranscriptionService,
|
||||
private sessionService: SessionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
}
|
||||
|
|
@ -156,6 +158,14 @@ export class MatrixService extends BaseMatrixService {
|
|||
await this.sendReply(roomId, event, HELP_TEXT);
|
||||
break;
|
||||
|
||||
case 'login':
|
||||
await this.handleLogin(roomId, event, userId, args);
|
||||
break;
|
||||
|
||||
case 'logout':
|
||||
await this.handleLogout(roomId, event, userId);
|
||||
break;
|
||||
|
||||
case 'timer':
|
||||
await this.handleTimerCommand(roomId, event, userId, args);
|
||||
break;
|
||||
|
|
@ -337,34 +347,76 @@ export class MatrixService extends BaseMatrixService {
|
|||
}
|
||||
}
|
||||
|
||||
private async handleStatusCommand(roomId: string, event: MatrixRoomEvent, userId: string) {
|
||||
try {
|
||||
const token = this.getToken(userId);
|
||||
if (!token) {
|
||||
await this.sendReply(roomId, event, 'Keine Authentifizierung.');
|
||||
return;
|
||||
}
|
||||
|
||||
const timer = await this.clockService.getRunningTimer(token);
|
||||
if (!timer) {
|
||||
await this.sendReply(roomId, event, 'Kein aktiver Timer.\n\nStarte einen mit `!timer 25m`');
|
||||
return;
|
||||
}
|
||||
|
||||
const remaining = this.clockService.formatDuration(timer.remainingSeconds);
|
||||
const total = this.clockService.formatDuration(timer.durationSeconds);
|
||||
const statusIcon = timer.status === 'running' ? '' : '';
|
||||
const statusText = timer.status === 'running' ? 'Lauft' : 'Pausiert';
|
||||
|
||||
let response = `**${statusIcon} Timer ${statusText}**\n\n`;
|
||||
response += `Verbleibend: ${remaining} / ${total}`;
|
||||
if (timer.label) response += `\nLabel: ${timer.label}`;
|
||||
|
||||
await this.sendReply(roomId, event, response);
|
||||
} catch (error) {
|
||||
this.logger.error('Status failed:', error);
|
||||
await this.sendReply(roomId, event, 'Fehler beim Abrufen des Status.');
|
||||
private async handleLogin(roomId: string, event: MatrixRoomEvent, userId: string, args: string) {
|
||||
const parts = args.split(' ');
|
||||
if (parts.length < 2 || !parts[0] || !parts[1]) {
|
||||
await this.sendReply(roomId, event, 'Verwendung: `!login email passwort`');
|
||||
return;
|
||||
}
|
||||
const [email, password] = parts;
|
||||
const result = await this.sessionService.login(userId, email, password);
|
||||
|
||||
if (result.success) {
|
||||
const token = this.sessionService.getToken(userId);
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
await this.sendReply(roomId, event,
|
||||
`✅ Erfolgreich angemeldet als **${email}**\n⚡ Credits: ${balance.balance.toFixed(2)}`);
|
||||
} else {
|
||||
await this.sendReply(roomId, event, `✅ Erfolgreich angemeldet als **${email}**`);
|
||||
}
|
||||
} else {
|
||||
await this.sendReply(roomId, event, `❌ Anmeldung fehlgeschlagen: ${result.error}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async handleLogout(roomId: string, event: MatrixRoomEvent, userId: string) {
|
||||
this.sessionService.logout(userId);
|
||||
await this.sendReply(roomId, event, '👋 Erfolgreich abgemeldet.');
|
||||
}
|
||||
|
||||
private async handleStatusCommand(roomId: string, event: MatrixRoomEvent, userId: string) {
|
||||
// Auth-Status zuerst
|
||||
const loggedIn = this.sessionService.isLoggedIn(userId);
|
||||
const session = this.sessionService.getSession(userId);
|
||||
const token = this.sessionService.getToken(userId);
|
||||
|
||||
let response = '**🕐 Clock Bot Status**\n\n';
|
||||
|
||||
if (loggedIn && session && token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
response += `👤 Angemeldet als: ${session.email}\n`;
|
||||
response += `⚡ Credits: ${balance.balance.toFixed(2)}\n\n`;
|
||||
} else {
|
||||
response += `❌ Nicht angemeldet\n`;
|
||||
response += `Nutze \`!login email passwort\` zum Anmelden.\n\n`;
|
||||
}
|
||||
|
||||
// Timer-Status
|
||||
try {
|
||||
const timerToken = this.getToken(userId);
|
||||
if (timerToken) {
|
||||
const timer = await this.clockService.getRunningTimer(timerToken);
|
||||
if (timer) {
|
||||
const remaining = this.clockService.formatDuration(timer.remainingSeconds);
|
||||
const total = this.clockService.formatDuration(timer.durationSeconds);
|
||||
const statusIcon = timer.status === 'running' ? '▶️' : '⏸️';
|
||||
const statusText = timer.status === 'running' ? 'Läuft' : 'Pausiert';
|
||||
response += `**${statusIcon} Timer ${statusText}**\n`;
|
||||
response += `Verbleibend: ${remaining} / ${total}`;
|
||||
if (timer.label) response += `\nLabel: ${timer.label}`;
|
||||
} else {
|
||||
response += `Kein aktiver Timer.\n\nStarte einen mit \`!timer 25m\``;
|
||||
}
|
||||
} else {
|
||||
response += `Timer-Status nicht verfügbar (nicht angemeldet).`;
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error('Timer status failed:', error);
|
||||
response += `Timer-Status nicht verfügbar.`;
|
||||
}
|
||||
|
||||
await this.sendReply(roomId, event, response);
|
||||
}
|
||||
|
||||
private async handleTimersCommand(roomId: string, event: MatrixRoomEvent, userId: string) {
|
||||
|
|
@ -603,11 +655,15 @@ export class MatrixService extends BaseMatrixService {
|
|||
}
|
||||
|
||||
private getToken(userId: string): string | null {
|
||||
// First check if user has a stored token
|
||||
// SessionService hat Priorität (Login via mana-core-auth)
|
||||
const sessionToken = this.sessionService.getToken(userId);
|
||||
if (sessionToken) return sessionToken;
|
||||
|
||||
// Fallback auf clockService Token
|
||||
const storedToken = this.clockService.getUserToken(userId);
|
||||
if (storedToken) return storedToken;
|
||||
|
||||
// Fall back to demo token for development
|
||||
// Entwicklungs-Fallback
|
||||
return this.demoToken || null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,12 +16,16 @@ export default () => ({
|
|||
|
||||
export const HELP_TEXT = `**Clock Bot - Zeiterfassung per Chat**
|
||||
|
||||
**Account:**
|
||||
- \`!login email passwort\` - Anmelden
|
||||
- \`!logout\` - Abmelden
|
||||
- \`!status\` - Account & Timer Status
|
||||
|
||||
**Timer (Stoppuhr):**
|
||||
- \`!timer 25m\` oder \`!timer 1h30m\` - Timer erstellen & starten
|
||||
- \`!stop\` - Laufenden Timer pausieren
|
||||
- \`!resume\` - Pausierten Timer fortsetzen
|
||||
- \`!reset\` - Timer zurucksetzen
|
||||
- \`!status\` - Aktuellen Timer-Status anzeigen
|
||||
- \`!timers\` - Alle Timer anzeigen
|
||||
|
||||
**Alarme (Wecker):**
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { MatrixService } from './matrix.service';
|
||||
import { ContactsModule } from '../contacts/contacts.module';
|
||||
import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
||||
import { SessionModule, TranscriptionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -10,6 +10,7 @@ import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
|||
TranscriptionModule.register({
|
||||
sttUrl: process.env.STT_URL || 'http://localhost:3020',
|
||||
}),
|
||||
CreditModule.forRoot(),
|
||||
],
|
||||
providers: [MatrixService],
|
||||
exports: [MatrixService],
|
||||
|
|
|
|||
|
|
@ -9,9 +9,11 @@ import {
|
|||
UserListMapper,
|
||||
} from '@manacore/matrix-bot-common';
|
||||
import { ContactsService, Contact } from '../contacts/contacts.service';
|
||||
import { SessionService, TranscriptionService } from '@manacore/bot-services';
|
||||
import { SessionService, TranscriptionService, CreditService } from '@manacore/bot-services';
|
||||
import { HELP_MESSAGE } from '../config/configuration';
|
||||
|
||||
const CONTACT_CREATE_CREDITS = 0.02;
|
||||
|
||||
// Natural language keyword detector
|
||||
const keywordDetector = new KeywordCommandDetector([
|
||||
...COMMON_KEYWORDS,
|
||||
|
|
@ -29,7 +31,8 @@ export class MatrixService extends BaseMatrixService {
|
|||
configService: ConfigService,
|
||||
private readonly transcriptionService: TranscriptionService,
|
||||
private contactsService: ContactsService,
|
||||
private sessionService: SessionService
|
||||
private sessionService: SessionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
}
|
||||
|
|
@ -414,6 +417,18 @@ Sag "hilfe" fur alle Befehle!`;
|
|||
return;
|
||||
}
|
||||
|
||||
// Validate credits
|
||||
const validation = await this.creditService.validateCredits(token, CONTACT_CREATE_CREDITS);
|
||||
if (!validation.hasCredits) {
|
||||
const errorMsg = this.creditService.formatInsufficientCreditsError(
|
||||
CONTACT_CREATE_CREDITS,
|
||||
validation.availableCredits,
|
||||
'Kontakt erstellen'
|
||||
);
|
||||
await this.sendReply(roomId, event, errorMsg.text);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length < 1) {
|
||||
await this.sendReply(
|
||||
roomId,
|
||||
|
|
@ -433,10 +448,11 @@ Sag "hilfe" fur alle Befehle!`;
|
|||
});
|
||||
|
||||
const name = contact.displayName || `${firstName} ${lastName || ''}`.trim();
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
await this.sendReply(
|
||||
roomId,
|
||||
event,
|
||||
`Kontakt **${name}** erstellt!\n\nNutze \`!kontakte\` um die Liste zu sehen oder \`!edit\` um weitere Daten hinzuzufugen.`
|
||||
`Kontakt **${name}** erstellt!\n⚡ -${CONTACT_CREATE_CREDITS} Credits (${balance.balance.toFixed(2)} verbleibend)\n\nNutze \`!kontakte\` um die Liste zu sehen oder \`!edit\` um weitere Daten hinzuzufugen.`
|
||||
);
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : 'Unbekannter Fehler';
|
||||
|
|
@ -693,13 +709,23 @@ Sag "hilfe" fur alle Befehle!`;
|
|||
const result = await this.sessionService.login(sender, email, password);
|
||||
|
||||
if (result.success) {
|
||||
await this.sendReply(
|
||||
roomId,
|
||||
event,
|
||||
`Erfolgreich angemeldet!\n\nNutze \`!kontakte\` um deine Kontakte zu sehen.`
|
||||
);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
await this.sendReply(
|
||||
roomId,
|
||||
event,
|
||||
`✅ Erfolgreich angemeldet als **${email}**\n⚡ Credits: ${balance.balance.toFixed(2)}\n\nNutze \`!kontakte\` um deine Kontakte zu sehen.`
|
||||
);
|
||||
} else {
|
||||
await this.sendReply(
|
||||
roomId,
|
||||
event,
|
||||
`✅ Erfolgreich angemeldet!\n\nNutze \`!kontakte\` um deine Kontakte zu sehen.`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
await this.sendReply(roomId, event, `Anmeldung fehlgeschlagen: ${result.error}`);
|
||||
await this.sendReply(roomId, event, `❌ Anmeldung fehlgeschlagen: ${result.error}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -707,14 +733,21 @@ Sag "hilfe" fur alle Befehle!`;
|
|||
const backendHealthy = await this.contactsService.checkHealth();
|
||||
const isLoggedIn = this.sessionService.isLoggedIn(sender);
|
||||
const sessionCount = this.sessionService.getSessionCount();
|
||||
const session = this.sessionService.getSession(sender);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
|
||||
const statusText = `**Contacts Bot Status**
|
||||
let statusText = `**Contacts Bot Status**\n\n`;
|
||||
statusText += `**Backend:** ${backendHealthy ? '✅ Online' : '❌ Offline'}\n`;
|
||||
statusText += `**Aktive Sessions:** ${sessionCount}\n\n`;
|
||||
|
||||
**Backend:** ${backendHealthy ? 'Online' : 'Offline'}
|
||||
**Dein Status:** ${isLoggedIn ? 'Angemeldet' : 'Nicht angemeldet'}
|
||||
**Aktive Sessions:** ${sessionCount}
|
||||
|
||||
${!isLoggedIn ? 'Nutze `!login email passwort` um dich anzumelden.' : ''}`;
|
||||
if (isLoggedIn && session && token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
statusText += `👤 Angemeldet als: ${session.email}\n`;
|
||||
statusText += `⚡ Credits: ${balance.balance.toFixed(2)}\n`;
|
||||
} else {
|
||||
statusText += `👤 Nicht angemeldet\n`;
|
||||
statusText += `💡 Login: \`!login email passwort\``;
|
||||
}
|
||||
|
||||
await this.sendReply(roomId, event, statusText);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,16 @@ import { CommandRouterService } from './command-router.service';
|
|||
import { HandlersModule } from '../handlers/handlers.module';
|
||||
import { OrchestrationModule } from '../orchestration/orchestration.module';
|
||||
import { VoiceModule } from '../voice/voice.module';
|
||||
import { SessionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [forwardRef(() => HandlersModule), forwardRef(() => OrchestrationModule), VoiceModule],
|
||||
imports: [
|
||||
forwardRef(() => HandlersModule),
|
||||
forwardRef(() => OrchestrationModule),
|
||||
VoiceModule,
|
||||
SessionModule.forRoot(),
|
||||
CreditModule.forRoot(),
|
||||
],
|
||||
providers: [MatrixService, CommandRouterService],
|
||||
exports: [MatrixService, CommandRouterService],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -67,6 +67,18 @@ export class CommandRouterService {
|
|||
description: 'Show help',
|
||||
},
|
||||
|
||||
// Auth Commands
|
||||
{
|
||||
patterns: ['!login'],
|
||||
handler: (ctx, args) => this.helpHandler.handleLogin(ctx, args),
|
||||
description: 'Login with email and password',
|
||||
},
|
||||
{
|
||||
patterns: ['!logout'],
|
||||
handler: (ctx) => this.helpHandler.handleLogout(ctx),
|
||||
description: 'Logout',
|
||||
},
|
||||
|
||||
// AI Commands
|
||||
{
|
||||
patterns: ['!models', '!modelle'],
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { BaseMatrixService, MatrixBotConfig, MatrixRoomEvent } from '@manacore/m
|
|||
import { CommandRouterService, CommandContext } from './command-router.service';
|
||||
import { VoiceService, VoiceServiceError } from '../voice/voice.service';
|
||||
import { VoiceFormatterService } from '../voice/voice-formatter.service';
|
||||
import { SessionService, CreditService } from '@manacore/bot-services';
|
||||
import { HELP_TEXT, WELCOME_TEXT, BOT_INTRODUCTION } from '../config/configuration';
|
||||
|
||||
@Injectable()
|
||||
|
|
@ -16,7 +17,9 @@ export class MatrixService extends BaseMatrixService {
|
|||
private commandRouter: CommandRouterService,
|
||||
@Inject(forwardRef(() => VoiceService))
|
||||
private voiceService: VoiceService,
|
||||
private voiceFormatter: VoiceFormatterService
|
||||
private voiceFormatter: VoiceFormatterService,
|
||||
private sessionService: SessionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
this.voiceEnabled = configService.get('voice.enabled') !== false;
|
||||
|
|
|
|||
|
|
@ -37,6 +37,11 @@ export default () => ({
|
|||
// Help text for the unified bot
|
||||
export const HELP_TEXT = `**🤖 Mana - Dein Assistent**
|
||||
|
||||
**👤 Account**
|
||||
• \`!login email passwort\` - Anmelden
|
||||
• \`!logout\` - Abmelden
|
||||
• \`!status\` - Account & Bot Status
|
||||
|
||||
**AI & Chat**
|
||||
Schreib einfach eine Nachricht - ich antworte!
|
||||
• \`!model [name]\` - KI-Modell wechseln
|
||||
|
|
|
|||
|
|
@ -7,9 +7,10 @@ import { HelpHandler } from './help.handler';
|
|||
import { VoiceHandler } from './voice.handler';
|
||||
import { BotModule } from '../bot/bot.module';
|
||||
import { VoiceModule } from '../voice/voice.module';
|
||||
import { SessionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [forwardRef(() => BotModule), VoiceModule],
|
||||
imports: [forwardRef(() => BotModule), VoiceModule, SessionModule.forRoot(), CreditModule.forRoot()],
|
||||
providers: [AiHandler, TodoHandler, CalendarHandler, ClockHandler, HelpHandler, VoiceHandler],
|
||||
exports: [AiHandler, TodoHandler, CalendarHandler, ClockHandler, HelpHandler, VoiceHandler],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { AiService, TodoService } from '@manacore/bot-services';
|
||||
import { AiService, TodoService, SessionService, CreditService } from '@manacore/bot-services';
|
||||
import { CommandContext } from '../bot/command-router.service';
|
||||
import { VoiceService } from '../voice/voice.service';
|
||||
import { HELP_TEXT } from '../config/configuration';
|
||||
|
|
@ -9,14 +9,61 @@ export class HelpHandler {
|
|||
constructor(
|
||||
private aiService: AiService,
|
||||
private todoService: TodoService,
|
||||
private voiceService: VoiceService
|
||||
private voiceService: VoiceService,
|
||||
private sessionService: SessionService,
|
||||
private creditService: CreditService
|
||||
) {}
|
||||
|
||||
async showHelp(ctx: CommandContext): Promise<string> {
|
||||
return HELP_TEXT;
|
||||
}
|
||||
|
||||
async handleLogin(ctx: CommandContext, args: string): Promise<string> {
|
||||
const parts = args.split(' ');
|
||||
if (parts.length < 2 || !parts[0] || !parts[1]) {
|
||||
return 'Verwendung: `!login email passwort`';
|
||||
}
|
||||
const [email, password] = parts;
|
||||
const result = await this.sessionService.login(ctx.userId, email, password);
|
||||
|
||||
if (result.success) {
|
||||
const token = this.sessionService.getToken(ctx.userId);
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
return `✅ Erfolgreich angemeldet als **${email}**\n⚡ Credits: ${balance.balance.toFixed(2)}`;
|
||||
}
|
||||
return `✅ Erfolgreich angemeldet als **${email}**`;
|
||||
}
|
||||
return `❌ Anmeldung fehlgeschlagen: ${result.error}`;
|
||||
}
|
||||
|
||||
async handleLogout(ctx: CommandContext): Promise<string> {
|
||||
this.sessionService.logout(ctx.userId);
|
||||
return '👋 Erfolgreich abgemeldet.';
|
||||
}
|
||||
|
||||
async showStatus(ctx: CommandContext): Promise<string> {
|
||||
// Auth-Status zuerst
|
||||
const loggedIn = this.sessionService.isLoggedIn(ctx.userId);
|
||||
const session = this.sessionService.getSession(ctx.userId);
|
||||
const token = this.sessionService.getToken(ctx.userId);
|
||||
|
||||
let authSection = '';
|
||||
if (loggedIn && session && token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
authSection = `**👤 Account**
|
||||
• Angemeldet als: ${session.email}
|
||||
• Credits: ⚡ ${balance.balance.toFixed(2)}
|
||||
|
||||
`;
|
||||
} else {
|
||||
authSection = `**👤 Account**
|
||||
• Nicht angemeldet
|
||||
• Nutze \`!login email passwort\`
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
// Check services in parallel
|
||||
const [aiConnected, todoStats, voiceHealth] = await Promise.all([
|
||||
this.aiService.checkConnection(),
|
||||
|
|
@ -36,7 +83,7 @@ export class HelpHandler {
|
|||
|
||||
return `**📊 Status**
|
||||
|
||||
**AI/Ollama**
|
||||
${authSection}**AI/Ollama**
|
||||
• Verbindung: ${aiStatus}
|
||||
• Modell: \`${currentModel}\`
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { MatrixService } from './matrix.service';
|
||||
import { ManadeckModule } from '../manadeck/manadeck.module';
|
||||
import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
||||
import { SessionModule, TranscriptionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -10,6 +10,7 @@ import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
|||
TranscriptionModule.register({
|
||||
sttUrl: process.env.STT_URL || 'http://localhost:3020',
|
||||
}),
|
||||
CreditModule.forRoot(),
|
||||
],
|
||||
providers: [MatrixService],
|
||||
exports: [MatrixService],
|
||||
|
|
|
|||
|
|
@ -9,9 +9,12 @@ import {
|
|||
COMMON_KEYWORDS,
|
||||
} from '@manacore/matrix-bot-common';
|
||||
import { ManadeckService, Deck, Card } from '../manadeck/manadeck.service';
|
||||
import { SessionService, TranscriptionService } from '@manacore/bot-services';
|
||||
import { SessionService, TranscriptionService, CreditService } from '@manacore/bot-services';
|
||||
import { HELP_MESSAGE } from '../config/configuration';
|
||||
|
||||
const DECK_CREATE_CREDITS = 0.1;
|
||||
const AI_DECK_GENERATE_CREDITS = 20;
|
||||
|
||||
@Injectable()
|
||||
export class MatrixService extends BaseMatrixService {
|
||||
// Store last shown decks/cards per user for reference by number
|
||||
|
|
@ -36,7 +39,8 @@ export class MatrixService extends BaseMatrixService {
|
|||
configService: ConfigService,
|
||||
private readonly transcriptionService: TranscriptionService,
|
||||
private manadeckService: ManadeckService,
|
||||
private sessionService: SessionService
|
||||
private sessionService: SessionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
}
|
||||
|
|
@ -221,9 +225,15 @@ export class MatrixService extends BaseMatrixService {
|
|||
const result = await this.sessionService.login(sender, email, password);
|
||||
|
||||
if (result.success) {
|
||||
await this.sendHtml(roomId, `<p>Erfolgreich angemeldet als <strong>${email}</strong></p>`);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
await this.sendHtml(roomId, `<p>✅ Erfolgreich angemeldet als <strong>${email}</strong><br/>⚡ Credits: ${balance.balance.toFixed(2)}</p>`);
|
||||
} else {
|
||||
await this.sendHtml(roomId, `<p>✅ Erfolgreich angemeldet als <strong>${email}</strong></p>`);
|
||||
}
|
||||
} else {
|
||||
await this.sendHtml(roomId, `<p>Login fehlgeschlagen: ${result.error}</p>`);
|
||||
await this.sendHtml(roomId, `<p>❌ Login fehlgeschlagen: ${result.error}</p>`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -231,16 +241,24 @@ export class MatrixService extends BaseMatrixService {
|
|||
const backendOk = await this.manadeckService.checkHealth();
|
||||
const loggedIn = this.sessionService.isLoggedIn(sender);
|
||||
const sessions = this.sessionService.getSessionCount();
|
||||
const session = this.sessionService.getSession(sender);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
|
||||
await this.sendHtml(
|
||||
roomId,
|
||||
`<h3>ManaDeck Bot Status</h3>
|
||||
<ul>
|
||||
<li>Backend: ${backendOk ? 'Online' : 'Offline'}</li>
|
||||
<li>Angemeldet: ${loggedIn ? 'Ja' : 'Nein'}</li>
|
||||
<li>Aktive Sessions: ${sessions}</li>
|
||||
</ul>`
|
||||
);
|
||||
let statusHtml = `<h3>ManaDeck Bot Status</h3><ul>`;
|
||||
statusHtml += `<li>Backend: ${backendOk ? '✅ Online' : '❌ Offline'}</li>`;
|
||||
statusHtml += `<li>Aktive Sessions: ${sessions}</li>`;
|
||||
|
||||
if (loggedIn && session && token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
statusHtml += `<li>👤 Angemeldet als: ${session.email}</li>`;
|
||||
statusHtml += `<li>⚡ Credits: ${balance.balance.toFixed(2)}</li>`;
|
||||
} else {
|
||||
statusHtml += `<li>👤 Nicht angemeldet</li>`;
|
||||
statusHtml += `<li>💡 Login: <code>!login email passwort</code></li>`;
|
||||
}
|
||||
statusHtml += `</ul>`;
|
||||
|
||||
await this.sendHtml(roomId, statusHtml);
|
||||
}
|
||||
|
||||
// Deck handlers
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { MatrixService } from './matrix.service';
|
||||
import { NutriPhiModule } from '../nutriphi/nutriphi.module';
|
||||
import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
||||
import { SessionModule, TranscriptionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [NutriPhiModule, SessionModule.forRoot(), TranscriptionModule.forRoot()],
|
||||
imports: [NutriPhiModule, SessionModule.forRoot(), TranscriptionModule.forRoot(), CreditModule.forRoot()],
|
||||
providers: [MatrixService],
|
||||
exports: [MatrixService],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -13,9 +13,11 @@ import {
|
|||
DailySummary,
|
||||
WeeklyStats,
|
||||
} from '../nutriphi/nutriphi.service';
|
||||
import { SessionService, TranscriptionService } from '@manacore/bot-services';
|
||||
import { SessionService, TranscriptionService, CreditService } from '@manacore/bot-services';
|
||||
import { HELP_MESSAGE, MEAL_TYPE_LABELS } from '../config/configuration';
|
||||
|
||||
const PHOTO_ANALYSIS_CREDITS = 3;
|
||||
|
||||
// Natural language keyword detector
|
||||
const keywordDetector = new KeywordCommandDetector([
|
||||
...COMMON_KEYWORDS,
|
||||
|
|
@ -33,7 +35,8 @@ export class MatrixService extends BaseMatrixService {
|
|||
configService: ConfigService,
|
||||
private nutriphiService: NutriPhiService,
|
||||
private sessionService: SessionService,
|
||||
private transcriptionService: TranscriptionService
|
||||
private transcriptionService: TranscriptionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
}
|
||||
|
|
@ -256,10 +259,19 @@ Sag "hilfe" fur alle Befehle!`;
|
|||
const result = await this.sessionService.login(sender, email, password);
|
||||
|
||||
if (result.success) {
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`Erfolgreich angemeldet!\n\nDu kannst jetzt Fotos analysieren und deine Ernahrung tracken.`
|
||||
);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`✅ Erfolgreich angemeldet als **${email}**\n⚡ Credits: ${balance.balance.toFixed(2)}\n\nDu kannst jetzt Fotos analysieren und deine Ernahrung tracken.`
|
||||
);
|
||||
} else {
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`✅ Erfolgreich angemeldet!\n\nDu kannst jetzt Fotos analysieren und deine Ernahrung tracken.`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
await this.sendMessage(roomId, `Anmeldung fehlgeschlagen: ${result.error}`);
|
||||
}
|
||||
|
|
@ -614,15 +626,21 @@ Sag "hilfe" fur alle Befehle!`;
|
|||
const backendHealthy = await this.nutriphiService.checkHealth();
|
||||
const isLoggedIn = this.sessionService.isLoggedIn(sender);
|
||||
const sessionCount = this.sessionService.getSessionCount();
|
||||
const loggedInCount = this.sessionService.getActiveSessionCount();
|
||||
const session = this.sessionService.getSession(sender);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
|
||||
const statusText = `**NutriPhi Bot Status**
|
||||
let statusText = `**NutriPhi Bot Status**\n\n`;
|
||||
statusText += `**Backend:** ${backendHealthy ? '✅ Online' : '❌ Offline'}\n`;
|
||||
statusText += `**Aktive Sessions:** ${sessionCount}\n\n`;
|
||||
|
||||
**Backend:** ${backendHealthy ? 'Online' : 'Offline'}
|
||||
**Dein Status:** ${isLoggedIn ? 'Angemeldet' : 'Nicht angemeldet'}
|
||||
**Aktive Sessions:** ${sessionCount} (${loggedInCount} angemeldet)
|
||||
|
||||
${!isLoggedIn ? 'Nutze `!login email passwort` um dich anzumelden.' : ''}`;
|
||||
if (isLoggedIn && session && token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
statusText += `👤 Angemeldet als: ${session.email}\n`;
|
||||
statusText += `⚡ Credits: ${balance.balance.toFixed(2)}\n`;
|
||||
} else {
|
||||
statusText += `👤 Nicht angemeldet\n`;
|
||||
statusText += `💡 Login: \`!login email passwort\``;
|
||||
}
|
||||
|
||||
await this.sendMessage(roomId, statusText);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { MatrixService } from './matrix.service';
|
||||
import { OllamaModule } from '../ollama/ollama.module';
|
||||
import { TranscriptionModule } from '@manacore/bot-services';
|
||||
import { TranscriptionModule, SessionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -9,6 +9,8 @@ import { TranscriptionModule } from '@manacore/bot-services';
|
|||
TranscriptionModule.register({
|
||||
sttUrl: process.env.STT_URL || 'http://localhost:3020',
|
||||
}),
|
||||
SessionModule.forRoot(),
|
||||
CreditModule.forRoot(),
|
||||
],
|
||||
providers: [MatrixService],
|
||||
exports: [MatrixService],
|
||||
|
|
|
|||
|
|
@ -7,10 +7,13 @@ import {
|
|||
KeywordCommandDetector,
|
||||
COMMON_KEYWORDS,
|
||||
} from '@manacore/matrix-bot-common';
|
||||
import { TranscriptionService } from '@manacore/bot-services';
|
||||
import { TranscriptionService, SessionService, CreditService } from '@manacore/bot-services';
|
||||
import { OllamaService } from '../ollama/ollama.service';
|
||||
import { SYSTEM_PROMPTS } from '../config/configuration';
|
||||
|
||||
// Ollama is local, so credits are minimal
|
||||
const OLLAMA_CHAT_CREDITS = 0.1;
|
||||
|
||||
interface UserSession {
|
||||
systemPrompt: string;
|
||||
model: string;
|
||||
|
|
@ -39,7 +42,9 @@ export class MatrixService extends BaseMatrixService {
|
|||
constructor(
|
||||
configService: ConfigService,
|
||||
private readonly transcriptionService: TranscriptionService,
|
||||
private ollamaService: OllamaService
|
||||
private ollamaService: OllamaService,
|
||||
private sessionService: SessionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
}
|
||||
|
|
@ -382,14 +387,23 @@ Schreibe einfach eine Nachricht und ich antworte!
|
|||
const connected = await this.ollamaService.checkConnection();
|
||||
const models = await this.ollamaService.listModels();
|
||||
const session = this.getSession(sender);
|
||||
const loggedIn = this.sessionService.isLoggedIn(sender);
|
||||
const authSession = this.sessionService.getSession(sender);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
|
||||
const statusText = `**Ollama Status**
|
||||
let statusText = `**Ollama Status**\n\n`;
|
||||
statusText += `**Verbindung:** ${connected ? 'Online' : 'Offline'}\n`;
|
||||
statusText += `**Modelle:** ${models.length}\n`;
|
||||
statusText += `**Dein Modell:** \`${session.model}\`\n`;
|
||||
statusText += `**Chat-Verlauf:** ${session.history.length} Nachrichten\n`;
|
||||
|
||||
**Verbindung:** ${connected ? 'Online' : 'Offline'}
|
||||
**Modelle:** ${models.length}
|
||||
**Dein Modell:** \`${session.model}\`
|
||||
**Chat-Verlauf:** ${session.history.length} Nachrichten
|
||||
**DSGVO:** Alle Daten lokal`;
|
||||
if (loggedIn && authSession && token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
statusText += `**👤 Angemeldet als:** ${authSession.email}\n`;
|
||||
statusText += `**⚡ Credits:** ${balance.balance.toFixed(2)}\n`;
|
||||
}
|
||||
|
||||
statusText += `**DSGVO:** Alle Daten lokal`;
|
||||
|
||||
await this.sendMessage(roomId, statusText);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { MatrixService } from './matrix.service';
|
||||
import { PictureModule } from '../picture/picture.module';
|
||||
import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
||||
import { SessionModule, TranscriptionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -10,6 +10,7 @@ import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
|||
TranscriptionModule.register({
|
||||
sttUrl: process.env.STT_URL || 'http://localhost:3020',
|
||||
}),
|
||||
CreditModule.forRoot(),
|
||||
],
|
||||
providers: [MatrixService],
|
||||
exports: [MatrixService],
|
||||
|
|
|
|||
|
|
@ -8,9 +8,12 @@ import {
|
|||
COMMON_KEYWORDS,
|
||||
} from '@manacore/matrix-bot-common';
|
||||
import { PictureService } from '../picture/picture.service';
|
||||
import { SessionService, TranscriptionService } from '@manacore/bot-services';
|
||||
import { SessionService, TranscriptionService, CreditService } from '@manacore/bot-services';
|
||||
import { HELP_MESSAGE } from '../config/configuration';
|
||||
|
||||
// Credit cost for image generation
|
||||
const IMAGE_GENERATION_CREDITS = 10;
|
||||
|
||||
interface ParsedPrompt {
|
||||
prompt: string;
|
||||
negativePrompt?: string;
|
||||
|
|
@ -38,7 +41,8 @@ export class MatrixService extends BaseMatrixService {
|
|||
configService: ConfigService,
|
||||
private readonly transcriptionService: TranscriptionService,
|
||||
private pictureService: PictureService,
|
||||
private sessionService: SessionService
|
||||
private sessionService: SessionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
}
|
||||
|
|
@ -239,6 +243,18 @@ Sag "hilfe" fur alle Befehle!`;
|
|||
return;
|
||||
}
|
||||
|
||||
// Validate credits before generating
|
||||
const validation = await this.creditService.validateCredits(token, IMAGE_GENERATION_CREDITS);
|
||||
if (!validation.hasCredits) {
|
||||
const errorMsg = this.creditService.formatInsufficientCreditsError(
|
||||
IMAGE_GENERATION_CREDITS,
|
||||
validation.availableCredits,
|
||||
'Bildgenerierung'
|
||||
);
|
||||
await this.sendMessage(roomId, errorMsg.text);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if user already has an active generation
|
||||
if (this.activeGenerations.has(sender)) {
|
||||
await this.sendMessage(
|
||||
|
|
@ -461,11 +477,17 @@ Sag "hilfe" fur alle Befehle!`;
|
|||
}
|
||||
|
||||
try {
|
||||
const balance = await this.pictureService.getCredits(token);
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`**Dein Credit-Guthaben:** ${balance} Credits\n\nEine Bildgenerierung kostet 10 Credits.`
|
||||
);
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
const creditIcon = balance.hasCredits ? '⚡' : '⚠️';
|
||||
let text = `${creditIcon} **Dein Credit-Guthaben:** ${balance.balance.toFixed(2)} Credits\n\n`;
|
||||
text += `Eine Bildgenerierung kostet **${IMAGE_GENERATION_CREDITS} Credits**.`;
|
||||
|
||||
if (balance.balance < IMAGE_GENERATION_CREDITS) {
|
||||
text += '\n\n⚠️ Nicht genug Credits fur eine Generierung!';
|
||||
text += '\n👉 Credits kaufen: https://mana.how/credits';
|
||||
}
|
||||
|
||||
await this.sendMessage(roomId, text);
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : 'Unbekannter Fehler';
|
||||
await this.sendMessage(roomId, `Fehler: ${errorMsg}`);
|
||||
|
|
@ -514,14 +536,30 @@ Sag "hilfe" fur alle Befehle!`;
|
|||
private async handleStatus(roomId: string, sender: string) {
|
||||
const backendHealthy = await this.pictureService.checkHealth();
|
||||
const isLoggedIn = this.sessionService.isLoggedIn(sender);
|
||||
const email = this.sessionService.getEmail(sender);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
const sessionCount = this.sessionService.getSessionCount();
|
||||
const currentModel = this.userModels.get(sender);
|
||||
const hasActiveGeneration = this.activeGenerations.has(sender);
|
||||
|
||||
// Get credit balance if logged in
|
||||
let creditInfo = '';
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
const creditIcon = balance.hasCredits ? '⚡' : '⚠️';
|
||||
creditInfo = `\n${creditIcon} **Credits:** ${balance.balance.toFixed(2)}`;
|
||||
if (balance.balance < IMAGE_GENERATION_CREDITS && balance.balance > 0) {
|
||||
creditInfo += '\n⚠️ Nicht genug Credits fur eine Generierung!';
|
||||
}
|
||||
if (!balance.hasCredits) {
|
||||
creditInfo += '\n👉 Credits kaufen: https://mana.how/credits';
|
||||
}
|
||||
}
|
||||
|
||||
const statusText = `**Picture Bot Status**
|
||||
|
||||
**Backend:** ${backendHealthy ? 'Online' : 'Offline'}
|
||||
**Dein Status:** ${isLoggedIn ? 'Angemeldet' : 'Nicht angemeldet'}
|
||||
**Dein Status:** ${isLoggedIn ? `Angemeldet (${email})` : 'Nicht angemeldet'}${creditInfo}
|
||||
**Ausgewahltes Modell:** ${currentModel || 'Standard'}
|
||||
**Aktive Generierung:** ${hasActiveGeneration ? 'Ja' : 'Nein'}
|
||||
**Aktive Sessions:** ${sessionCount}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { MatrixService } from './matrix.service';
|
||||
import { PlantaModule } from '../planta/planta.module';
|
||||
import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
||||
import { SessionModule, TranscriptionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -10,6 +10,7 @@ import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
|||
TranscriptionModule.register({
|
||||
sttUrl: process.env.STT_URL || 'http://localhost:3020',
|
||||
}),
|
||||
CreditModule.forRoot(),
|
||||
],
|
||||
providers: [MatrixService],
|
||||
exports: [MatrixService],
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
COMMON_KEYWORDS,
|
||||
} from '@manacore/matrix-bot-common';
|
||||
import { PlantaService, Plant } from '../planta/planta.service';
|
||||
import { SessionService, TranscriptionService } from '@manacore/bot-services';
|
||||
import { SessionService, TranscriptionService, CreditService } from '@manacore/bot-services';
|
||||
import { HELP_MESSAGE } from '../config/configuration';
|
||||
|
||||
@Injectable()
|
||||
|
|
@ -51,7 +51,8 @@ export class MatrixService extends BaseMatrixService {
|
|||
configService: ConfigService,
|
||||
private readonly transcriptionService: TranscriptionService,
|
||||
private plantaService: PlantaService,
|
||||
private sessionService: SessionService
|
||||
private sessionService: SessionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
}
|
||||
|
|
@ -211,9 +212,15 @@ export class MatrixService extends BaseMatrixService {
|
|||
const result = await this.sessionService.login(sender, email, password);
|
||||
|
||||
if (result.success) {
|
||||
await this.sendMessage(roomId, `<p>Erfolgreich angemeldet als <strong>${email}</strong></p>`);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
await this.sendMessage(roomId, `<p>✅ Erfolgreich angemeldet als <strong>${email}</strong><br/>⚡ Credits: ${balance.balance.toFixed(2)}</p>`);
|
||||
} else {
|
||||
await this.sendMessage(roomId, `<p>✅ Erfolgreich angemeldet als <strong>${email}</strong></p>`);
|
||||
}
|
||||
} else {
|
||||
await this.sendMessage(roomId, `<p>Login fehlgeschlagen: ${result.error}</p>`);
|
||||
await this.sendMessage(roomId, `<p>❌ Login fehlgeschlagen: ${result.error}</p>`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -221,16 +228,24 @@ export class MatrixService extends BaseMatrixService {
|
|||
const backendOk = await this.plantaService.checkHealth();
|
||||
const loggedIn = this.sessionService.isLoggedIn(sender);
|
||||
const sessions = this.sessionService.getSessionCount();
|
||||
const session = this.sessionService.getSession(sender);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`<h3>Planta Bot Status</h3>
|
||||
<ul>
|
||||
<li>Backend: ${backendOk ? 'Online' : 'Offline'}</li>
|
||||
<li>Angemeldet: ${loggedIn ? 'Ja' : 'Nein'}</li>
|
||||
<li>Aktive Sessions: ${sessions}</li>
|
||||
</ul>`
|
||||
);
|
||||
let statusHtml = `<h3>Planta Bot Status</h3><ul>`;
|
||||
statusHtml += `<li>Backend: ${backendOk ? '✅ Online' : '❌ Offline'}</li>`;
|
||||
statusHtml += `<li>Aktive Sessions: ${sessions}</li>`;
|
||||
|
||||
if (loggedIn && session && token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
statusHtml += `<li>👤 Angemeldet als: ${session.email}</li>`;
|
||||
statusHtml += `<li>⚡ Credits: ${balance.balance.toFixed(2)}</li>`;
|
||||
} else {
|
||||
statusHtml += `<li>👤 Nicht angemeldet</li>`;
|
||||
statusHtml += `<li>💡 Login: <code>!login email passwort</code></li>`;
|
||||
}
|
||||
statusHtml += `</ul>`;
|
||||
|
||||
await this.sendMessage(roomId, statusHtml);
|
||||
}
|
||||
|
||||
// Plant handlers
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { MatrixService } from './matrix.service';
|
||||
import { PresiModule } from '../presi/presi.module';
|
||||
import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
||||
import { SessionModule, TranscriptionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -10,6 +10,7 @@ import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
|||
TranscriptionModule.register({
|
||||
sttUrl: process.env.STT_URL || 'http://localhost:3020',
|
||||
}),
|
||||
CreditModule.forRoot(),
|
||||
],
|
||||
providers: [MatrixService],
|
||||
exports: [MatrixService],
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
COMMON_KEYWORDS,
|
||||
} from '@manacore/matrix-bot-common';
|
||||
import { PresiService, Deck, Theme, SlideContent } from '../presi/presi.service';
|
||||
import { SessionService, TranscriptionService } from '@manacore/bot-services';
|
||||
import { SessionService, TranscriptionService, CreditService } from '@manacore/bot-services';
|
||||
import { HELP_MESSAGE } from '../config/configuration';
|
||||
|
||||
@Injectable()
|
||||
|
|
@ -32,7 +32,8 @@ export class MatrixService extends BaseMatrixService {
|
|||
configService: ConfigService,
|
||||
private readonly transcriptionService: TranscriptionService,
|
||||
private presiService: PresiService,
|
||||
private sessionService: SessionService
|
||||
private sessionService: SessionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
}
|
||||
|
|
@ -204,7 +205,13 @@ export class MatrixService extends BaseMatrixService {
|
|||
const result = await this.sessionService.login(sender, email, password);
|
||||
|
||||
if (result.success) {
|
||||
await this.sendMessage(roomId, `<p>Erfolgreich angemeldet als <strong>${email}</strong></p>`);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
await this.sendMessage(roomId, `<p>✅ Erfolgreich angemeldet als <strong>${email}</strong><br/>⚡ Credits: ${balance.balance.toFixed(2)}</p>`);
|
||||
} else {
|
||||
await this.sendMessage(roomId, `<p>✅ Erfolgreich angemeldet als <strong>${email}</strong></p>`);
|
||||
}
|
||||
} else {
|
||||
await this.sendMessage(roomId, `<p>Login fehlgeschlagen: ${result.error}</p>`);
|
||||
}
|
||||
|
|
@ -214,16 +221,23 @@ export class MatrixService extends BaseMatrixService {
|
|||
const backendOk = await this.presiService.checkHealth();
|
||||
const loggedIn = this.sessionService.isLoggedIn(sender);
|
||||
const sessions = this.sessionService.getSessionCount();
|
||||
const session = this.sessionService.getSession(sender);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`<h3>Presi Bot Status</h3>
|
||||
<ul>
|
||||
<li>Backend: ${backendOk ? 'Online' : 'Offline'}</li>
|
||||
<li>Angemeldet: ${loggedIn ? 'Ja' : 'Nein'}</li>
|
||||
<li>Aktive Sessions: ${sessions}</li>
|
||||
</ul>`
|
||||
);
|
||||
let statusHtml = '<h3>Presi Bot Status</h3><ul>';
|
||||
statusHtml += `<li>Backend: ${backendOk ? 'Online' : 'Offline'}</li>`;
|
||||
statusHtml += `<li>Angemeldet: ${loggedIn ? 'Ja' : 'Nein'}</li>`;
|
||||
|
||||
if (loggedIn && session && token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
statusHtml += `<li>👤 Angemeldet als: ${session.email}</li>`;
|
||||
statusHtml += `<li>⚡ Credits: ${balance.balance.toFixed(2)}</li>`;
|
||||
}
|
||||
|
||||
statusHtml += `<li>Aktive Sessions: ${sessions}</li>`;
|
||||
statusHtml += '</ul>';
|
||||
|
||||
await this.sendMessage(roomId, statusHtml);
|
||||
}
|
||||
|
||||
// Deck handlers
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ import { MatrixService } from './matrix.service';
|
|||
import { ProjectModule } from '../project/project.module';
|
||||
import { MediaModule } from '../media/media.module';
|
||||
import { GenerationModule } from '../generation/generation.module';
|
||||
import { SessionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [ProjectModule, MediaModule, GenerationModule],
|
||||
imports: [ProjectModule, MediaModule, GenerationModule, SessionModule.forRoot(), CreditModule.forRoot()],
|
||||
providers: [MatrixService],
|
||||
exports: [MatrixService],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import {
|
|||
import { ProjectService } from '../project/project.service';
|
||||
import { MediaService } from '../media/media.service';
|
||||
import { GenerationService } from '../generation/generation.service';
|
||||
import { SessionService, CreditService } from '@manacore/bot-services';
|
||||
import { BLOG_STYLES } from '../config/configuration';
|
||||
|
||||
@Injectable()
|
||||
|
|
@ -34,7 +35,9 @@ export class MatrixService extends BaseMatrixService {
|
|||
configService: ConfigService,
|
||||
private projectService: ProjectService,
|
||||
private mediaService: MediaService,
|
||||
private generationService: GenerationService
|
||||
private generationService: GenerationService,
|
||||
private sessionService: SessionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
this.allowedUsers = this.configService.get<string[]>('matrix.allowedUsers') || [];
|
||||
|
|
@ -116,6 +119,16 @@ export class MatrixService extends BaseMatrixService {
|
|||
case 'start':
|
||||
await this.sendHelp(roomId);
|
||||
break;
|
||||
case 'login':
|
||||
await this.handleLogin(roomId, sender, argString);
|
||||
break;
|
||||
case 'logout':
|
||||
await this.handleLogout(roomId, sender);
|
||||
break;
|
||||
case 'auth':
|
||||
case 'account':
|
||||
await this.handleAuthStatus(roomId, sender);
|
||||
break;
|
||||
case 'new':
|
||||
await this.createProject(roomId, sender, argString);
|
||||
break;
|
||||
|
|
@ -154,6 +167,11 @@ export class MatrixService extends BaseMatrixService {
|
|||
|
||||
Sammle Fotos, Sprachnotizen und Text für deine Projekte und erstelle daraus Blogbeiträge.
|
||||
|
||||
**Account:**
|
||||
- \`!login email passwort\` - Anmelden
|
||||
- \`!logout\` - Abmelden
|
||||
- \`!auth\` - Account Status
|
||||
|
||||
**Projekt-Commands:**
|
||||
- \`!new [Name]\` - Neues Projekt starten
|
||||
- \`!projects\` - Alle Projekte anzeigen
|
||||
|
|
@ -180,6 +198,53 @@ ${styles}
|
|||
await this.sendMessage(roomId, helpText);
|
||||
}
|
||||
|
||||
private async handleLogin(roomId: string, sender: string, args: string) {
|
||||
const parts = args.split(' ');
|
||||
if (parts.length < 2 || !parts[0] || !parts[1]) {
|
||||
await this.sendMessage(roomId, 'Verwendung: `!login email passwort`');
|
||||
return;
|
||||
}
|
||||
const [email, password] = parts;
|
||||
const result = await this.sessionService.login(sender, email, password);
|
||||
|
||||
if (result.success) {
|
||||
const token = this.sessionService.getToken(sender);
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
await this.sendMessage(roomId,
|
||||
`✅ Erfolgreich angemeldet als **${email}**\n⚡ Credits: ${balance.balance.toFixed(2)}`);
|
||||
} else {
|
||||
await this.sendMessage(roomId, `✅ Erfolgreich angemeldet als **${email}**`);
|
||||
}
|
||||
} else {
|
||||
await this.sendMessage(roomId, `❌ Anmeldung fehlgeschlagen: ${result.error}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async handleLogout(roomId: string, sender: string) {
|
||||
this.sessionService.logout(sender);
|
||||
await this.sendMessage(roomId, '👋 Erfolgreich abgemeldet.');
|
||||
}
|
||||
|
||||
private async handleAuthStatus(roomId: string, sender: string) {
|
||||
const loggedIn = this.sessionService.isLoggedIn(sender);
|
||||
const session = this.sessionService.getSession(sender);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
|
||||
let response = '**📋 Account Status**\n\n';
|
||||
|
||||
if (loggedIn && session && token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
response += `👤 Angemeldet als: ${session.email}\n`;
|
||||
response += `⚡ Credits: ${balance.balance.toFixed(2)}`;
|
||||
} else {
|
||||
response += `❌ Nicht angemeldet\n`;
|
||||
response += `Nutze \`!login email passwort\` zum Anmelden.`;
|
||||
}
|
||||
|
||||
await this.sendMessage(roomId, response);
|
||||
}
|
||||
|
||||
private async createProject(roomId: string, sender: string, name: string) {
|
||||
if (!name) {
|
||||
await this.sendMessage(
|
||||
|
|
@ -262,23 +327,34 @@ ${styles}
|
|||
}
|
||||
|
||||
private async showStatus(roomId: string, sender: string) {
|
||||
// Auth info
|
||||
const loggedIn = this.sessionService.isLoggedIn(sender);
|
||||
const session = this.sessionService.getSession(sender);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
|
||||
let authInfo = '';
|
||||
if (loggedIn && session && token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
authInfo = `**👤 Account**\n${session.email} | ⚡ ${balance.balance.toFixed(2)} Credits\n\n`;
|
||||
}
|
||||
|
||||
const projectId = this.activeProjects.get(sender);
|
||||
if (!projectId) {
|
||||
await this.sendMessage(roomId, 'Kein aktives Projekt.\n\nStarte mit: `!new Projektname`');
|
||||
await this.sendMessage(roomId, `${authInfo}Kein aktives Projekt.\n\nStarte mit: \`!new Projektname\``);
|
||||
return;
|
||||
}
|
||||
|
||||
const project = await this.projectService.findById(projectId);
|
||||
if (!project) {
|
||||
this.activeProjects.delete(sender);
|
||||
await this.sendMessage(roomId, 'Projekt nicht gefunden. Starte ein neues mit `!new`');
|
||||
await this.sendMessage(roomId, `${authInfo}Projekt nicht gefunden. Starte ein neues mit \`!new\``);
|
||||
return;
|
||||
}
|
||||
|
||||
const stats = await this.projectService.getStats(projectId);
|
||||
const latest = await this.generationService.getLatestGeneration(projectId);
|
||||
|
||||
let statusText = `**Projekt-Status**\n\n**Name:** ${project.name}\n**Status:** ${project.status}\n**Erstellt:** ${project.createdAt.toLocaleDateString('de-DE')}\n\n**Inhalte:**\n${stats.photos} Fotos\n${stats.voices} Sprachnotizen\n${stats.texts} Textnotizen\n**Gesamt:** ${stats.total} Einträge`;
|
||||
let statusText = `${authInfo}**Projekt-Status**\n\n**Name:** ${project.name}\n**Status:** ${project.status}\n**Erstellt:** ${project.createdAt.toLocaleDateString('de-DE')}\n\n**Inhalte:**\n${stats.photos} Fotos\n${stats.voices} Sprachnotizen\n${stats.texts} Textnotizen\n**Gesamt:** ${stats.total} Einträge`;
|
||||
|
||||
if (latest) {
|
||||
statusText += `\n\n**Letzte Generierung:**\n${latest.createdAt.toLocaleString('de-DE')} (${latest.style})`;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { MatrixService } from './matrix.service';
|
||||
import { QuestionsModule } from '../questions/questions.module';
|
||||
import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
||||
import { SessionModule, TranscriptionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -10,6 +10,7 @@ import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
|||
TranscriptionModule.register({
|
||||
sttUrl: process.env.STT_URL || 'http://localhost:3020',
|
||||
}),
|
||||
CreditModule.forRoot(),
|
||||
],
|
||||
providers: [MatrixService],
|
||||
exports: [MatrixService],
|
||||
|
|
|
|||
|
|
@ -9,9 +9,14 @@ import {
|
|||
COMMON_KEYWORDS,
|
||||
} from '@manacore/matrix-bot-common';
|
||||
import { QuestionsService, Question, Collection, Answer } from '../questions/questions.service';
|
||||
import { SessionService, TranscriptionService } from '@manacore/bot-services';
|
||||
import { SessionService, TranscriptionService, CreditService } from '@manacore/bot-services';
|
||||
import { HELP_MESSAGE } from '../config/configuration';
|
||||
|
||||
const QUESTION_CREATE_CREDITS = 0.02;
|
||||
const QUICK_RESEARCH_CREDITS = 5;
|
||||
const STANDARD_RESEARCH_CREDITS = 10;
|
||||
const DEEP_RESEARCH_CREDITS = 25;
|
||||
|
||||
@Injectable()
|
||||
export class MatrixService extends BaseMatrixService {
|
||||
// Store last shown items per user for reference by number
|
||||
|
|
@ -34,7 +39,8 @@ export class MatrixService extends BaseMatrixService {
|
|||
configService: ConfigService,
|
||||
private questionsService: QuestionsService,
|
||||
private sessionService: SessionService,
|
||||
private readonly transcriptionService: TranscriptionService
|
||||
private readonly transcriptionService: TranscriptionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
}
|
||||
|
|
@ -220,9 +226,15 @@ export class MatrixService extends BaseMatrixService {
|
|||
const result = await this.sessionService.login(sender, email, password);
|
||||
|
||||
if (result.success) {
|
||||
await this.sendMessage(roomId, `<p>Erfolgreich angemeldet als <strong>${email}</strong></p>`);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
await this.sendMessage(roomId, `<p>✅ Erfolgreich angemeldet als <strong>${email}</strong><br/>⚡ Credits: ${balance.balance.toFixed(2)}</p>`);
|
||||
} else {
|
||||
await this.sendMessage(roomId, `<p>✅ Erfolgreich angemeldet als <strong>${email}</strong></p>`);
|
||||
}
|
||||
} else {
|
||||
await this.sendMessage(roomId, `<p>Login fehlgeschlagen: ${result.error}</p>`);
|
||||
await this.sendMessage(roomId, `<p>❌ Login fehlgeschlagen: ${result.error}</p>`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -230,16 +242,24 @@ export class MatrixService extends BaseMatrixService {
|
|||
const backendOk = await this.questionsService.checkHealth();
|
||||
const loggedIn = this.sessionService.isLoggedIn(sender);
|
||||
const sessions = this.sessionService.getSessionCount();
|
||||
const session = this.sessionService.getSession(sender);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`<h3>Questions Bot Status</h3>
|
||||
<ul>
|
||||
<li>Backend: ${backendOk ? 'Online' : 'Offline'}</li>
|
||||
<li>Angemeldet: ${loggedIn ? 'Ja' : 'Nein'}</li>
|
||||
<li>Aktive Sessions: ${sessions}</li>
|
||||
</ul>`
|
||||
);
|
||||
let statusHtml = `<h3>Questions Bot Status</h3><ul>`;
|
||||
statusHtml += `<li>Backend: ${backendOk ? '✅ Online' : '❌ Offline'}</li>`;
|
||||
statusHtml += `<li>Aktive Sessions: ${sessions}</li>`;
|
||||
|
||||
if (loggedIn && session && token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
statusHtml += `<li>👤 Angemeldet als: ${session.email}</li>`;
|
||||
statusHtml += `<li>⚡ Credits: ${balance.balance.toFixed(2)}</li>`;
|
||||
} else {
|
||||
statusHtml += `<li>👤 Nicht angemeldet</li>`;
|
||||
statusHtml += `<li>💡 Login: <code>!login email passwort</code></li>`;
|
||||
}
|
||||
statusHtml += `</ul>`;
|
||||
|
||||
await this.sendMessage(roomId, statusHtml);
|
||||
}
|
||||
|
||||
// Question handlers
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { MatrixService } from './matrix.service';
|
||||
import { SkilltreeModule } from '../skilltree/skilltree.module';
|
||||
import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
||||
import { SessionModule, TranscriptionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -10,6 +10,7 @@ import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
|||
TranscriptionModule.register({
|
||||
sttUrl: process.env.STT_URL || 'http://localhost:3020',
|
||||
}),
|
||||
CreditModule.forRoot(),
|
||||
],
|
||||
providers: [MatrixService],
|
||||
exports: [MatrixService],
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
COMMON_KEYWORDS,
|
||||
} from '@manacore/matrix-bot-common';
|
||||
import { SkilltreeService, Skill, SkillBranch } from '../skilltree/skilltree.service';
|
||||
import { SessionService, TranscriptionService } from '@manacore/bot-services';
|
||||
import { SessionService, TranscriptionService, CreditService } from '@manacore/bot-services';
|
||||
import { HELP_MESSAGE } from '../config/configuration';
|
||||
|
||||
@Injectable()
|
||||
|
|
@ -55,7 +55,8 @@ export class MatrixService extends BaseMatrixService {
|
|||
configService: ConfigService,
|
||||
private skilltreeService: SkilltreeService,
|
||||
private sessionService: SessionService,
|
||||
private readonly transcriptionService: TranscriptionService
|
||||
private readonly transcriptionService: TranscriptionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
}
|
||||
|
|
@ -207,7 +208,13 @@ export class MatrixService extends BaseMatrixService {
|
|||
const result = await this.sessionService.login(sender, email, password);
|
||||
|
||||
if (result.success) {
|
||||
await this.sendMessage(roomId, `<p>Erfolgreich angemeldet als <strong>${email}</strong></p>`);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
await this.sendMessage(roomId, `<p>✅ Erfolgreich angemeldet als <strong>${email}</strong><br/>⚡ Credits: ${balance.balance.toFixed(2)}</p>`);
|
||||
} else {
|
||||
await this.sendMessage(roomId, `<p>✅ Erfolgreich angemeldet als <strong>${email}</strong></p>`);
|
||||
}
|
||||
} else {
|
||||
await this.sendMessage(roomId, `<p>Login fehlgeschlagen: ${result.error}</p>`);
|
||||
}
|
||||
|
|
@ -217,16 +224,23 @@ export class MatrixService extends BaseMatrixService {
|
|||
const backendOk = await this.skilltreeService.checkHealth();
|
||||
const loggedIn = this.sessionService.isLoggedIn(sender);
|
||||
const sessions = this.sessionService.getSessionCount();
|
||||
const session = this.sessionService.getSession(sender);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`<h3>Skilltree Bot Status</h3>
|
||||
<ul>
|
||||
<li>Backend: ${backendOk ? 'Online' : 'Offline'}</li>
|
||||
<li>Angemeldet: ${loggedIn ? 'Ja' : 'Nein'}</li>
|
||||
<li>Aktive Sessions: ${sessions}</li>
|
||||
</ul>`
|
||||
);
|
||||
let statusHtml = '<h3>Skilltree Bot Status</h3><ul>';
|
||||
statusHtml += `<li>Backend: ${backendOk ? 'Online' : 'Offline'}</li>`;
|
||||
statusHtml += `<li>Angemeldet: ${loggedIn ? 'Ja' : 'Nein'}</li>`;
|
||||
|
||||
if (loggedIn && session && token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
statusHtml += `<li>👤 Angemeldet als: ${session.email}</li>`;
|
||||
statusHtml += `<li>⚡ Credits: ${balance.balance.toFixed(2)}</li>`;
|
||||
}
|
||||
|
||||
statusHtml += `<li>Aktive Sessions: ${sessions}</li>`;
|
||||
statusHtml += '</ul>';
|
||||
|
||||
await this.sendMessage(roomId, statusHtml);
|
||||
}
|
||||
|
||||
// Skill handlers
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { Module } from '@nestjs/common';
|
|||
import { MatrixService } from './matrix.service';
|
||||
import { AnalyticsModule } from '../analytics/analytics.module';
|
||||
import { UsersModule } from '../users/users.module';
|
||||
import { TranscriptionModule } from '@manacore/bot-services';
|
||||
import { TranscriptionModule, SessionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -11,6 +11,8 @@ import { TranscriptionModule } from '@manacore/bot-services';
|
|||
TranscriptionModule.register({
|
||||
sttUrl: process.env.STT_URL || 'http://localhost:3020',
|
||||
}),
|
||||
SessionModule.forRoot(),
|
||||
CreditModule.forRoot(),
|
||||
],
|
||||
providers: [MatrixService],
|
||||
exports: [MatrixService],
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
} from '@manacore/matrix-bot-common';
|
||||
import { AnalyticsService } from '../analytics/analytics.service';
|
||||
import { UsersService } from '../users/users.service';
|
||||
import { TranscriptionService } from '@manacore/bot-services';
|
||||
import { TranscriptionService, SessionService, CreditService } from '@manacore/bot-services';
|
||||
|
||||
@Injectable()
|
||||
export class MatrixService extends BaseMatrixService {
|
||||
|
|
@ -28,7 +28,9 @@ export class MatrixService extends BaseMatrixService {
|
|||
configService: ConfigService,
|
||||
private analyticsService: AnalyticsService,
|
||||
private usersService: UsersService,
|
||||
private readonly transcriptionService: TranscriptionService
|
||||
private readonly transcriptionService: TranscriptionService,
|
||||
private sessionService: SessionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
this.reportRoomId = this.configService.get<string>('matrix.reportRoomId') || '';
|
||||
|
|
@ -48,7 +50,7 @@ export class MatrixService extends BaseMatrixService {
|
|||
roomId: string,
|
||||
_event: MatrixRoomEvent,
|
||||
message: string,
|
||||
_sender: string
|
||||
sender: string
|
||||
): Promise<void> {
|
||||
// Check for keyword commands first
|
||||
const keywordCommand = this.keywordDetector.detect(message);
|
||||
|
|
@ -58,8 +60,8 @@ export class MatrixService extends BaseMatrixService {
|
|||
|
||||
if (!message.startsWith('!')) return;
|
||||
|
||||
const [command] = message.slice(1).split(' ');
|
||||
await this.handleCommand(roomId, command.toLowerCase());
|
||||
const [command, ...args] = message.slice(1).split(' ');
|
||||
await this.handleCommand(roomId, command.toLowerCase(), sender, args.join(' '));
|
||||
}
|
||||
|
||||
protected override async handleAudioMessage(
|
||||
|
|
@ -86,13 +88,25 @@ export class MatrixService extends BaseMatrixService {
|
|||
}
|
||||
}
|
||||
|
||||
private async handleCommand(roomId: string, command: string) {
|
||||
private async handleCommand(roomId: string, command: string, sender: string, args: string) {
|
||||
switch (command) {
|
||||
case 'help':
|
||||
case 'start':
|
||||
await this.sendHelp(roomId);
|
||||
break;
|
||||
|
||||
case 'login':
|
||||
await this.handleLogin(roomId, sender, args);
|
||||
break;
|
||||
|
||||
case 'logout':
|
||||
await this.handleLogout(roomId, sender);
|
||||
break;
|
||||
|
||||
case 'status':
|
||||
await this.handleStatus(roomId, sender);
|
||||
break;
|
||||
|
||||
case 'stats':
|
||||
await this.sendStats(roomId);
|
||||
break;
|
||||
|
|
@ -121,7 +135,12 @@ export class MatrixService extends BaseMatrixService {
|
|||
private async sendHelp(roomId: string) {
|
||||
const helpText = `**📊 ManaCore Stats Bot (DSGVO-konform)**
|
||||
|
||||
**Befehle:**
|
||||
**Account:**
|
||||
- \`!login email passwort\` - Anmelden
|
||||
- \`!logout\` - Abmelden
|
||||
- \`!status\` - Account Status
|
||||
|
||||
**Statistiken:**
|
||||
- \`!stats\` - Übersicht aller Apps (30 Tage)
|
||||
- \`!today\` - Heutige Statistiken
|
||||
- \`!week\` - Wochenstatistiken
|
||||
|
|
@ -177,6 +196,53 @@ Daten von Umami Analytics (self-hosted).`;
|
|||
await this.sendMessage(roomId, report);
|
||||
}
|
||||
|
||||
private async handleLogin(roomId: string, sender: string, args: string) {
|
||||
const parts = args.split(' ');
|
||||
if (parts.length < 2 || !parts[0] || !parts[1]) {
|
||||
await this.sendMessage(roomId, 'Verwendung: `!login email passwort`');
|
||||
return;
|
||||
}
|
||||
const [email, password] = parts;
|
||||
const result = await this.sessionService.login(sender, email, password);
|
||||
|
||||
if (result.success) {
|
||||
const token = this.sessionService.getToken(sender);
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
await this.sendMessage(roomId,
|
||||
`✅ Erfolgreich angemeldet als **${email}**\n⚡ Credits: ${balance.balance.toFixed(2)}`);
|
||||
} else {
|
||||
await this.sendMessage(roomId, `✅ Erfolgreich angemeldet als **${email}**`);
|
||||
}
|
||||
} else {
|
||||
await this.sendMessage(roomId, `❌ Anmeldung fehlgeschlagen: ${result.error}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async handleLogout(roomId: string, sender: string) {
|
||||
this.sessionService.logout(sender);
|
||||
await this.sendMessage(roomId, '👋 Erfolgreich abgemeldet.');
|
||||
}
|
||||
|
||||
private async handleStatus(roomId: string, sender: string) {
|
||||
const loggedIn = this.sessionService.isLoggedIn(sender);
|
||||
const session = this.sessionService.getSession(sender);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
|
||||
let response = '**📊 Stats Bot Status**\n\n';
|
||||
|
||||
if (loggedIn && session && token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
response += `👤 Angemeldet als: ${session.email}\n`;
|
||||
response += `⚡ Credits: ${balance.balance.toFixed(2)}\n`;
|
||||
} else {
|
||||
response += `❌ Nicht angemeldet\n`;
|
||||
response += `Nutze \`!login email passwort\` zum Anmelden.`;
|
||||
}
|
||||
|
||||
await this.sendMessage(roomId, response);
|
||||
}
|
||||
|
||||
// Public method for scheduled reports
|
||||
async sendScheduledReport(report: string) {
|
||||
if (!this.reportRoomId) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { MatrixService } from './matrix.service';
|
||||
import { StorageModule } from '../storage/storage.module';
|
||||
import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
||||
import { SessionModule, TranscriptionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -10,6 +10,7 @@ import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
|||
TranscriptionModule.register({
|
||||
sttUrl: process.env.STT_URL || 'http://localhost:3020',
|
||||
}),
|
||||
CreditModule.forRoot(),
|
||||
],
|
||||
providers: [MatrixService],
|
||||
exports: [MatrixService],
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
COMMON_KEYWORDS,
|
||||
} from '@manacore/matrix-bot-common';
|
||||
import { StorageService, StorageFile, Folder, ShareLink, TrashItem } from '../storage/storage.service';
|
||||
import { SessionService, TranscriptionService } from '@manacore/bot-services';
|
||||
import { SessionService, TranscriptionService, CreditService } from '@manacore/bot-services';
|
||||
import { HELP_MESSAGE } from '../config/configuration';
|
||||
|
||||
@Injectable()
|
||||
|
|
@ -36,7 +36,8 @@ export class MatrixService extends BaseMatrixService {
|
|||
configService: ConfigService,
|
||||
private storageService: StorageService,
|
||||
private sessionService: SessionService,
|
||||
private readonly transcriptionService: TranscriptionService
|
||||
private readonly transcriptionService: TranscriptionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
}
|
||||
|
|
@ -247,7 +248,13 @@ export class MatrixService extends BaseMatrixService {
|
|||
const result = await this.sessionService.login(sender, email, password);
|
||||
|
||||
if (result.success) {
|
||||
await this.sendMessage(roomId, `<p>Erfolgreich angemeldet als <strong>${email}</strong></p>`);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
await this.sendMessage(roomId, `<p>✅ Erfolgreich angemeldet als <strong>${email}</strong><br/>⚡ Credits: ${balance.balance.toFixed(2)}</p>`);
|
||||
} else {
|
||||
await this.sendMessage(roomId, `<p>✅ Erfolgreich angemeldet als <strong>${email}</strong></p>`);
|
||||
}
|
||||
} else {
|
||||
await this.sendMessage(roomId, `<p>Login fehlgeschlagen: ${result.error}</p>`);
|
||||
}
|
||||
|
|
@ -257,16 +264,23 @@ export class MatrixService extends BaseMatrixService {
|
|||
const backendOk = await this.storageService.checkHealth();
|
||||
const loggedIn = this.sessionService.isLoggedIn(sender);
|
||||
const sessions = this.sessionService.getSessionCount();
|
||||
const session = this.sessionService.getSession(sender);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`<h3>Storage Bot Status</h3>
|
||||
<ul>
|
||||
<li>Backend: ${backendOk ? 'Online' : 'Offline'}</li>
|
||||
<li>Angemeldet: ${loggedIn ? 'Ja' : 'Nein'}</li>
|
||||
<li>Aktive Sessions: ${sessions}</li>
|
||||
</ul>`
|
||||
);
|
||||
let statusHtml = '<h3>Storage Bot Status</h3><ul>';
|
||||
statusHtml += `<li>Backend: ${backendOk ? 'Online' : 'Offline'}</li>`;
|
||||
statusHtml += `<li>Angemeldet: ${loggedIn ? 'Ja' : 'Nein'}</li>`;
|
||||
|
||||
if (loggedIn && session && token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
statusHtml += `<li>👤 Angemeldet als: ${session.email}</li>`;
|
||||
statusHtml += `<li>⚡ Credits: ${balance.balance.toFixed(2)}</li>`;
|
||||
}
|
||||
|
||||
statusHtml += `<li>Aktive Sessions: ${sessions}</li>`;
|
||||
statusHtml += '</ul>';
|
||||
|
||||
await this.sendMessage(roomId, statusHtml);
|
||||
}
|
||||
|
||||
// File handlers
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { MatrixService } from './matrix.service';
|
||||
import { TodoModule } from '../todo/todo.module';
|
||||
import { TranscriptionModule } from '@manacore/bot-services';
|
||||
import { TranscriptionModule, SessionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [TodoModule, TranscriptionModule.forRoot()],
|
||||
imports: [
|
||||
TodoModule,
|
||||
TranscriptionModule.forRoot(),
|
||||
SessionModule.forRoot(),
|
||||
CreditModule.forRoot(),
|
||||
],
|
||||
providers: [MatrixService],
|
||||
exports: [MatrixService],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -8,9 +8,12 @@ import {
|
|||
COMMON_KEYWORDS,
|
||||
} from '@manacore/matrix-bot-common';
|
||||
import { TodoService, Task } from '../todo/todo.service';
|
||||
import { TranscriptionService } from '@manacore/bot-services';
|
||||
import { TranscriptionService, SessionService, CreditService } from '@manacore/bot-services';
|
||||
import { HELP_TEXT, WELCOME_TEXT, BOT_INTRODUCTION } from '../config/configuration';
|
||||
|
||||
// Credit cost for task creation (micro-credits)
|
||||
const TASK_CREATE_CREDITS = 0.02;
|
||||
|
||||
@Injectable()
|
||||
export class MatrixService extends BaseMatrixService {
|
||||
private readonly keywordDetector = new KeywordCommandDetector(
|
||||
|
|
@ -29,7 +32,9 @@ export class MatrixService extends BaseMatrixService {
|
|||
constructor(
|
||||
configService: ConfigService,
|
||||
private todoService: TodoService,
|
||||
private transcriptionService: TranscriptionService
|
||||
private transcriptionService: TranscriptionService,
|
||||
private sessionService: SessionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
}
|
||||
|
|
@ -113,6 +118,21 @@ export class MatrixService extends BaseMatrixService {
|
|||
return;
|
||||
}
|
||||
|
||||
// Check credits if user is logged in
|
||||
const token = this.sessionService.getToken(sender);
|
||||
if (token) {
|
||||
const validation = await this.creditService.validateCredits(token, TASK_CREATE_CREDITS);
|
||||
if (!validation.hasCredits) {
|
||||
const errorMsg = this.creditService.formatInsufficientCreditsError(
|
||||
TASK_CREATE_CREDITS,
|
||||
validation.availableCredits,
|
||||
'Aufgabe erstellen'
|
||||
);
|
||||
await this.sendReply(roomId, event, `Transkription: "${transcription}"\n\n${errorMsg.text}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the transcription as a task input
|
||||
const { title, priority, dueDate, project } = this.todoService.parseTaskInput(transcription);
|
||||
|
||||
|
|
@ -134,6 +154,12 @@ export class MatrixService extends BaseMatrixService {
|
|||
responseText += `\n${details.join(' | ')}`;
|
||||
}
|
||||
|
||||
// Show credit deduction if logged in
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
responseText += `\n\n⚡ -${TASK_CREATE_CREDITS} Credits (${balance.balance.toFixed(2)} verbleibend)`;
|
||||
}
|
||||
|
||||
await this.sendReply(roomId, event, responseText);
|
||||
} catch (error) {
|
||||
this.logger.error('Audio processing failed:', error);
|
||||
|
|
@ -155,6 +181,14 @@ export class MatrixService extends BaseMatrixService {
|
|||
await this.sendReply(roomId, event, HELP_TEXT);
|
||||
break;
|
||||
|
||||
case 'login':
|
||||
await this.handleLogin(roomId, event, userId, args);
|
||||
break;
|
||||
|
||||
case 'logout':
|
||||
await this.handleLogout(roomId, event, userId);
|
||||
break;
|
||||
|
||||
case 'add':
|
||||
case 'neu':
|
||||
case 'neue':
|
||||
|
|
@ -223,6 +257,21 @@ export class MatrixService extends BaseMatrixService {
|
|||
return;
|
||||
}
|
||||
|
||||
// Check credits if user is logged in
|
||||
const token = this.sessionService.getToken(userId);
|
||||
if (token) {
|
||||
const validation = await this.creditService.validateCredits(token, TASK_CREATE_CREDITS);
|
||||
if (!validation.hasCredits) {
|
||||
const errorMsg = this.creditService.formatInsufficientCreditsError(
|
||||
TASK_CREATE_CREDITS,
|
||||
validation.availableCredits,
|
||||
'Aufgabe erstellen'
|
||||
);
|
||||
await this.sendReply(roomId, event, errorMsg.text);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const { title, priority, dueDate, project } = this.todoService.parseTaskInput(input);
|
||||
|
||||
const task = await this.todoService.createTask(userId, title, {
|
||||
|
|
@ -242,6 +291,12 @@ export class MatrixService extends BaseMatrixService {
|
|||
response += `\n${details.join(' | ')}`;
|
||||
}
|
||||
|
||||
// Show credit deduction if logged in
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
response += `\n\n⚡ -${TASK_CREATE_CREDITS} Credits (${balance.balance.toFixed(2)} verbleibend)`;
|
||||
}
|
||||
|
||||
await this.sendReply(roomId, event, response);
|
||||
}
|
||||
|
||||
|
|
@ -379,19 +434,60 @@ export class MatrixService extends BaseMatrixService {
|
|||
|
||||
private async handleStatus(roomId: string, event: MatrixRoomEvent, userId: string) {
|
||||
const stats = await this.todoService.getStats(userId);
|
||||
const isLoggedIn = this.sessionService.isLoggedIn(userId);
|
||||
const email = this.sessionService.getEmail(userId);
|
||||
const token = this.sessionService.getToken(userId);
|
||||
|
||||
// Get credit balance if logged in
|
||||
let creditInfo = '';
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
const creditIcon = balance.hasCredits ? '⚡' : '⚠️';
|
||||
creditInfo = `\n${creditIcon} Credits: ${balance.balance.toFixed(2)}`;
|
||||
if (balance.balance < 10 && balance.balance > 0) {
|
||||
creditInfo += '\n⚠️ Nur noch wenig Credits!';
|
||||
}
|
||||
if (!balance.hasCredits) {
|
||||
creditInfo += '\n👉 Credits kaufen: https://mana.how/credits';
|
||||
}
|
||||
}
|
||||
|
||||
const response = `**Status**
|
||||
|
||||
👤 Angemeldet: ${isLoggedIn ? `Ja (${email})` : 'Nein'}${creditInfo}
|
||||
|
||||
- Offene Aufgaben: ${stats.pending}
|
||||
- Heute faellig: ${stats.today}
|
||||
- Erledigt: ${stats.completed}
|
||||
- Gesamt: ${stats.total}
|
||||
|
||||
Bot: Online`;
|
||||
Bot: Online${!isLoggedIn ? '\n\nTipp: Mit `!login email passwort` anmelden fuer Credit-Tracking' : ''}`;
|
||||
|
||||
await this.sendReply(roomId, event, response);
|
||||
}
|
||||
|
||||
private async handleLogin(roomId: string, event: MatrixRoomEvent, userId: string, args: string) {
|
||||
const parts = args.trim().split(/\s+/);
|
||||
if (parts.length < 2) {
|
||||
await this.sendReply(roomId, event, 'Verwendung: `!login email passwort`');
|
||||
return;
|
||||
}
|
||||
|
||||
const [email, password] = parts;
|
||||
const result = await this.sessionService.login(userId, email, password);
|
||||
|
||||
if (result.success) {
|
||||
await this.sendReply(roomId, event, `Erfolgreich angemeldet als **${email}**`);
|
||||
} else {
|
||||
await this.sendReply(roomId, event, `Anmeldung fehlgeschlagen: ${result.error}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async handleLogout(roomId: string, event: MatrixRoomEvent, userId: string) {
|
||||
this.sessionService.logout(userId);
|
||||
await this.sendReply(roomId, event, 'Erfolgreich abgemeldet.');
|
||||
}
|
||||
|
||||
private async handlePinHelp(roomId: string, event: MatrixRoomEvent) {
|
||||
try {
|
||||
// Send help message
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { MatrixService } from './matrix.service';
|
||||
import { TtsModule } from '../tts/tts.module';
|
||||
import { TranscriptionModule } from '@manacore/bot-services';
|
||||
import { TranscriptionModule, SessionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -9,6 +9,8 @@ import { TranscriptionModule } from '@manacore/bot-services';
|
|||
TranscriptionModule.register({
|
||||
sttUrl: process.env.STT_URL || 'http://localhost:3020',
|
||||
}),
|
||||
SessionModule.forRoot(),
|
||||
CreditModule.forRoot(),
|
||||
],
|
||||
providers: [MatrixService],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
COMMON_KEYWORDS,
|
||||
} from '@manacore/matrix-bot-common';
|
||||
import { TtsService } from '../tts/tts.service';
|
||||
import { TranscriptionService } from '@manacore/bot-services';
|
||||
import { TranscriptionService, SessionService, CreditService } from '@manacore/bot-services';
|
||||
import { HELP_TEXT, WELCOME_TEXT } from '../config/configuration';
|
||||
|
||||
interface UserSettings {
|
||||
|
|
@ -38,7 +38,9 @@ export class MatrixService extends BaseMatrixService {
|
|||
constructor(
|
||||
configService: ConfigService,
|
||||
private ttsService: TtsService,
|
||||
private readonly transcriptionService: TranscriptionService
|
||||
private readonly transcriptionService: TranscriptionService,
|
||||
private sessionService: SessionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
this.defaultVoice = this.configService.get<string>('tts.defaultVoice') || 'af_heart';
|
||||
|
|
@ -277,12 +279,21 @@ export class MatrixService extends BaseMatrixService {
|
|||
private async handleStatusCommand(roomId: string, event: MatrixRoomEvent, userId: string) {
|
||||
const settings = this.getUserSettings(userId);
|
||||
const ttsHealthy = await this.ttsService.isHealthy();
|
||||
const loggedIn = this.sessionService.isLoggedIn(userId);
|
||||
const session = this.sessionService.getSession(userId);
|
||||
const token = this.sessionService.getToken(userId);
|
||||
|
||||
let response = '**Aktuelle Einstellungen:**\n\n';
|
||||
response += `Stimme: \`${settings.voice}\`\n`;
|
||||
response += `Geschwindigkeit: ${settings.speed}x\n`;
|
||||
response += `Max. Textlaenge: ${this.maxTextLength} Zeichen\n\n`;
|
||||
response += `TTS-Service: ${ttsHealthy ? 'Online' : 'Offline'}`;
|
||||
response += `TTS-Service: ${ttsHealthy ? 'Online' : 'Offline'}\n`;
|
||||
|
||||
if (loggedIn && session && token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
response += `\n👤 Angemeldet als: ${session.email}\n`;
|
||||
response += `⚡ Credits: ${balance.balance.toFixed(2)}`;
|
||||
}
|
||||
|
||||
await this.sendReply(roomId, event, response);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { MatrixService } from './matrix.service';
|
||||
import { QuotesModule } from '../quotes/quotes.module';
|
||||
import { SessionModule, TranscriptionModule } from '@manacore/bot-services';
|
||||
import { SessionModule, TranscriptionModule, CreditModule } from '@manacore/bot-services';
|
||||
|
||||
@Module({
|
||||
imports: [QuotesModule, SessionModule.forRoot(), TranscriptionModule.forRoot()],
|
||||
imports: [QuotesModule, SessionModule.forRoot(), TranscriptionModule.forRoot(), CreditModule.forRoot()],
|
||||
providers: [MatrixService],
|
||||
exports: [MatrixService],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
} from '@manacore/matrix-bot-common';
|
||||
import { QuotesService } from '../quotes/quotes.service';
|
||||
import { ZitareService } from '../quotes/zitare.service';
|
||||
import { SessionService, TranscriptionService } from '@manacore/bot-services';
|
||||
import { SessionService, TranscriptionService, CreditService } from '@manacore/bot-services';
|
||||
import { HELP_MESSAGE, Category } from '../config/configuration';
|
||||
|
||||
@Injectable()
|
||||
|
|
@ -33,7 +33,8 @@ export class MatrixService extends BaseMatrixService {
|
|||
private quotesService: QuotesService,
|
||||
private zitareService: ZitareService,
|
||||
private sessionService: SessionService,
|
||||
private transcriptionService: TranscriptionService
|
||||
private transcriptionService: TranscriptionService,
|
||||
private creditService: CreditService
|
||||
) {
|
||||
super(configService);
|
||||
}
|
||||
|
|
@ -361,10 +362,19 @@ Sag "hilfe" fuer alle Befehle!`;
|
|||
const result = await this.sessionService.login(sender, email, password);
|
||||
|
||||
if (result.success) {
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`Erfolgreich angemeldet!\n\nDu kannst jetzt Favoriten speichern und Listen verwalten.`
|
||||
);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
if (token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`✅ Erfolgreich angemeldet!\n⚡ Credits: ${balance.balance.toFixed(2)}\n\nDu kannst jetzt Favoriten speichern und Listen verwalten.`
|
||||
);
|
||||
} else {
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`Erfolgreich angemeldet!\n\nDu kannst jetzt Favoriten speichern und Listen verwalten.`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
await this.sendMessage(roomId, `Anmeldung fehlgeschlagen: ${result.error}`);
|
||||
}
|
||||
|
|
@ -556,15 +566,22 @@ Sag "hilfe" fuer alle Befehle!`;
|
|||
const isLoggedIn = this.sessionService.isLoggedIn(sender);
|
||||
const sessionCount = this.sessionService.getSessionCount();
|
||||
const totalQuotes = this.quotesService.getTotalCount();
|
||||
const session = this.sessionService.getSession(sender);
|
||||
const token = this.sessionService.getToken(sender);
|
||||
|
||||
const statusText = `**Zitare Bot Status**
|
||||
let statusText = `**Zitare Bot Status**\n\n`;
|
||||
statusText += `**Backend:** ${backendHealthy ? 'Online' : 'Offline'}\n`;
|
||||
statusText += `**Dein Status:** ${isLoggedIn ? 'Angemeldet' : 'Nicht angemeldet'}\n`;
|
||||
|
||||
**Backend:** ${backendHealthy ? 'Online' : 'Offline'}
|
||||
**Dein Status:** ${isLoggedIn ? 'Angemeldet' : 'Nicht angemeldet'}
|
||||
**Aktive Sessions:** ${sessionCount}
|
||||
**Verfuegbare Zitate:** ${totalQuotes}
|
||||
if (isLoggedIn && session && token) {
|
||||
const balance = await this.creditService.getBalance(token);
|
||||
statusText += `**👤 Angemeldet als:** ${session.email}\n`;
|
||||
statusText += `**⚡ Credits:** ${balance.balance.toFixed(2)}\n`;
|
||||
}
|
||||
|
||||
${!isLoggedIn ? 'Nutze `!login email passwort` um dich anzumelden.' : ''}`;
|
||||
statusText += `**Aktive Sessions:** ${sessionCount}\n`;
|
||||
statusText += `**Verfuegbare Zitate:** ${totalQuotes}\n`;
|
||||
statusText += `\n${!isLoggedIn ? 'Nutze `!login email passwort` um dich anzumelden.' : ''}`;
|
||||
|
||||
await this.sendMessage(roomId, statusText);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue