Add poster image support to Matrix download listings
Some checks failed
Test action / kaas (push) Failing after 2s
Some checks failed
Test action / kaas (push) Failing after 2s
- Fetch and display poster images for tracked items in Matrix - Show monitored/unmonitored icons in listings - Limit displayed items to 12, with count and overflow message - Add tests for image fetching and formatting - Enable Grafana datasources - Fix Sonarr/Radarr URL config bug
This commit is contained in:
parent
e07257e137
commit
100a218aed
9 changed files with 432 additions and 59 deletions
|
|
@ -73,16 +73,22 @@ func handleDownloadList(ctx *Context, client arrclient.Client, contentType arr.C
|
|||
return
|
||||
}
|
||||
|
||||
var builder strings.Builder
|
||||
builder.WriteString(fmt.Sprintf("Tracked %s:\n", contentType.Label()))
|
||||
count := len(items)
|
||||
if count > 12 {
|
||||
count = 12
|
||||
}
|
||||
ctx.Reply("Tracked %s (showing %d of %d):", contentType.Label(), count, len(items))
|
||||
for i, item := range items {
|
||||
if i == 10 {
|
||||
builder.WriteString("…\n")
|
||||
if i == 12 {
|
||||
break
|
||||
}
|
||||
builder.WriteString(fmt.Sprintf("- `%d` %s — monitored=%t\n", item.ID, formatManagedItem(item), item.Monitored))
|
||||
if err := replyWithManagedItem(ctx, client, item); err != nil {
|
||||
ctx.Log.Err(err).Int64("item_id", item.ID).Str("content_type", contentType.Label()).Msg("Failed to send Matrix-native image for download listing")
|
||||
}
|
||||
}
|
||||
if len(items) > 12 {
|
||||
ctx.Reply("…and %d more.", len(items)-12)
|
||||
}
|
||||
ctx.Reply(builder.String())
|
||||
}
|
||||
|
||||
func handleDownloadSearch(ctx *Context, client arrclient.Client, contentType arr.ContentType) {
|
||||
|
|
@ -200,10 +206,7 @@ func replyWithSearchResults(ctx *Context, contentType arr.ContentType, query str
|
|||
}
|
||||
|
||||
func formatManagedItem(item arrclient.ManagedItem) string {
|
||||
if item.Year != 0 {
|
||||
return fmt.Sprintf("%s (%d)", item.Title, item.Year)
|
||||
}
|
||||
return item.Title
|
||||
return arrclient.FormatManagedItem(item)
|
||||
}
|
||||
|
||||
func parseEnabled(value string) (bool, error) {
|
||||
|
|
@ -220,3 +223,38 @@ func parseEnabled(value string) (bool, error) {
|
|||
func userIDString(userID id.UserID) string {
|
||||
return userID.String()
|
||||
}
|
||||
|
||||
func replyWithManagedItem(ctx *Context, client arrclient.Client, item arrclient.ManagedItem) error {
|
||||
details := formatDownloadListCaption(item)
|
||||
if item.ImageURL != "" {
|
||||
asset, err := client.FetchImage(ctx.Ctx, item)
|
||||
if err != nil {
|
||||
ctx.Log.Err(err).Int64("item_id", item.ID).Msg("Failed to fetch poster for Matrix listing")
|
||||
} else if asset != nil {
|
||||
if err := ctx.SendImage(asset, details); err != nil {
|
||||
ctx.Log.Err(err).Int64("item_id", item.ID).Msg("Failed to upload poster for Matrix listing")
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
ctx.Log.Debug().Int64("item_id", item.ID).Msg("Poster was empty for Matrix listing")
|
||||
}
|
||||
}
|
||||
ctx.Reply(details)
|
||||
return nil
|
||||
}
|
||||
|
||||
func formatDownloadListCaption(item arrclient.ManagedItem) string {
|
||||
return fmt.Sprintf("%s %s", monitoredIcon(item.Monitored), arrclient.FormatManagedItem(item))
|
||||
}
|
||||
|
||||
func formatDownloadListFallbackCard(item arrclient.ManagedItem) string {
|
||||
return formatDownloadListCaption(item)
|
||||
}
|
||||
|
||||
func monitoredIcon(monitored bool) string {
|
||||
if monitored {
|
||||
return "👁"
|
||||
}
|
||||
return "🚫"
|
||||
}
|
||||
|
|
|
|||
44
packages/arrtrix/pkg/matrixcmd/download_test.go
Normal file
44
packages/arrtrix/pkg/matrixcmd/download_test.go
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package matrixcmd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"sneeuwvlok/packages/arrtrix/pkg/arrclient"
|
||||
)
|
||||
|
||||
func TestFormatDownloadListFallbackCardUsesMonitoredIcon(t *testing.T) {
|
||||
item := arrclient.ManagedItem{
|
||||
ID: 1,
|
||||
Title: "Severance",
|
||||
Year: 2022,
|
||||
Monitored: true,
|
||||
}
|
||||
|
||||
fallback := formatDownloadListFallbackCard(item)
|
||||
if fallback != "👁 Severance (2022)" {
|
||||
t.Fatalf("unexpected monitored fallback %q", fallback)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatDownloadListFallbackCardUsesUnmonitoredIcon(t *testing.T) {
|
||||
item := arrclient.ManagedItem{
|
||||
ID: 7,
|
||||
Title: "Andor",
|
||||
Year: 2022,
|
||||
Monitored: false,
|
||||
}
|
||||
|
||||
fallback := formatDownloadListFallbackCard(item)
|
||||
if fallback != "🚫 Andor (2022)" {
|
||||
t.Fatalf("unexpected unmonitored fallback %q", fallback)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonitoredIcon(t *testing.T) {
|
||||
if monitoredIcon(true) != "👁" {
|
||||
t.Fatalf("expected monitored icon, got %q", monitoredIcon(true))
|
||||
}
|
||||
if monitoredIcon(false) != "🚫" {
|
||||
t.Fatalf("expected unmonitored icon, got %q", monitoredIcon(false))
|
||||
}
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ import (
|
|||
"maunium.net/go/mautrix/format"
|
||||
"maunium.net/go/mautrix/id"
|
||||
|
||||
"sneeuwvlok/packages/arrtrix/pkg/arrclient"
|
||||
"sneeuwvlok/packages/arrtrix/pkg/observability"
|
||||
)
|
||||
|
||||
|
|
@ -221,7 +222,49 @@ func (c *Context) Reply(message string, args ...any) {
|
|||
|
||||
content := format.RenderMarkdown(message, true, false)
|
||||
content.MsgType = event.MsgNotice
|
||||
if _, err := c.Bot.SendMessage(c.Ctx, c.OrigRoomID, event.EventMessage, &event.Content{Parsed: &content}, nil); err != nil {
|
||||
if err := c.sendNotice(&content); err != nil {
|
||||
c.Log.Err(err).Msg("Failed to reply to Matrix room command")
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Context) ReplyFormatted(body, formattedBody string) {
|
||||
content := &event.MessageEventContent{
|
||||
MsgType: event.MsgNotice,
|
||||
Body: body,
|
||||
Format: event.FormatHTML,
|
||||
FormattedBody: formattedBody,
|
||||
}
|
||||
if err := c.sendNotice(content); err != nil {
|
||||
c.Log.Err(err).Msg("Failed to reply to Matrix room command")
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Context) SendImage(asset *arrclient.MediaAsset, body string) error {
|
||||
if asset == nil || len(asset.Data) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
mxcURL, file, err := c.Bot.UploadMedia(c.Ctx, c.OrigRoomID, asset.Data, asset.FileName, asset.MimeType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
content := &event.MessageEventContent{
|
||||
MsgType: event.MsgImage,
|
||||
Body: body,
|
||||
FileName: asset.FileName,
|
||||
URL: mxcURL,
|
||||
File: file,
|
||||
Info: &event.FileInfo{
|
||||
MimeType: asset.MimeType,
|
||||
Size: len(asset.Data),
|
||||
},
|
||||
}
|
||||
_, err = c.Bot.SendMessage(c.Ctx, c.OrigRoomID, event.EventMessage, &event.Content{Parsed: content}, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Context) sendNotice(content *event.MessageEventContent) error {
|
||||
_, err := c.Bot.SendMessage(c.Ctx, c.OrigRoomID, event.EventMessage, &event.Content{Parsed: content}, nil)
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue