diff --git a/docs/URL_SCHEMA.md b/docs/URL_SCHEMA.md index fc0a1fd3e..cc0bfde19 100644 --- a/docs/URL_SCHEMA.md +++ b/docs/URL_SCHEMA.md @@ -13,25 +13,68 @@ This document defines the URL schema for all mana.how subdomains. ## Complete URL Mapping -### Core Apps +### Core Apps (Production) -| App | Landing Page | Web App | API | -|-----|--------------|---------|-----| -| **Calendar** | calendars.mana.how | calendar.mana.how | calendar-api.mana.how | -| **Clock** | clocks.mana.how | clock.mana.how | clock-api.mana.how | -| **Todo** | todos.mana.how | todo.mana.how | todo-api.mana.how | -| **Contacts** | contacts.mana.how | contact.mana.how | contact-api.mana.how | -| **Chat** | chats.mana.how | chat.mana.how | chat-api.mana.how | -| **Picture** | pictures.mana.how | picture.mana.how | picture-api.mana.how | -| **Zitare** | zitares.mana.how | zitare.mana.how | zitare-api.mana.how | +| App | Web App | API | Status | +|-----|---------|-----|--------| +| **Calendar** | calendar.mana.how | api.mana.how/calendar | Active | +| **Clock** | clock.mana.how | api.mana.how/clock | Active | +| **Todo** | todo.mana.how | api.mana.how/todo | Active | +| **Contacts** | contacts.mana.how | api.mana.how/contacts | Active | +| **Chat** | chat.mana.how | api.mana.how/chat | Active | +| **Storage** | storage.mana.how | api.mana.how/storage | Active | +| **Zitare** | zitare.mana.how | api.mana.how/zitare | Active | +| **NutriPhi** | nutriphi.mana.how | api.mana.how/nutriphi | Active | +| **Presi** | presi.mana.how | api.mana.how/presi | Active | +| **SkillTree** | skilltree.mana.how | api.mana.how/skilltree | Active | +| **Photos** | photos.mana.how | api.mana.how/photos | Active | -### Platform +### Platform Services -| Service | URL | -|---------|-----| -| **Main Dashboard** | mana.how | -| **Dashboard App** | app.mana.how | -| **Auth Service** | auth.mana.how | +| Service | URL | Description | +|---------|-----|-------------| +| **Main Dashboard** | mana.how | Main landing/dashboard | +| **Auth Service** | auth.mana.how | Central authentication (mana-core-auth) | +| **API Gateway** | api.mana.how | Unified API gateway | +| **Media Service** | media.mana.how | Image/video processing | +| **LLM Service** | llm.mana.how | LLM abstraction layer | +| **LLM Playground** | playground.mana.how | LLM testing interface | +| **Link Shortener** | link.mana.how | URL shortener (uload) | +| **File Storage** | files.mana.how | MinIO/S3 file access | + +### Matrix/Communication + +| Service | URL | Description | +|---------|-----|-------------| +| **Matrix Server** | matrix.mana.how | Synapse homeserver | +| **Element Web** | element.mana.how | Matrix web client | +| **N8N** | n.mana.how | Workflow automation | + +### Monitoring & Admin + +| Service | URL | Description | +|---------|-----|-------------| +| **Grafana** | grafana.mana.how | Metrics dashboards | +| **Umami** | (internal :8010) | Web analytics | + +### Umami Tracking (Analytics) + +For web analytics, the following apps are tracked in Umami: + +| Umami Website ID | Display Name | Domain | +|------------------|--------------|--------| +| `manacore-webapp` | Dashboard | mana.how | +| `chat-webapp` | Chat | chat.mana.how | +| `todo-webapp` | Todo | todo.mana.how | +| `calendar-webapp` | Calendar | calendar.mana.how | +| `clock-webapp` | Clock | clock.mana.how | +| `contacts-webapp` | Contacts | contacts.mana.how | +| `storage-webapp` | Storage | storage.mana.how | +| `zitare-webapp` | Zitare | zitare.mana.how | +| `nutriphi-webapp` | NutriPhi | nutriphi.mana.how | +| `presi-webapp` | Presi | presi.mana.how | +| `skilltree-webapp` | SkillTree | skilltree.mana.how | +| `photos-webapp` | Photos | photos.mana.how | --- diff --git a/services/matrix-nutriphi-bot/src/bot/matrix.service.ts b/services/matrix-nutriphi-bot/src/bot/matrix.service.ts index 053d8f631..d76d2b92f 100644 --- a/services/matrix-nutriphi-bot/src/bot/matrix.service.ts +++ b/services/matrix-nutriphi-bot/src/bot/matrix.service.ts @@ -155,17 +155,11 @@ Sag "hilfe" fur alle Befehle!`; await this.client.setTyping(roomId, true, 60000); try { - // Download audio from Matrix + // Download audio from Matrix using authenticated API const mxcUrl = event.content.url!; - const httpUrl = this.client.mxcToHttp(mxcUrl); - this.logger.log(`Downloading audio from ${httpUrl}`); + this.logger.log(`Downloading audio from ${mxcUrl}`); - const response = await fetch(httpUrl); - if (!response.ok) { - throw new Error(`Failed to download audio: ${response.status}`); - } - - const buffer = Buffer.from(await response.arrayBuffer()); + const buffer = await this.downloadMedia(mxcUrl); // Transcribe audio const transcription = await this.transcriptionService.transcribe(buffer); @@ -709,17 +703,11 @@ Sag "hilfe" fur alle Befehle!`; } private async downloadMatrixImage(mxcUrl: string): Promise { - const httpUrl = this.client.mxcToHttp(mxcUrl); - this.logger.log(`Downloading image from ${httpUrl}`); + this.logger.log(`Downloading image from ${mxcUrl}`); - const response = await fetch(httpUrl); - if (!response.ok) { - throw new Error(`Failed to download image: ${response.status}`); - } - - const buffer = await response.arrayBuffer(); - const base64 = Buffer.from(buffer).toString('base64'); - return base64; + // Use the authenticated download method from BaseMatrixService + const buffer = await this.downloadMedia(mxcUrl); + return buffer.toString('base64'); } private markdownToHtmlLocal(markdown: string): string { diff --git a/services/matrix-stats-bot/src/umami/umami.service.ts b/services/matrix-stats-bot/src/umami/umami.service.ts index a16c46b23..30771c622 100644 --- a/services/matrix-stats-bot/src/umami/umami.service.ts +++ b/services/matrix-stats-bot/src/umami/umami.service.ts @@ -9,6 +9,22 @@ interface UmamiStats { totaltime: { value: number; change: number }; } +// Raw API response format from Umami +interface UmamiStatsRaw { + pageviews: number; + visitors: number; + visits: number; + bounces: number; + totaltime: number; + comparison: { + pageviews: number; + visitors: number; + visits: number; + bounces: number; + totaltime: number; + }; +} + interface UmamiRealtime { pageviews: number; visitors: number; @@ -119,9 +135,40 @@ export class UmamiService implements OnModuleInit { } async getStats(websiteId: string, startAt: number, endAt: number): Promise { - return this.request( + const raw = await this.request( `/api/websites/${websiteId}/stats?startAt=${startAt}&endAt=${endAt}` ); + + if (!raw) return null; + + // Transform raw API response to expected format + const calcChange = (current: number, previous: number): number => { + if (previous === 0) return current > 0 ? 100 : 0; + return Math.round(((current - previous) / previous) * 100); + }; + + return { + pageviews: { + value: raw.pageviews, + change: calcChange(raw.pageviews, raw.comparison?.pageviews ?? 0), + }, + visitors: { + value: raw.visitors, + change: calcChange(raw.visitors, raw.comparison?.visitors ?? 0), + }, + visits: { + value: raw.visits, + change: calcChange(raw.visits, raw.comparison?.visits ?? 0), + }, + bounces: { + value: raw.bounces, + change: calcChange(raw.bounces, raw.comparison?.bounces ?? 0), + }, + totaltime: { + value: raw.totaltime, + change: calcChange(raw.totaltime, raw.comparison?.totaltime ?? 0), + }, + }; } async getRealtime(websiteId: string): Promise { @@ -133,7 +180,10 @@ export class UmamiService implements OnModuleInit { startAt: number, endAt: number, unit: 'hour' | 'day' | 'month' = 'day' - ): Promise<{ pageviews: { x: string; y: number }[]; sessions: { x: string; y: number }[] } | null> { + ): Promise<{ + pageviews: { x: string; y: number }[]; + sessions: { x: string; y: number }[]; + } | null> { return this.request( `/api/websites/${websiteId}/pageviews?startAt=${startAt}&endAt=${endAt}&unit=${unit}` );