Spotify Link-Through & Navidrome Logo Overlay #15

Merged
Woahai321 merged 19 commits from main into main 2026-03-04 10:04:03 -07:00
Woahai321 commented 2026-02-22 16:27:45 -07:00 (Migrated from github.com)

First off — huge thanks for building this plugin. It's a great piece of work and exactly the kind of thing that makes self-hosting music actually fun.

Background

I've been in the middle of migrating away from Spotify to Navidrome and this plugin was a brilliant find. It meant the Discord presence experience I was used to carried over almost perfectly — my friends could still see what I was listening to, which was one of the things I'd quietly miss about Spotify. The plugin covered everything I needed, except for one thing my friends kept pointing out: they couldn't easily get to what I was listening to. On Spotify, clicking the track in someone's status opens it straight away — there was no equivalent here.

What I've Added

Spotify Link-Through (ListenBrainz-powered)

The track title, artist name, and album art in the Discord presence are now all clickable and link through to Spotify.

I deliberately went with ListenBrainz Labs for the resolution rather than just building a Spotify search URL: a search URL opens Spotify's search results page — you still have to find and click the right track yourself. What my friends actually wanted was to click and have it play, not have to go hunting. ListenBrainz maps MusicBrainz recording IDs (and track metadata as a fallback) directly to Spotify track IDs, so clicking the link opens the exact track ready to play.

The resolution chain is:

  1. MBID lookup — if the track has a MusicBrainz Recording ID, that's used first for the most accurate match
  2. Metadata lookup — artist name, track title, and album are used if no MBID is available
  3. Search URL fallback — if neither resolves, a Spotify search URL is used so the link is never dead

Resolved URLs are cached (30 days for direct track links, 4 hours for search fallbacks) to keep things snappy and avoid hammering the API.

Navidrome Logo Overlay

image

(The example screenshot shows as purple, this is just in my deployment the code references the official blue logo.)
A small Navidrome logo badge is shown in the corner of the album art. Purely aesthetic — it gives the presence a bit of identity and makes it clear the music is coming from Navidrome rather than looking like a generic status. It's on by default but can be disabled in the plugin settings for anyone who prefers a clean album art display.


I understand this is a navidrome official repo, however I thought best to contribute the work I have done on the project to make it useable for me.
Happy to tweak anything — open to feedback!

First off — huge thanks for building this plugin. It's a great piece of work and exactly the kind of thing that makes self-hosting music actually fun. ## Background I've been in the middle of migrating away from Spotify to Navidrome and this plugin was a brilliant find. It meant the Discord presence experience I was used to carried over almost perfectly — my friends could still see what I was listening to, which was one of the things I'd quietly miss about Spotify. The plugin covered everything I needed, except for one thing my friends kept pointing out: they couldn't easily *get to* what I was listening to. On Spotify, clicking the track in someone's status opens it straight away — there was no equivalent here. ## What I've Added ### Spotify Link-Through (ListenBrainz-powered) The track title, artist name, and album art in the Discord presence are now all clickable and link through to Spotify. I deliberately went with [ListenBrainz Labs](https://labs.api.listenbrainz.org) for the resolution rather than just building a Spotify search URL: a search URL opens Spotify's search results page — you still have to find and click the right track yourself. What my friends actually wanted was to click and have it *play*, not have to go hunting. ListenBrainz maps MusicBrainz recording IDs (and track metadata as a fallback) directly to Spotify track IDs, so clicking the link opens the exact track ready to play. The resolution chain is: 1. **MBID lookup** — if the track has a MusicBrainz Recording ID, that's used first for the most accurate match 2. **Metadata lookup** — artist name, track title, and album are used if no MBID is available 3. **Search URL fallback** — if neither resolves, a Spotify search URL is used so the link is never dead Resolved URLs are cached (30 days for direct track links, 4 hours for search fallbacks) to keep things snappy and avoid hammering the API. ### Navidrome Logo Overlay <img width="340" height="152" alt="image" src="https://github.com/user-attachments/assets/935fb181-4285-4fd6-b436-47e156706a1d" /> **(The example screenshot shows as purple, this is just in my deployment the code references the official blue logo.)** A small Navidrome logo badge is shown in the corner of the album art. Purely aesthetic — it gives the presence a bit of identity and makes it clear the music is coming from Navidrome rather than looking like a generic status. It's on by default but can be disabled in the plugin settings for anyone who prefers a clean album art display. --- I understand this is a navidrome official repo, however I thought best to contribute the work I have done on the project to make it useable for me. Happy to tweak anything — open to feedback!
gemini-code-assist[bot] commented 2026-02-22 16:28:08 -07:00 (Migrated from github.com)

