mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 22:01:09 +02:00
fix(matrix-bots): update to matrix-bot-sdk v0.7 API
- Import LogLevel separately instead of LogService.LogLevel - Change sendTyping to setTyping - Use any type for event handler to avoid generic type issues - Fix Buffer to Uint8Array conversion for OpenAI File API Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
9dfad0128a
commit
b50376dfdb
4 changed files with 94 additions and 49 deletions
|
|
@ -6,8 +6,7 @@ import {
|
|||
AutojoinRoomsMixin,
|
||||
RichConsoleLogger,
|
||||
LogService,
|
||||
MessageEvent,
|
||||
RoomEvent,
|
||||
LogLevel,
|
||||
} from 'matrix-bot-sdk';
|
||||
import { OllamaService } from '../ollama/ollama.service';
|
||||
import { SYSTEM_PROMPTS } from '../config/configuration';
|
||||
|
|
@ -45,7 +44,7 @@ export class MatrixService implements OnModuleInit, OnModuleDestroy {
|
|||
|
||||
// Setup logging
|
||||
LogService.setLogger(new RichConsoleLogger());
|
||||
LogService.setLevel(LogService.LogLevel.INFO);
|
||||
LogService.setLevel(LogLevel.INFO);
|
||||
|
||||
// Storage for sync token persistence
|
||||
const storage = new SimpleFsStorageProvider(storagePath || './data/bot-storage.json');
|
||||
|
|
@ -91,7 +90,7 @@ export class MatrixService implements OnModuleInit, OnModuleDestroy {
|
|||
return this.sessions.get(senderId)!;
|
||||
}
|
||||
|
||||
private async handleRoomMessage(roomId: string, event: RoomEvent<MessageEvent>) {
|
||||
private async handleRoomMessage(roomId: string, event: any) {
|
||||
// Ignore messages from self
|
||||
if (event.sender === this.botUserId) return;
|
||||
|
||||
|
|
@ -102,7 +101,7 @@ export class MatrixService implements OnModuleInit, OnModuleDestroy {
|
|||
}
|
||||
|
||||
// Only handle text messages
|
||||
const content = event.content;
|
||||
const content = event.content as { msgtype?: string; body?: string };
|
||||
if (content.msgtype !== 'm.text') return;
|
||||
|
||||
const body = content.body;
|
||||
|
|
@ -151,7 +150,10 @@ export class MatrixService implements OnModuleInit, OnModuleDestroy {
|
|||
break;
|
||||
|
||||
default:
|
||||
await this.sendMessage(roomId, `Unbekannter Befehl: !${command}\n\nVerwende !help für eine Liste der Befehle.`);
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`Unbekannter Befehl: !${command}\n\nVerwende !help für eine Liste der Befehle.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -197,13 +199,19 @@ Schreibe einfach eine Nachricht und ich antworte!
|
|||
})
|
||||
.join('\n');
|
||||
|
||||
await this.sendMessage(roomId, `**Verfügbare Modelle:**\n\n${modelList}\n\nWechseln mit: \`!model [name]\``);
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`**Verfügbare Modelle:**\n\n${modelList}\n\nWechseln mit: \`!model [name]\``
|
||||
);
|
||||
}
|
||||
|
||||
private async setModel(roomId: string, sender: string, modelName: string) {
|
||||
if (!modelName) {
|
||||
const session = this.getSession(sender);
|
||||
await this.sendMessage(roomId, `Aktuelles Modell: \`${session.model}\`\n\nVerwendung: \`!model gemma3:4b\``);
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`Aktuelles Modell: \`${session.model}\`\n\nVerwendung: \`!model gemma3:4b\``
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -212,7 +220,10 @@ Schreibe einfach eine Nachricht und ich antworte!
|
|||
|
||||
if (!exists) {
|
||||
const available = models.map((m) => m.name).join(', ');
|
||||
await this.sendMessage(roomId, `Modell "${modelName}" nicht gefunden.\n\nVerfügbar: ${available}`);
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`Modell "${modelName}" nicht gefunden.\n\nVerfügbar: ${available}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -230,14 +241,21 @@ Schreibe einfach eine Nachricht und ich antworte!
|
|||
if (!mode) {
|
||||
const session = this.getSession(sender);
|
||||
const currentMode =
|
||||
Object.entries(SYSTEM_PROMPTS).find(([_, v]) => v === session.systemPrompt)?.[0] || 'custom';
|
||||
await this.sendMessage(roomId, `Aktueller Modus: \`${currentMode}\`\n\nVerfügbar: ${availableModes.join(', ')}`);
|
||||
Object.entries(SYSTEM_PROMPTS).find(([_, v]) => v === session.systemPrompt)?.[0] ||
|
||||
'custom';
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`Aktueller Modus: \`${currentMode}\`\n\nVerfügbar: ${availableModes.join(', ')}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const normalizedMode = mode.toLowerCase();
|
||||
if (!SYSTEM_PROMPTS[normalizedMode]) {
|
||||
await this.sendMessage(roomId, `Unbekannter Modus: ${mode}\n\nVerfügbar: ${availableModes.join(', ')}`);
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`Unbekannter Modus: ${mode}\n\nVerfügbar: ${availableModes.join(', ')}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -277,7 +295,7 @@ Schreibe einfach eine Nachricht und ich antworte!
|
|||
const session = this.getSession(sender);
|
||||
|
||||
// Send typing indicator
|
||||
await this.client.sendTyping(roomId, true, 30000);
|
||||
await this.client.setTyping(roomId, true, 30000);
|
||||
|
||||
try {
|
||||
// Add user message to history
|
||||
|
|
@ -300,12 +318,12 @@ Schreibe einfach eine Nachricht und ich antworte!
|
|||
session.history.push({ role: 'assistant', content: response });
|
||||
|
||||
// Stop typing indicator
|
||||
await this.client.sendTyping(roomId, false);
|
||||
await this.client.setTyping(roomId, false);
|
||||
|
||||
// Send response (Matrix has higher message limits than Telegram)
|
||||
await this.sendMessage(roomId, response);
|
||||
} catch (error) {
|
||||
await this.client.sendTyping(roomId, false);
|
||||
await this.client.setTyping(roomId, false);
|
||||
this.logger.error(`Error processing message:`, error);
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler';
|
||||
await this.sendMessage(roomId, `❌ Fehler: ${errorMessage}`);
|
||||
|
|
@ -325,16 +343,18 @@ Schreibe einfach eine Nachricht und ich antworte!
|
|||
}
|
||||
|
||||
private markdownToHtml(markdown: string): string {
|
||||
return markdown
|
||||
// Code blocks
|
||||
.replace(/```(\w+)?\n([\s\S]*?)```/g, '<pre><code>$2</code></pre>')
|
||||
// Inline code
|
||||
.replace(/`([^`]+)`/g, '<code>$1</code>')
|
||||
// Bold
|
||||
.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
|
||||
// Italic
|
||||
.replace(/\*([^*]+)\*/g, '<em>$1</em>')
|
||||
// Line breaks
|
||||
.replace(/\n/g, '<br/>');
|
||||
return (
|
||||
markdown
|
||||
// Code blocks
|
||||
.replace(/```(\w+)?\n([\s\S]*?)```/g, '<pre><code>$2</code></pre>')
|
||||
// Inline code
|
||||
.replace(/`([^`]+)`/g, '<code>$1</code>')
|
||||
// Bold
|
||||
.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
|
||||
// Italic
|
||||
.replace(/\*([^*]+)\*/g, '<em>$1</em>')
|
||||
// Line breaks
|
||||
.replace(/\n/g, '<br/>')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ import {
|
|||
AutojoinRoomsMixin,
|
||||
RichConsoleLogger,
|
||||
LogService,
|
||||
MessageEvent,
|
||||
RoomEvent,
|
||||
LogLevel,
|
||||
} from 'matrix-bot-sdk';
|
||||
import { ProjectService } from '../project/project.service';
|
||||
import { MediaService } from '../media/media.service';
|
||||
|
|
@ -44,7 +43,7 @@ export class MatrixService implements OnModuleInit, OnModuleDestroy {
|
|||
}
|
||||
|
||||
LogService.setLogger(new RichConsoleLogger());
|
||||
LogService.setLevel(LogService.LogLevel.INFO);
|
||||
LogService.setLevel(LogLevel.INFO);
|
||||
|
||||
const storage = new SimpleFsStorageProvider(storagePath || './data/bot-storage.json');
|
||||
this.client = new MatrixClient(homeserverUrl!, accessToken, storage);
|
||||
|
|
@ -71,15 +70,15 @@ export class MatrixService implements OnModuleInit, OnModuleDestroy {
|
|||
return this.allowedUsers.includes(userId);
|
||||
}
|
||||
|
||||
private async handleRoomMessage(roomId: string, event: RoomEvent<MessageEvent>) {
|
||||
private async handleRoomMessage(roomId: string, event: any) {
|
||||
if (event.sender === this.botUserId) return;
|
||||
if (!this.isAllowed(event.sender)) return;
|
||||
|
||||
const content = event.content;
|
||||
const content = event.content as { msgtype?: string; body?: string; url?: string; info?: any };
|
||||
const msgtype = content.msgtype;
|
||||
|
||||
if (msgtype === 'm.text') {
|
||||
const body = content.body;
|
||||
const body = content.body || '';
|
||||
if (body.startsWith('!')) {
|
||||
await this.handleCommand(roomId, event.sender, body);
|
||||
} else {
|
||||
|
|
@ -167,7 +166,10 @@ ${styles}
|
|||
|
||||
private async createProject(roomId: string, sender: string, name: string) {
|
||||
if (!name) {
|
||||
await this.sendMessage(roomId, 'Verwendung: `!new Projektname`\n\nBeispiel: `!new Gartenhaus-Renovierung`');
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
'Verwendung: `!new Projektname`\n\nBeispiel: `!new Gartenhaus-Renovierung`'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -185,7 +187,10 @@ ${styles}
|
|||
);
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to create project:', error);
|
||||
await this.sendMessage(roomId, `❌ Fehler: ${error instanceof Error ? error.message : 'Unbekannt'}`);
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`❌ Fehler: ${error instanceof Error ? error.message : 'Unbekannt'}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -208,12 +213,18 @@ ${styles}
|
|||
})
|
||||
);
|
||||
|
||||
await this.sendMessage(roomId, `**📂 Deine Projekte:**\n\n${projectList.join('\n\n')}\n\nWechseln mit: \`!switch [ID]\``);
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`**📂 Deine Projekte:**\n\n${projectList.join('\n\n')}\n\nWechseln mit: \`!switch [ID]\``
|
||||
);
|
||||
}
|
||||
|
||||
private async switchProject(roomId: string, sender: string, idPrefix: string) {
|
||||
if (!idPrefix) {
|
||||
await this.sendMessage(roomId, 'Verwendung: `!switch [ID]`\n\nZeige Projekte mit `!projects`');
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
'Verwendung: `!switch [ID]`\n\nZeige Projekte mit `!projects`'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -278,7 +289,10 @@ ${styles}
|
|||
.map(([key, value]) => `**${key}** - ${value.name}\n_${value.prompt.slice(0, 80)}..._`)
|
||||
.join('\n\n');
|
||||
|
||||
await this.sendMessage(roomId, `**📝 Verfügbare Blog-Stile:**\n\n${styles}\n\nVerwendung: \`!generate [stil]\``);
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`**📝 Verfügbare Blog-Stile:**\n\n${styles}\n\nVerwendung: \`!generate [stil]\``
|
||||
);
|
||||
}
|
||||
|
||||
private async generateBlogpost(roomId: string, sender: string, style: string) {
|
||||
|
|
@ -300,18 +314,21 @@ ${styles}
|
|||
}
|
||||
|
||||
await this.sendMessage(roomId, '🚀 Generiere Blogbeitrag...\n\nDas kann einen Moment dauern.');
|
||||
await this.client.sendTyping(roomId, true, 60000);
|
||||
await this.client.setTyping(roomId, true, 60000);
|
||||
|
||||
try {
|
||||
const content = await this.generationService.generateBlogpost(projectId, selectedStyle);
|
||||
await this.client.sendTyping(roomId, false);
|
||||
await this.client.setTyping(roomId, false);
|
||||
|
||||
await this.sendMessage(roomId, content);
|
||||
await this.sendMessage(roomId, '✅ Blogbeitrag erstellt!\n\nExportieren mit `!export`');
|
||||
} catch (error) {
|
||||
await this.client.sendTyping(roomId, false);
|
||||
await this.client.setTyping(roomId, false);
|
||||
this.logger.error('Generation failed:', error);
|
||||
await this.sendMessage(roomId, `❌ Fehler: ${error instanceof Error ? error.message : 'Unbekannt'}`);
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
`❌ Fehler: ${error instanceof Error ? error.message : 'Unbekannt'}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -324,7 +341,10 @@ ${styles}
|
|||
|
||||
const latest = await this.generationService.getLatestGeneration(projectId);
|
||||
if (!latest) {
|
||||
await this.sendMessage(roomId, 'Noch kein Blogbeitrag generiert.\n\nErstelle einen mit `!generate`');
|
||||
await this.sendMessage(
|
||||
roomId,
|
||||
'Noch kein Blogbeitrag generiert.\n\nErstelle einen mit `!generate`'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -404,7 +424,13 @@ ${styles}
|
|||
const contentType = content.info?.mimetype || 'audio/ogg';
|
||||
const duration = Math.round((content.info?.duration || 0) / 1000);
|
||||
|
||||
const item = await this.mediaService.processVoice(projectId, buffer, contentType, mxcUrl, duration);
|
||||
const item = await this.mediaService.processVoice(
|
||||
projectId,
|
||||
buffer,
|
||||
contentType,
|
||||
mxcUrl,
|
||||
duration
|
||||
);
|
||||
|
||||
const stats = await this.projectService.getStats(projectId);
|
||||
let reply = `✅ Sprachnotiz gespeichert! (${stats.voices} gesamt)`;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export class TranscriptionService {
|
|||
}
|
||||
|
||||
// Create a File-like object for the API
|
||||
const file = new File([audioBuffer], 'audio.ogg', { type: 'audio/ogg' });
|
||||
const file = new File([new Uint8Array(audioBuffer)], 'audio.ogg', { type: 'audio/ogg' });
|
||||
|
||||
const response = await this.openai.audio.transcriptions.create({
|
||||
file,
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ import {
|
|||
AutojoinRoomsMixin,
|
||||
RichConsoleLogger,
|
||||
LogService,
|
||||
MessageEvent,
|
||||
RoomEvent,
|
||||
LogLevel,
|
||||
} from 'matrix-bot-sdk';
|
||||
import { AnalyticsService } from '../analytics/analytics.service';
|
||||
import { UsersService } from '../users/users.service';
|
||||
|
|
@ -38,7 +37,7 @@ export class MatrixService implements OnModuleInit, OnModuleDestroy {
|
|||
}
|
||||
|
||||
LogService.setLogger(new RichConsoleLogger());
|
||||
LogService.setLevel(LogService.LogLevel.INFO);
|
||||
LogService.setLevel(LogLevel.INFO);
|
||||
|
||||
const storage = new SimpleFsStorageProvider(storagePath || './data/bot-storage.json');
|
||||
this.client = new MatrixClient(homeserverUrl!, accessToken, storage);
|
||||
|
|
@ -61,10 +60,10 @@ export class MatrixService implements OnModuleInit, OnModuleDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
private async handleRoomMessage(roomId: string, event: RoomEvent<MessageEvent>) {
|
||||
private async handleRoomMessage(roomId: string, event: any) {
|
||||
if (event.sender === this.botUserId) return;
|
||||
|
||||
const content = event.content;
|
||||
const content = event.content as { msgtype?: string; body?: string };
|
||||
if (content.msgtype !== 'm.text') return;
|
||||
|
||||
const body = content.body;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue