diff --git a/cmd/server/matrix.go b/cmd/server/matrix.go index f0beef7..62b4f93 100644 --- a/cmd/server/matrix.go +++ b/cmd/server/matrix.go @@ -159,8 +159,10 @@ func (m *MatrixClient) mapEventToMessage(ctx context.Context, ev *event.Event) ( switch ev.Type { case event.EventMessage: - if body, ok := extractBody(ev); ok { - return MatrixMessage{Sender: sender, Body: body, Timestamp: ts}, true + if msg, ok := m.extractMessage(ev); ok { + msg.Sender = sender + msg.Timestamp = ts + return msg, true } return MatrixMessage{}, false case event.EventEncrypted: @@ -176,8 +178,10 @@ func (m *MatrixClient) mapEventToMessage(ctx context.Context, ev *event.Event) ( cancel() } if err == nil && decrypted != nil { - if body, ok := extractBody(decrypted); ok { - return MatrixMessage{Sender: sender, Body: body, Timestamp: ts}, true + if msg, ok := m.extractMessage(decrypted); ok { + msg.Sender = sender + msg.Timestamp = ts + return msg, true } } } @@ -195,20 +199,46 @@ func (m *MatrixClient) formatTimestamp(tsMillis int64) string { return time.UnixMilli(tsMillis).In(loc).Format("02.01.2006 15:04") } -func extractBody(ev *event.Event) (string, bool) { +func (m *MatrixClient) extractMessage(ev *event.Event) (MatrixMessage, bool) { if ev == nil { - return "", false + return MatrixMessage{}, false } _ = ev.Content.ParseRaw(ev.Type) msg := ev.Content.AsMessage() - if msg.MsgType != event.MsgText && msg.MsgType != event.MsgNotice { - return "", false + switch msg.MsgType { + case event.MsgText, event.MsgNotice: + body := strings.TrimSpace(msg.Body) + if body == "" { + return MatrixMessage{}, false + } + return MatrixMessage{Body: body}, true + case event.MsgImage: + imageURL := m.mxcToHTTP(string(msg.URL)) + if imageURL == "" { + // Encrypted file attachments need additional media decryption path. + return MatrixMessage{Body: "[Bild konnte nicht direkt dargestellt werden]"}, true + } + body := strings.TrimSpace(msg.Body) + if body == "" { + body = "Bild" + } + return MatrixMessage{Body: body, ImageURL: imageURL}, true + default: + return MatrixMessage{}, false } - body := strings.TrimSpace(msg.Body) - if body == "" { - return "", false +} + +func (m *MatrixClient) mxcToHTTP(mxc string) string { + raw := strings.TrimSpace(mxc) + if raw == "" || !strings.HasPrefix(raw, "mxc://") { + return "" } - return body, true + trimmed := strings.TrimPrefix(raw, "mxc://") + parts := strings.SplitN(trimmed, "/", 2) + if len(parts) != 2 || parts[0] == "" || parts[1] == "" { + return "" + } + return fmt.Sprintf("%s/_matrix/media/v3/download/%s/%s", m.HomeserverURL, url.PathEscape(parts[0]), url.PathEscape(parts[1])) } func shortMatrixSender(sender string) string { diff --git a/cmd/server/types.go b/cmd/server/types.go index 9039671..112d84b 100644 --- a/cmd/server/types.go +++ b/cmd/server/types.go @@ -190,4 +190,5 @@ type MatrixMessage struct { Sender string Body string Timestamp string + ImageURL string } diff --git a/static/styles.css b/static/styles.css index 078f8b5..aeaaa4b 100644 --- a/static/styles.css +++ b/static/styles.css @@ -274,6 +274,14 @@ button:hover { background: linear-gradient(180deg, #7cbc19, #5e8a12); } word-break: break-word; } +.matrix-image { + display: block; + max-width: 100%; + height: auto; + border-radius: 8px; + border: 1px solid #d7decb; +} + .matrix-card { display: flex; flex-direction: column; diff --git a/templates/dashboard.html b/templates/dashboard.html index 0217947..332cff6 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -94,6 +94,9 @@ {{range .MatrixMessages}}