Summary of Changes

Hello @Woahai321, I'm Gemini Code Assist1 ! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the Discord Rich Presence plugin for Navidrome by adding interactive Spotify linking and a visual branding element. Users can now click on the track title, artist, or album art in their Discord status to directly open the corresponding song on Spotify, powered by intelligent resolution via ListenBrainz. Additionally, a subtle Navidrome logo overlay has been introduced to the album art, providing clear identification of the music source. These changes aim to improve the user experience by making shared music more accessible and visually distinct.

Highlights

  • Spotify Link-Through: Implemented clickable Spotify links for track title, artist name, and album art within the Discord presence. These links are resolved using the ListenBrainz Labs API for direct track links, falling back to metadata-based resolution or a Spotify search URL.
  • Navidrome Logo Overlay: Added an optional Navidrome logo overlay badge to the corner of the album art displayed in Discord, providing visual branding for the music source. This feature is enabled by default and can be disabled in plugin settings.
  • Spotify URL Caching: Introduced caching for resolved Spotify URLs (30 days for direct track links, 4 hours for search fallbacks) to optimize performance and reduce calls to the ListenBrainz API.
  • Improved Artist Parsing: Enhanced artist parsing logic to correctly identify primary artists by stripping 'Feat.', 'Ft.', 'Featuring', '&', or '/' suffixes for more accurate Spotify lookups.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • README.md
    • Updated the "Features" section to include clickable Spotify links and the Navidrome logo overlay.
    • Added a new configuration option for "Show Navidrome Logo Overlay" with its description.
    • Expanded the "Host Services" table to reflect new HTTP and Cache usages for ListenBrainz.
    • Introduced a new "Spotify Linking" section detailing the resolution process and caching.
    • Updated the "Files" table to include navidrome.webp and reflect main.go's new responsibilities.
  • coverart_test.go
    • Added integration build tags to the file.
  • main.go
    • Imported crypto/sha256, encoding/hex, and net/url for Spotify URL resolution and caching.
    • Defined navLogoOverlayKey constant and navidromeLogoURL.
    • Implemented buildSpotifySearchURL, spotifySearch, spotifyCacheKey, listenBrainzResult struct, trySpotifyFromMBID, trySpotifyFromMetadata, parseSpotifyID, resolveSpotifyURL, and parsePrimaryArtist functions for Spotify integration.
    • Modified NowPlaying function to incorporate Navidrome logo overlay logic and pass Spotify URLs to rpc.sendActivity.
  • main_test.go
    • Added integration build tags to the file.
    • Updated GetConfig mocks to include navLogoOverlayKey.
  • manifest.json
    • Updated http permission reasons and requiredHosts to include labs.api.listenbrainz.org and raw.githubusercontent.com.
    • Added navlogooverlay boolean property to the plugin configuration schema with a default of true.
    • Added a UI control for navlogooverlay.
  • plugin_suite_test.go
    • Added integration build tags to the test suite.
  • rpc.go
    • Modified activity struct to include DetailsURL, StateURL, and StatusDisplayType fields for clickable links.
    • Modified activityAssets struct to include LargeURL, SmallImage, and SmallText for clickable album art and logo overlay.
    • Updated sendActivity to process and send the small image for the logo overlay.
  • rpc_test.go
    • Added integration build tags to the file.
  • url_builder_test.go
    • Added a new test file containing unit tests for parsePrimaryArtist, buildSpotifySearchURL, spotifyCacheKey, parseSpotifyID, and ListenBrainz request payload construction.
Activity
  • No human activity (comments, reviews, etc.) was detected for this pull request.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.


  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩︎

