Compare commits
15 Commits
v1.0.0-beta-1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
72456aa05f
|
|||
|
b5e9822626
|
|||
|
2b096b23ff
|
|||
|
dc64de825c
|
|||
|
6c051734cc
|
|||
|
7de0568bc7
|
|||
|
383789a6a5
|
|||
| a903d6cdea | |||
|
fa381fbc83
|
|||
|
87366781f5
|
|||
| 41cf2971c1 | |||
| 4e0f98aa51 | |||
| e0f3361051 | |||
|
414021f471
|
|||
|
24fb4cf752
|
Binary file not shown.
|
Before Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.1 KiB |
@@ -1,54 +0,0 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
|
||||
- name: Install TinyGo
|
||||
run: |
|
||||
wget https://github.com/tinygo-org/tinygo/releases/download/v0.40.1/tinygo_0.40.1_amd64.deb
|
||||
sudo dpkg -i tinygo_0.40.1_amd64.deb
|
||||
sudo apt install -y binaryen
|
||||
|
||||
- name: Run tests
|
||||
run: make test
|
||||
|
||||
- name: Append PR info to version
|
||||
if: github.event_name == 'pull_request'
|
||||
run: |
|
||||
PR_NUM=${{ github.event.pull_request.number }}
|
||||
SHA=$(echo "${{ github.event.pull_request.head.sha }}" | cut -c1-7)
|
||||
SUFFIX="PR${PR_NUM}-${SHA}"
|
||||
jq --arg suffix "$SUFFIX" '.version = .version + "-" + $suffix' manifest.json > manifest.tmp && mv manifest.tmp manifest.json
|
||||
|
||||
- name: Append git SHA to version
|
||||
if: github.event_name == 'push'
|
||||
run: |
|
||||
SHA=$(echo "${{ github.sha }}" | cut -c1-7)
|
||||
jq --arg sha "$SHA" '.version = .version + "-" + $sha' manifest.json > manifest.tmp && mv manifest.tmp manifest.json
|
||||
|
||||
- name: Build and package plugin
|
||||
run: make package
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: discord-rich-presence
|
||||
path: discord-rich-presence.ndp
|
||||
@@ -1,89 +0,0 @@
|
||||
name: Create Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: "Release version (e.g., 1.2.3, without the 'v' prefix)"
|
||||
required: true
|
||||
type: string
|
||||
beta:
|
||||
description: "Beta number (1, 2, 3...). Leave empty for stable release"
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
create-release:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Validate version format
|
||||
env:
|
||||
VERSION: ${{ inputs.version }}
|
||||
run: |
|
||||
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "::error::Invalid version format '$VERSION'. Use X.X.X (e.g., 1.2.3)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Compute full version
|
||||
run: |
|
||||
VERSION="${{ inputs.version }}"
|
||||
BETA="${{ inputs.beta }}"
|
||||
if [[ -n "$BETA" && "$BETA" != "0" ]]; then
|
||||
VERSION="${VERSION}-beta-${BETA}"
|
||||
fi
|
||||
echo "VERSION=${VERSION}" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Check tag does not already exist
|
||||
run: |
|
||||
if git ls-remote --tags origin "refs/tags/v${VERSION}" | grep -q .; then
|
||||
echo "::error::Tag v${VERSION} already exists"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
|
||||
- name: Run tests
|
||||
run: go test -race ./...
|
||||
|
||||
- name: Update manifest.json version
|
||||
run: |
|
||||
jq --arg v "$VERSION" '.version = $v' manifest.json > manifest.tmp && mv manifest.tmp manifest.json
|
||||
|
||||
- name: Commit, tag, and push
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add manifest.json
|
||||
git commit --allow-empty -m "Release v${VERSION}"
|
||||
git tag "v${VERSION}"
|
||||
git push origin main "v${VERSION}"
|
||||
|
||||
- name: Install TinyGo
|
||||
run: |
|
||||
wget https://github.com/tinygo-org/tinygo/releases/download/v0.40.1/tinygo_0.40.1_amd64.deb
|
||||
sudo dpkg -i tinygo_0.40.1_amd64.deb
|
||||
sudo apt install -y binaryen
|
||||
|
||||
- name: Build and package plugin
|
||||
run: make package
|
||||
|
||||
- name: Create release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: v${{ env.VERSION }}
|
||||
draft: true
|
||||
prerelease: ${{ inputs.beta != '' && inputs.beta != '0' }}
|
||||
files: discord-rich-presence.ndp
|
||||
generate_release_notes: true
|
||||
@@ -1,38 +0,0 @@
|
||||
name: Add download link to PR
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Build"]
|
||||
types: [completed]
|
||||
|
||||
jobs:
|
||||
pr_comment:
|
||||
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Get PR number
|
||||
id: pr
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const pulls = await github.rest.pulls.list({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
state: 'open'
|
||||
});
|
||||
const pr = pulls.data.find(p => p.head.sha === '${{ github.event.workflow_run.head_sha }}');
|
||||
if (pr) {
|
||||
core.setOutput('number', pr.number);
|
||||
}
|
||||
|
||||
- name: Add download link comment
|
||||
if: steps.pr.outputs.number
|
||||
uses: marocchino/sticky-pull-request-comment@v2
|
||||
with:
|
||||
number: ${{ steps.pr.outputs.number }}
|
||||
message: |
|
||||
Download the plugin for this PR: [discord-rich-presence.zip](https://nightly.link/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}/discord-rich-presence.zip)
|
||||
|
||||
Built from ${{ github.event.workflow_run.head_sha }} on ${{ github.event.workflow_run.updated_at }}
|
||||
+4
-1
@@ -1,4 +1,7 @@
|
||||
*.wasm
|
||||
*.ndp
|
||||
tmp
|
||||
discord-rich-presence
|
||||
|
||||
discordrome
|
||||
.DS_Store
|
||||
.direnv/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
SHELL := /usr/bin/env bash
|
||||
.PHONY: test build package clean
|
||||
|
||||
PLUGIN_NAME := discord-rich-presence
|
||||
PLUGIN_NAME := discodrome
|
||||
WASM_FILE := plugin.wasm
|
||||
TINYGO := $(shell command -v tinygo 2> /dev/null)
|
||||
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
# Discord Rich Presence Plugin for Navidrome
|
||||
# Discodrome, a work of Discord Rich Presence Plugin for Navidrome
|
||||
|
||||
[](https://github.com/navidrome/discord-rich-presence-plugin/actions/workflows/build.yml)
|
||||
[](https://github.com/navidrome/discord-rich-presence-plugin/releases/latest/download/discord-rich-presence.ndp)
|
||||
|
||||
**Attention: This plugin requires Navidrome 0.60.2 or later.**
|
||||
**Attention: This plugin requires Navidrome 0.61.0 or later.**
|
||||
|
||||
This plugin integrates Navidrome with Discord Rich Presence, displaying your currently playing track in your Discord status.
|
||||
The goal is to demonstrate the capabilities of Navidrome's plugin system by implementing a real-time presence feature using Discord's Gateway API.
|
||||
It demonstrates how a Navidrome plugin can maintain real-time connections to external services while remaining completely stateless.
|
||||
|
||||
Based on the [Navicord](https://github.com/logixism/navicord) project.
|
||||
Based on the [discord-rich-presence-plugin](https://github.com/navidrome/discord-rich-presence-plugin) project.
|
||||
|
||||
**⚠️ WARNING: This plugin requires storing Discord user tokens, which may violate Discord's Terms of Service. Use at your own risk.**
|
||||
|
||||
@@ -26,13 +23,12 @@ Based on the [Navicord](https://github.com/logixism/navicord) project.
|
||||
- Optional album art from [Cover Art Archive](https://coverartarchive.org) for MusicBrainz-tagged music
|
||||
- Optional image hosting via [uguu.se](https://uguu.se) for non-public Navidrome instances
|
||||
|
||||
<img alt="Discord Rich Presence showing currently playing track with album art, artist, and playback progress" src="https://raw.githubusercontent.com/navidrome/discord-rich-presence-plugin/master/.github/ss-richpresence.webp">
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
### Step 1: Download and Install the Plugin
|
||||
1. Download the `discord-rich-presence.ndp` file from the [releases page](https://github.com/navidrome/discord-rich-presence-plugin/releases)
|
||||
1. Download the `discodrome.ndp` file from the [releases page](https://git.atri.dad/atridad/discodrome/releases)
|
||||
2. Copy it to your Navidrome plugins folder. Default location: `<navidrome-data-directory>/plugins/`
|
||||
|
||||
### Step 2: Create a Discord Application
|
||||
@@ -115,7 +111,6 @@ For album artwork to display in Discord, Discord needs to be able to access the
|
||||
|
||||
Access the plugin configuration in Navidrome: **Settings > Plugins > Discord Rich Presence**
|
||||
|
||||
<img alt="Plugin configuration panel showing all available settings" src="https://raw.githubusercontent.com/navidrome/discord-rich-presence-plugin/master/.github/ss-config.webp">
|
||||
|
||||
### Configuration Fields
|
||||
|
||||
@@ -249,7 +244,7 @@ make build
|
||||
make package
|
||||
```
|
||||
|
||||
The `make package` command creates `discord-rich-presence.ndp` containing the compiled WebAssembly module and manifest.
|
||||
The `make package` command creates `discodrome.ndp` containing the compiled WebAssembly module and manifest.
|
||||
|
||||
### Manual Build Options
|
||||
|
||||
@@ -257,16 +252,15 @@ The `make package` command creates `discord-rich-presence.ndp` containing the co
|
||||
```sh
|
||||
# Install TinyGo first: https://tinygo.org/getting-started/install/
|
||||
tinygo build -target wasip1 -buildmode=c-shared -o plugin.wasm -scheduler=none .
|
||||
zip discord-rich-presence.ndp plugin.wasm manifest.json
|
||||
zip discodrome.ndp plugin.wasm manifest.json
|
||||
```
|
||||
|
||||
#### Using Standard Go
|
||||
```sh
|
||||
GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o plugin.wasm .
|
||||
zip discord-rich-presence.ndp plugin.wasm manifest.json
|
||||
zip discodrome.ndp plugin.wasm manifest.json
|
||||
```
|
||||
|
||||
### Output
|
||||
- `plugin.wasm`: The compiled WebAssembly module
|
||||
- `discord-rich-presence.ndp`: The complete plugin package ready for installation
|
||||
|
||||
- `discodrome.ndp`: The complete plugin package ready for installation
|
||||
|
||||
Generated
+61
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1775036866,
|
||||
"narHash": "sha256-ZojAnPuCdy657PbTq5V0Y+AHKhZAIwSIT2cb8UgAz/U=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "6201e203d09599479a3b3450ed24fa81537ebc4e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
description = "Discodrome Development Environment";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs =
|
||||
{
|
||||
nixpkgs,
|
||||
flake-utils,
|
||||
self,
|
||||
}:
|
||||
flake-utils.lib.eachDefaultSystem (
|
||||
system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
in
|
||||
{
|
||||
devShells.default = pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
go
|
||||
tinygo
|
||||
gnumake
|
||||
binaryen
|
||||
jq
|
||||
];
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
module discord-rich-presence
|
||||
module discodrome
|
||||
|
||||
go 1.25.0
|
||||
|
||||
require (
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0-20260320221607-03844a9a369a
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0-20260404191800-e7c7cba87374
|
||||
github.com/onsi/ginkgo/v2 v2.28.1
|
||||
github.com/onsi/gomega v1.39.1
|
||||
github.com/stretchr/testify v1.11.1
|
||||
|
||||
@@ -33,8 +33,8 @@ github.com/maruel/natural v1.3.0 h1:VsmCsBmEyrR46RomtgHs5hbKADGRVtliHTyCOLFBpsg=
|
||||
github.com/maruel/natural v1.3.0/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg=
|
||||
github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE=
|
||||
github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A=
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0-20260320221607-03844a9a369a h1:EHllNfhSpL6F3EqM4M0GDHQZb7DyClw0y7afddd8XPg=
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0-20260320221607-03844a9a369a/go.mod h1:5aedoevIXlwUFuR7kbd/WkjaiLg87D3XUFRGIwDBroo=
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0-20260404191800-e7c7cba87374 h1:JzllgppjaCE7sh+v1eGYlA5RuMyvNo5pNsUNuI0Oqy4=
|
||||
github.com/navidrome/navidrome/plugins/pdk/go v0.0.0-20260404191800-e7c7cba87374/go.mod h1:5aedoevIXlwUFuR7kbd/WkjaiLg87D3XUFRGIwDBroo=
|
||||
github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI=
|
||||
github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE=
|
||||
github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28=
|
||||
|
||||
@@ -25,12 +25,13 @@ import (
|
||||
|
||||
// Configuration keys
|
||||
const (
|
||||
clientIDKey = "clientid"
|
||||
usersKey = "users"
|
||||
activityNameKey = "activityname"
|
||||
spotifyLinksKey = "spotifylinks"
|
||||
caaEnabledKey = "caaenabled"
|
||||
uguuEnabledKey = "uguuenabled"
|
||||
clientIDKey = "clientid"
|
||||
usersKey = "users"
|
||||
activityNameKey = "activityname"
|
||||
activityNameTemplateKey = "activitynametemplate"
|
||||
spotifyLinksKey = "spotifylinks"
|
||||
caaEnabledKey = "caaenabled"
|
||||
uguuEnabledKey = "uguuenabled"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -47,6 +48,7 @@ const (
|
||||
activityNameTrack = "Track"
|
||||
activityNameArtist = "Artist"
|
||||
activityNameAlbum = "Album"
|
||||
activityNameCustom = "Custom"
|
||||
)
|
||||
|
||||
// userToken represents a user-token mapping from the config
|
||||
@@ -170,6 +172,16 @@ func (p *discordPlugin) NowPlaying(input scrobbler.NowPlayingRequest) error {
|
||||
case activityNameArtist:
|
||||
activityName = input.Track.Artist
|
||||
statusDisplayType = statusDisplayName
|
||||
case activityNameCustom:
|
||||
template, _ := pdk.GetConfig(activityNameTemplateKey)
|
||||
if template != "" {
|
||||
r := strings.NewReplacer(
|
||||
"{track}", input.Track.Title,
|
||||
"{artist}", input.Track.Artist,
|
||||
"{album}", input.Track.Album,
|
||||
)
|
||||
activityName = r.Replace(template)
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve Spotify URLs if enabled
|
||||
|
||||
@@ -225,6 +225,62 @@ var _ = Describe("discordPlugin", func() {
|
||||
Entry("uses track album when configured", "Album", true, "Test Album", 0),
|
||||
Entry("uses track artist when configured", "Artist", true, "Test Artist", 0),
|
||||
)
|
||||
|
||||
DescribeTable("custom activity name template",
|
||||
func(template string, templateExists bool, expectedName string) {
|
||||
pdk.PDKMock.On("GetConfig", clientIDKey).Return("test-client-id", true)
|
||||
pdk.PDKMock.On("GetConfig", usersKey).Return(`[{"username":"testuser","token":"test-token"}]`, true)
|
||||
pdk.PDKMock.On("GetConfig", uguuEnabledKey).Return("", false)
|
||||
pdk.PDKMock.On("GetConfig", activityNameKey).Return("Custom", true)
|
||||
pdk.PDKMock.On("GetConfig", activityNameTemplateKey).Return(template, templateExists)
|
||||
pdk.PDKMock.On("GetConfig", spotifyLinksKey).Return("", false)
|
||||
|
||||
// Connect mocks
|
||||
host.CacheMock.On("GetInt", "discord.seq.testuser").Return(int64(0), false, errors.New("not found"))
|
||||
gatewayResp := []byte(`{"url":"wss://gateway.discord.gg"}`)
|
||||
host.HTTPMock.On("Send", mock.MatchedBy(func(req host.HTTPRequest) bool {
|
||||
return req.Method == "GET" && req.URL == "https://discord.com/api/gateway"
|
||||
})).Return(&host.HTTPResponse{StatusCode: 200, Body: gatewayResp}, nil)
|
||||
host.WebSocketMock.On("Connect", mock.MatchedBy(func(url string) bool {
|
||||
return strings.Contains(url, "gateway.discord.gg")
|
||||
}), mock.Anything, "testuser").Return("testuser", nil)
|
||||
|
||||
// Capture the activity payload sent to Discord
|
||||
var sentPayload string
|
||||
host.WebSocketMock.On("SendText", "testuser", mock.Anything).Run(func(args mock.Arguments) {
|
||||
sentPayload = args.Get(1).(string)
|
||||
}).Return(nil)
|
||||
host.SchedulerMock.On("ScheduleRecurring", mock.Anything, payloadHeartbeat, "testuser").Return("testuser", nil)
|
||||
host.SchedulerMock.On("CancelSchedule", "testuser-clear").Return(nil)
|
||||
|
||||
// Image mocks
|
||||
host.CacheMock.On("GetString", discordImageKey).Return("", false, nil)
|
||||
host.CacheMock.On("SetString", discordImageKey, mock.Anything, mock.Anything).Return(nil)
|
||||
host.ArtworkMock.On("GetTrackUrl", "track1", int32(300)).Return("https://example.com/art.jpg", nil)
|
||||
host.HTTPMock.On("Send", externalAssetsReq).Return(&host.HTTPResponse{StatusCode: 200, Body: []byte(`{}`)}, nil)
|
||||
host.SchedulerMock.On("ScheduleOneTime", mock.Anything, payloadClearActivity, "testuser-clear").Return("testuser-clear", nil)
|
||||
|
||||
err := plugin.NowPlaying(scrobbler.NowPlayingRequest{
|
||||
Username: "testuser",
|
||||
Position: 10,
|
||||
Track: scrobbler.TrackInfo{
|
||||
ID: "track1",
|
||||
Title: "Test Song",
|
||||
Artist: "Test Artist",
|
||||
Album: "Test Album",
|
||||
Duration: 180,
|
||||
},
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(sentPayload).To(ContainSubstring(fmt.Sprintf(`"name":"%s"`, expectedName)))
|
||||
},
|
||||
Entry("uses custom template with all placeholders", "{artist} - {track} ({album})", true, "Test Artist - Test Song (Test Album)"),
|
||||
Entry("uses custom template with only track", "{track}", true, "Test Song"),
|
||||
Entry("uses custom template with only artist", "{artist}", true, "Test Artist"),
|
||||
Entry("uses custom template with only album", "{album}", true, "Test Album"),
|
||||
Entry("uses custom template with plain text", "Now Playing", true, "Now Playing"),
|
||||
Entry("falls back to Navidrome when template is empty", "", false, "Navidrome"),
|
||||
)
|
||||
})
|
||||
|
||||
Describe("Scrobble", func() {
|
||||
|
||||
+27
-21
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/navidrome/navidrome/refs/heads/master/plugins/manifest-schema.json",
|
||||
"name": "Discord Rich Presence",
|
||||
"author": "Navidrome Team",
|
||||
"version": "1.0.0-beta-1",
|
||||
"name": "Discodrome",
|
||||
"author": "Atridad Lahiji",
|
||||
"version": "1.1.1",
|
||||
"description": "Discord Rich Presence integration for Navidrome",
|
||||
"website": "https://github.com/navidrome/discord-rich-presence-plugin",
|
||||
"website": "https://git.atri.dad/atridad/discodrome",
|
||||
"permissions": {
|
||||
"users": {
|
||||
"reason": "To process scrobbles on behalf of users"
|
||||
@@ -20,9 +20,7 @@
|
||||
},
|
||||
"websocket": {
|
||||
"reason": "To maintain real-time connection with Discord gateway",
|
||||
"requiredHosts": [
|
||||
"gateway.discord.gg"
|
||||
]
|
||||
"requiredHosts": ["gateway.discord.gg"]
|
||||
},
|
||||
"cache": {
|
||||
"reason": "To store connection state and sequence numbers"
|
||||
@@ -53,14 +51,15 @@
|
||||
"type": "string",
|
||||
"title": "Activity Name Display",
|
||||
"description": "Choose what to display as the activity name in Discord Rich Presence",
|
||||
"enum": [
|
||||
"Default",
|
||||
"Track",
|
||||
"Album",
|
||||
"Artist"
|
||||
],
|
||||
"enum": ["Default", "Track", "Album", "Artist", "Custom"],
|
||||
"default": "Default"
|
||||
},
|
||||
"activitynametemplate": {
|
||||
"type": "string",
|
||||
"title": "Custom Activity Name Template",
|
||||
"description": "Template for the activity name. Available placeholders: {track}, {artist}, {album}",
|
||||
"default": "{artist} - {track}"
|
||||
},
|
||||
"caaenabled": {
|
||||
"type": "boolean",
|
||||
"title": "Use artwork from Cover Art Archive (for MusicBrainz-tagged music)",
|
||||
@@ -99,17 +98,11 @@
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"username",
|
||||
"token"
|
||||
]
|
||||
"required": ["username", "token"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"clientid",
|
||||
"users"
|
||||
]
|
||||
"required": ["clientid", "users"]
|
||||
},
|
||||
"uiSchema": {
|
||||
"type": "VerticalLayout",
|
||||
@@ -125,6 +118,19 @@
|
||||
"format": "radio"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Control",
|
||||
"scope": "#/properties/activitynametemplate",
|
||||
"rule": {
|
||||
"effect": "SHOW",
|
||||
"condition": {
|
||||
"scope": "#/properties/activityname",
|
||||
"schema": {
|
||||
"const": "Custom"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Control",
|
||||
"scope": "#/properties/caaenabled"
|
||||
|
||||
Reference in New Issue
Block a user