## Summary of Changes Hello @Woahai321, I'm Gemini Code Assist[^1]! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the Discord Rich Presence plugin for Navidrome by adding interactive Spotify linking and a visual branding element. Users can now click on the track title, artist, or album art in their Discord status to directly open the corresponding song on Spotify, powered by intelligent resolution via ListenBrainz. Additionally, a subtle Navidrome logo overlay has been introduced to the album art, providing clear identification of the music source. These changes aim to improve the user experience by making shared music more accessible and visually distinct. ### Highlights * **Spotify Link-Through**: Implemented clickable Spotify links for track title, artist name, and album art within the Discord presence. These links are resolved using the ListenBrainz Labs API for direct track links, falling back to metadata-based resolution or a Spotify search URL. * **Navidrome Logo Overlay**: Added an optional Navidrome logo overlay badge to the corner of the album art displayed in Discord, providing visual branding for the music source. This feature is enabled by default and can be disabled in plugin settings. * **Spotify URL Caching**: Introduced caching for resolved Spotify URLs (30 days for direct track links, 4 hours for search fallbacks) to optimize performance and reduce calls to the ListenBrainz API. * **Improved Artist Parsing**: Enhanced artist parsing logic to correctly identify primary artists by stripping 'Feat.', 'Ft.', 'Featuring', '&', or '/' suffixes for more accurate Spotify lookups. 🧠 **New Feature in Public Preview:** You can now enable **Memory** to help **Gemini Code Assist** learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. **Click [here](https://codeassist.google/code-review/login) to enable Memory in your admin console.** <details> <summary><b>Changelog</b></summary> * **README.md** * Updated the "Features" section to include clickable Spotify links and the Navidrome logo overlay. * Added a new configuration option for "Show Navidrome Logo Overlay" with its description. * Expanded the "Host Services" table to reflect new HTTP and Cache usages for ListenBrainz. * Introduced a new "Spotify Linking" section detailing the resolution process and caching. * Updated the "Files" table to include `navidrome.webp` and reflect `main.go`'s new responsibilities. * **coverart_test.go** * Added integration build tags to the file. * **main.go** * Imported `crypto/sha256`, `encoding/hex`, and `net/url` for Spotify URL resolution and caching. * Defined `navLogoOverlayKey` constant and `navidromeLogoURL`. * Implemented `buildSpotifySearchURL`, `spotifySearch`, `spotifyCacheKey`, `listenBrainzResult` struct, `trySpotifyFromMBID`, `trySpotifyFromMetadata`, `parseSpotifyID`, `resolveSpotifyURL`, and `parsePrimaryArtist` functions for Spotify integration. * Modified `NowPlaying` function to incorporate Navidrome logo overlay logic and pass Spotify URLs to `rpc.sendActivity`. * **main_test.go** * Added integration build tags to the file. * Updated `GetConfig` mocks to include `navLogoOverlayKey`. * **manifest.json** * Updated `http` permission reasons and `requiredHosts` to include `labs.api.listenbrainz.org` and `raw.githubusercontent.com`. * Added `navlogooverlay` boolean property to the plugin configuration schema with a default of `true`. * Added a UI control for `navlogooverlay`. * **plugin_suite_test.go** * Added integration build tags to the test suite. * **rpc.go** * Modified `activity` struct to include `DetailsURL`, `StateURL`, and `StatusDisplayType` fields for clickable links. * Modified `activityAssets` struct to include `LargeURL`, `SmallImage`, and `SmallText` for clickable album art and logo overlay. * Updated `sendActivity` to process and send the small image for the logo overlay. * **rpc_test.go** * Added integration build tags to the file. * **url_builder_test.go** * Added a new test file containing unit tests for `parsePrimaryArtist`, `buildSpotifySearchURL`, `spotifyCacheKey`, `parseSpotifyID`, and ListenBrainz request payload construction. </details> <details> <summary><b>Activity</b></summary> * No human activity (comments, reviews, etc.) was detected for this pull request. </details> <details> <summary><b>Using Gemini Code Assist</b></summary> <br> The full guide for Gemini Code Assist can be found on our [documentation page](https://developers.google.com/gemini-code-assist/docs/review-github-code), here are some quick tips. <b>Invoking Gemini</b> You can request assistance from Gemini at any point by creating a comment using either `/gemini <command>` or `@gemini-code-assist <command>`. Below is a summary of the supported commands on the current page. Feature | Command | Description --- | --- | --- Code Review | `/gemini review` | Performs a code review for the current pull request in its current state. Pull Request Summary | `/gemini summary` | Provides a summary of the current pull request in its current state. Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in pull request comments and review comments. Help | `/gemini help` | Displays a list of available commands. <b>Customization</b> To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a `.gemini/` folder in the base of the repository. Detailed instructions can be found [here](https://developers.google.com/gemini-code-assist/docs/customize-gemini-behavior-github). <b>Limitations & Feedback</b> Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with :thumbsup: and :thumbsdown: on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up [here](https://google.qualtrics.com/jfe/form/SV_2cyuGuTWsEw84yG). <b>You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the [Gemini Code Assist IDE Extension](https://cloud.google.com/products/gemini/code-assist).</b> </details> [^1]: Review the [Privacy Notices](https://policies.google.com/privacy), [Generative AI Prohibited Use Policy](https://policies.google.com/terms/generative-ai/use-policy), [Terms of Service](https://policies.google.com/terms), and learn how to configure Gemini Code Assist in GitHub [here](https://developers.google.com/gemini-code-assist/docs/customize-gemini-behavior-github). Gemini can make mistakes, so double check it and [use code with caution](https://support.google.com/legal/answer/13505487).
gemini-code-assist[bot] (Migrated from github.com) reviewed 2026-02-22 16:37:26 -07:00
gemini-code-assist[bot] (Migrated from github.com) left a comment

Code Review

This is a fantastic contribution that adds valuable new features to the plugin. The Spotify link-through powered by ListenBrainz is a great idea, and the implementation with caching and fallbacks is well-executed. The Navidrome logo overlay is a nice aesthetic touch. The code is generally clean and well-structured, and the addition of unit tests for the new logic is much appreciated. I've identified a few areas for improvement, including a minor bug in the manifest that would prevent the logo from loading, and a discrepancy between the described and implemented behavior for the track title link. My feedback aims to align the implementation with the feature description and improve robustness.

## Code Review This is a fantastic contribution that adds valuable new features to the plugin. The Spotify link-through powered by ListenBrainz is a great idea, and the implementation with caching and fallbacks is well-executed. The Navidrome logo overlay is a nice aesthetic touch. The code is generally clean and well-structured, and the addition of unit tests for the new logic is much appreciated. I've identified a few areas for improvement, including a minor bug in the manifest that would prevent the logo from loading, and a discrepancy between the described and implemented behavior for the track title link. My feedback aims to align the implementation with the feature description and improve robustness.
gemini-code-assist[bot] (Migrated from github.com) commented 2026-02-22 16:37:26 -07:00

medium

For consistency and improved robustness, it's better to use the %q format verb to safely quote the mbid string, just as you've done in trySpotifyFromMetadata. While MBIDs are UUIDs and unlikely to contain special characters that need escaping in a JSON string, this change would prevent any potential JSON injection issues and make the code more resilient.

body := fmt.Sprintf(`[{"recording_mbid":%q}]`, mbid)
![medium](https://www.gstatic.com/codereviewagent/medium-priority.svg) For consistency and improved robustness, it's better to use the `%q` format verb to safely quote the `mbid` string, just as you've done in `trySpotifyFromMetadata`. While MBIDs are UUIDs and unlikely to contain special characters that need escaping in a JSON string, this change would prevent any potential JSON injection issues and make the code more resilient. ```suggestion body := fmt.Sprintf(`[{"recording_mbid":%q}]`, mbid) ```
gemini-code-assist[bot] (Migrated from github.com) commented 2026-02-22 16:37:26 -07:00

medium

The PR description and README state that the track title should link directly to the Spotify track. However, DetailsURL is currently being set to a generic Spotify search URL using spotifySearch(input.Track.Title), while the more sophisticated resolveSpotifyURL is used for LargeURL.

To align with the described functionality and improve efficiency, you can call resolveSpotifyURL once before sending the activity and reuse its result for both DetailsURL and LargeURL. This ensures the track title links directly to the song and avoids a redundant API call.

	// Send activity update
	statusDisplayType := 2
	spotifyURL := resolveSpotifyURL(input.Track)
	if err := rpc.sendActivity(clientID, input.Username, userToken, activity{
		Application:       clientID,
		Name:              activityName,
		Type:              2, // Listening
		Details:           input.Track.Title,
		DetailsURL:        spotifyURL,
		State:             input.Track.Artist,
		StateURL:          spotifySearch(input.Track.Artist),
		StatusDisplayType: &statusDisplayType,
		Timestamps: activityTimestamps{
			Start: startTime,
			End:   endTime,
		},
		Assets: activityAssets{
			LargeImage: getImageURL(input.Username, input.Track.ID),
			LargeText:  input.Track.Album,
			LargeURL:   spotifyURL,
			SmallImage: smallImage,
			SmallText:  smallText,
		},
	}); err != nil {
![medium](https://www.gstatic.com/codereviewagent/medium-priority.svg) The PR description and README state that the track title should link directly to the Spotify track. However, `DetailsURL` is currently being set to a generic Spotify search URL using `spotifySearch(input.Track.Title)`, while the more sophisticated `resolveSpotifyURL` is used for `LargeURL`. To align with the described functionality and improve efficiency, you can call `resolveSpotifyURL` once before sending the activity and reuse its result for both `DetailsURL` and `LargeURL`. This ensures the track title links directly to the song and avoids a redundant API call. ```go // Send activity update statusDisplayType := 2 spotifyURL := resolveSpotifyURL(input.Track) if err := rpc.sendActivity(clientID, input.Username, userToken, activity{ Application: clientID, Name: activityName, Type: 2, // Listening Details: input.Track.Title, DetailsURL: spotifyURL, State: input.Track.Artist, StateURL: spotifySearch(input.Track.Artist), StatusDisplayType: &statusDisplayType, Timestamps: activityTimestamps{ Start: startTime, End: endTime, }, Assets: activityAssets{ LargeImage: getImageURL(input.Username, input.Track.ID), LargeText: input.Track.Album, LargeURL: spotifyURL, SmallImage: smallImage, SmallText: smallText, }, }); err != nil { ```
@@ -17,3 +17,4 @@
"labs.api.listenbrainz.org"
]
},
"websocket": {
gemini-code-assist[bot] (Migrated from github.com) commented 2026-02-22 16:37:26 -07:00

high

The Navidrome logo overlay is fetched from cdn.jsdelivr.net, but this host is missing from the requiredHosts list. This will prevent the logo from being displayed due to security restrictions. Please add cdn.jsdelivr.net to the list.

Additionally, raw.githubusercontent.com is included but doesn't appear to be used by the plugin. If it's not needed, you could remove it to keep the required permissions minimal.

      "requiredHosts": [
        "discord.com",
        "uguu.se",
        "labs.api.listenbrainz.org",
        "cdn.jsdelivr.net"
      ]
![high](https://www.gstatic.com/codereviewagent/high-priority.svg) The Navidrome logo overlay is fetched from `cdn.jsdelivr.net`, but this host is missing from the `requiredHosts` list. This will prevent the logo from being displayed due to security restrictions. Please add `cdn.jsdelivr.net` to the list. Additionally, `raw.githubusercontent.com` is included but doesn't appear to be used by the plugin. If it's not needed, you could remove it to keep the required permissions minimal. ```suggestion "requiredHosts": [ "discord.com", "uguu.se", "labs.api.listenbrainz.org", "cdn.jsdelivr.net" ] ```
github-actions[bot] commented 2026-02-23 16:30:11 -07:00 (Migrated from github.com)

Download the plugin for this PR: discord-rich-presence.zip

Built from 56b449b23a on 2026-02-28T00:34:31Z

Download the plugin for this PR: [discord-rich-presence.zip](https://nightly.link/navidrome/discord-rich-presence-plugin/actions/runs/22508626777/discord-rich-presence.zip) Built from 56b449b23ae2cc11ffa681932c25764baf42900e on 2026-02-28T00:34:31Z <!-- Sticky Pull Request Comment -->
deluan commented 2026-02-23 16:30:40 -07:00 (Migrated from github.com)

Hey, thanks for the contribution! I tried to implement this overlay and link, but could not find any docs or examples on how to do it. Thanks!

I have some ideas of refactoring this, so it would be easier if I could just commit some changes directly to your PR, is that ok?

Hey, thanks for the contribution! I tried to implement this overlay and link, but could not find any docs or examples on how to do it. Thanks! I have some ideas of refactoring this, so it would be easier if I could just commit some changes directly to your PR, is that ok?
deluan commented 2026-02-23 16:38:26 -07:00 (Migrated from github.com)

I actually prefer the overlay to always be applied, but the link should be optional, specially because most of self-hosters don't want their servers pinging Spotify servers.

I actually prefer the overlay to always be applied, but the link should be optional, specially because most of self-hosters don't want their servers pinging Spotify servers.
Woahai321 commented 2026-02-23 18:02:44 -07:00 (Migrated from github.com)

Hey, thanks for getting back to me on this.

I am more than happy for you to make changes to the pr please go ahead. My goal was to replicate what I had before as close as possible functionality wise and share my implementation of what I'm using everyday to provide inspiration.

I agree with the sentiment of logo always on and linking optional, this makes more sense for the wider community, especially people trying to move away from Spotify.

For clarity we would only be pining listenbrainz API on every change in order to construct a Spotify URL that's hyperlinked to the respective items.
Currently it's set:
(Album Cover) links to the crafted open.spotify url resolved through the listenbrainz API
(Title & Artist) link to a crafted to a crafted open.spotify search URL of the respective content.
(Album) has to be the same link as the artwork.

My initial thoughts on making linking an optional setting in the configuration leads me to enhancing this to offer the user Spotify / YTmusic / etc URLs linked to the items (this was a route I initially went down)

Let me know your thoughts

Hey, thanks for getting back to me on this. I am more than happy for you to make changes to the pr please go ahead. My goal was to replicate what I had before as close as possible functionality wise and share my implementation of what I'm using everyday to provide inspiration. I agree with the sentiment of logo always on and linking optional, this makes more sense for the wider community, especially people trying to move away from Spotify. For clarity we would only be pining listenbrainz API on every change in order to construct a Spotify URL that's hyperlinked to the respective items. Currently it's set: (Album Cover) links to the crafted open.spotify url resolved through the listenbrainz API (Title & Artist) link to a crafted to a crafted open.spotify search URL of the respective content. (Album) has to be the same link as the artwork. My initial thoughts on making linking an optional setting in the configuration leads me to enhancing this to offer the user Spotify / YTmusic / etc URLs linked to the items (this was a route I initially went down) Let me know your thoughts
deluan commented 2026-02-23 18:36:49 -07:00 (Migrated from github.com)

(Album Cover) links to the crafted open.spotify url resolved through the listenbrainz API
(Title & Artist) link to a crafted to a crafted open.spotify search URL of the respective content.
(Album) has to be the same link as the artwork.

Any reason why we can't try to find title and artist links from LB API as well? Is it a limitation of LB or Spotify?

By the way, where did you find information about these undocumented options?

My initial thoughts on making linking an optional setting in the configuration leads me to enhancing this to offer the user Spotify / YTmusic / etc URLs linked to the items (this was a route I initially went down)

I thought about that as well, we can enhance the plugin later with this functionality

> (Album Cover) links to the crafted open.spotify url resolved through the listenbrainz API > (Title & Artist) link to a crafted to a crafted open.spotify search URL of the respective content. > (Album) has to be the same link as the artwork. Any reason why we can't try to find title and artist links from LB API as well? Is it a limitation of LB or Spotify? By the way, where did you find information about these undocumented options? > My initial thoughts on making linking an optional setting in the configuration leads me to enhancing this to offer the user Spotify / YTmusic / etc URLs linked to the items (this was a route I initially went down) I thought about that as well, we can enhance the plugin later with this functionality
deluan commented 2026-02-23 20:42:34 -07:00 (Migrated from github.com)

Ok, I finished my changes. Let me know what do you think. Once you review it, I'm ready to release it.

Ok, I finished my changes. Let me know what do you think. Once you review it, I'm ready to release it.
Woahai321 commented 2026-02-24 06:02:48 -07:00 (Migrated from github.com)

For the documentation on these abilities I will have to go on a hunt and may not be able to provide exact documentation. for context I also previously built a "music notify" app that pinged the spotify API every 30m for selected artists to send a discord notification about new releases. I recently migrated this to use Deezer but it still delivers the notifications through a discord webhook. I applied some of the logic used in webhook formatting to the presence to see if it would work, and it did, so I think these are undocumented capabilities.

For the documentation on these abilities I will have to go on a hunt and may not be able to provide exact documentation. for context I also previously built a "music notify" app that pinged the spotify API every 30m for selected artists to send a discord notification about new releases. I recently migrated this to use Deezer but it still delivers the notifications through a discord webhook. I applied some of the logic used in webhook formatting to the presence to see if it would work, and it did, so I think these are undocumented capabilities.
deluan commented 2026-02-24 08:17:25 -07:00 (Migrated from github.com)

This PR has the same issue as #12: ListenBrainz calls fails and we can't handle this due to limitations of the Extism http client:

time="2026-02-24T15:11:34Z" level=trace msg="Plugin call failed" error="Post \"https://labs.api.listenbrainz.org/spotify-id-from-mbid/json\": read tcp 172.29.0.3:49264->142.132.240.1:443: read: connection reset by peer (recovered by wazero)\nwasm stack trace:\n\textism:host/env.http_request(i64,i64) i64\n\tmain.(*github.com/extism/go-pdk.HTTPRequest).Send(i32,i32)\n\tmain.github.com/navidrome/navidrome/plugins/pdk/go/scrobbler._NdScrobblerNowPlaying#wasmexport() i32" function=nd_scrobbler_now_playing navidromeDuration="777.559µs" plugin=discord-rich-presence pluginDuration=440.8ms requestId=decdb20eb6d0/s9HBsPKFFE-002887
time="2026-02-24T15:11:34Z" level=error msg="Error sending NowPlayingInfo" artist=DEVO error=unrecoverable requestId=decdb20eb6d0/s9HBsPKFFE-002887 scrobbler=discord-rich-presence track=Fresh

We may need to implement a new HTTP host function in Navidrome for better error handling.

This PR has the same issue as #12: ListenBrainz calls fails and we can't handle this due to limitations of the Extism http client: ``` time="2026-02-24T15:11:34Z" level=trace msg="Plugin call failed" error="Post \"https://labs.api.listenbrainz.org/spotify-id-from-mbid/json\": read tcp 172.29.0.3:49264->142.132.240.1:443: read: connection reset by peer (recovered by wazero)\nwasm stack trace:\n\textism:host/env.http_request(i64,i64) i64\n\tmain.(*github.com/extism/go-pdk.HTTPRequest).Send(i32,i32)\n\tmain.github.com/navidrome/navidrome/plugins/pdk/go/scrobbler._NdScrobblerNowPlaying#wasmexport() i32" function=nd_scrobbler_now_playing navidromeDuration="777.559µs" plugin=discord-rich-presence pluginDuration=440.8ms requestId=decdb20eb6d0/s9HBsPKFFE-002887 time="2026-02-24T15:11:34Z" level=error msg="Error sending NowPlayingInfo" artist=DEVO error=unrecoverable requestId=decdb20eb6d0/s9HBsPKFFE-002887 scrobbler=discord-rich-presence track=Fresh ``` We may need to implement a new HTTP host function in Navidrome for better error handling.
Woahai321 commented 2026-02-24 09:52:12 -07:00 (Migrated from github.com)

Understood thanks for the update

Understood thanks for the update
deluan commented 2026-02-24 12:46:33 -07:00 (Migrated from github.com)

Fixed! Will use this version for a couple of days, to spot any remaining issues, before merging. Please do the same if you can.

Fixed! Will use this version for a couple of days, to spot any remaining issues, before merging. Please do the same if you can.
Woahai321 commented 2026-02-24 14:37:03 -07:00 (Migrated from github.com)

hi looking to test the changes and received the below error on enablement of the plugin.

Error creating instance: instantiating module: "http_send" is not exported in module "extism:host/user"

i assume this is related to the change in http request mechanism can you confirm how to resolve on my end for testing?

hi looking to test the changes and received the below error on enablement of the plugin. `Error creating instance: instantiating module: "http_send" is not exported in module "extism:host/user"` i assume this is related to the change in http request mechanism can you confirm how to resolve on my end for testing?
deluan commented 2026-02-24 14:45:26 -07:00 (Migrated from github.com)

Error creating instance: instantiating module: "http_send" is not exported in module "extism:host/user"

Ah yes, forgot about this. You'll need the latest navidrome from the develop build. The change will be included in the next Navidrome version, due end of next month.

If you prefer not to use the develop build, unfortunately you'll have to wait.

> `Error creating instance: instantiating module: "http_send" is not exported in module "extism:host/user"` Ah yes, forgot about this. You'll need the latest navidrome from the `develop` build. The change will be included in the next Navidrome version, due end of next month. If you prefer not to use the develop build, unfortunately you'll have to wait.
Woahai321 commented 2026-02-24 14:59:47 -07:00 (Migrated from github.com)

ahha makes sense no problem thanks for letting me know.
im due to migrate all my homelab to new hardware this weekend so i shall move to the develop build then and give it a whirl!

ahha makes sense no problem thanks for letting me know. im due to migrate all my homelab to new hardware this weekend so i shall move to the develop build then and give it a whirl!
deluan commented 2026-03-04 10:03:56 -07:00 (Migrated from github.com)

This is working as expected. I'll merge it now, but will only release a new plugin after the next Navidrome release, as this requires the new HTTP host service

This is working as expected. I'll merge it now, but will only release a new plugin after the next Navidrome release, as this requires the new HTTP host service
Sign in to join this conversation.