Skip to content

Commit 64f9754

Browse files
Merge pull request #29 from sdasda7777/sdasda7777_staticOverrides
Implemented static overrides
2 parents 1bd41ba + d744f18 commit 64f9754

File tree

6 files changed

+140
-22
lines changed

6 files changed

+140
-22
lines changed

config/dummy

Whitespace-only changes.

src/helpers/configs/default_config.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,14 @@ module.exports = {
3434
// How frequently in milliseconds to check for updates
3535
updateInterval: 1000,
3636

37-
// Preferred provider of the album artwork
38-
// Supported: "apple", "bandcamp", "deezer", "qobuz", "spotify", "soundcloud" and "tidal"
39-
// Use "musichoarders" to use closest fit from all services above
40-
whereToFetchOnline: "musichoarders",
37+
// Preferred provider of the album artwork. Supported values
38+
// "staticoverrides" (for values from `config/staticoverrides.js`)
39+
// "musichoarders" (for closest fit from servicese below)
40+
// "apple", "bandcamp", "deezer", "qobuz", "spotify", "soundcloud" and "tidal"
41+
whereToFetchOnline: "staticoverrides",
4142

4243
// Preferred provider of the rpc button (as above + "youtube")
43-
changeButtonProvider: "spotify",
44+
changeButtonProvider: "staticoverrides",
4445

4546
// Whether to use persistent cache for MusicHoarders queries
4647
persistentMusicHoardersCache: false,
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
2+
// Include your static overrides here
3+
// Override's key may use album artist name or album name, most specific combination being used first
4+
// Override's value must contain artworkFrom and artworkUrl or joinFrom and joinUrl or all four
5+
// For example:
6+
/*
7+
module.exports = [
8+
{key: {albumArtist: "Artist1", albumName: "Album1"},
9+
value: {artworkFrom: "Example1", artworkUrl: "example1.jpg", joinFrom: "Example1", joinUrl: "example1"}},
10+
11+
{key: {albumName: "Album2"},
12+
value: {joinUrl: "example2a"}},
13+
{key: {albumArtist: "Artist1", albumName: "Album2"},
14+
value: {artworkFrom: "Example2b", artworkUrl: "example2b.jpg", joinFrom: "Example2b", joinUrl: "example2b"}},
15+
16+
{key: {albumArtist: "Artist1"},
17+
value: {artworkFrom: "Example3", artworkUrl: "example3.jpg"}},
18+
19+
{key: {albumName: "Album4"},
20+
value: {joinFrom: "Example4", joinUrl: "example4.jpg"}},
21+
]
22+
*/
23+
// will return:
24+
25+
// for "Album1" by "Artist1":
26+
// {artworkFrom: "Example1", artworkUrl: "example1.jpg", joinFrom: "Example1", joinUrl: "example1"}
27+
// (no tricks here, the key is an exact match)
28+
29+
// for "Album2" by "Artist1":
30+
// {artworkFrom: "Example2b", artworkUrl: "example2b.jpg", joinFrom: "Example2b", joinUrl: "example2b"}
31+
// (because the most specific key is used first)
32+
33+
// for "Album3" by "Artist1":
34+
// {fetchedFrom: "Example3", artworkUrl: "example3.jpg"}
35+
// (because it is the best match for given album)
36+
37+
// for "Album4" by "Artist1":
38+
// {artworkFrom: "Example3", artworkUrl: "example3.jpg", joinFrom: "Example4", joinUrl: "example4.jpg"}
39+
// (partial matches for "Album4" and "Artist1" get combined)
40+
41+
42+
module.exports = [
43+
44+
]

src/rpc/format.js

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55

66
const fs = require('fs');
77
const log = require('../helpers/lager.js');
8-
const config = require('../helpers/configLoader.js').getOrInit('config.js');
8+
const cl = require('../helpers/configLoader.js');
9+
const config = cl.getOrInit('config.js');
910
const axios = require('axios');
1011
const yt = require("ytsr");
1112
const path = require("path");
1213

14+
let staticOverridesFetcher = new (require('./staticOverridesFetcher.js'))(cl.getOrInit('staticoverrides.js'));
1315
let musichoardersFetcher = new (require('./musichoardersFetcher.js'))(config.rpc.persistentMusicHoardersCache);
1416

1517
// These functions, 'fetchers', provide uniform inteface for simple access to the APIs
@@ -18,6 +20,12 @@ let musichoardersFetcher = new (require('./musichoardersFetcher.js'))(config.rpc
1820
// In order to be as simple as possible, the functions may throw exceptions or not return anything.
1921
// They are expected to be called through the `fetchSafely()` wrapper.
2022
const fetchers = {
23+
"staticoverrides": async (metadata) => {
24+
return staticOverridesFetcher.fetch(metadata);
25+
},
26+
"musichoarders": async (metadata) => {
27+
return musichoardersFetcher.fetch("musichoarders", metadata);
28+
},
2129
"apple": async (metadata) => { // Doesn't rely on MusicHoarders, keep it that way, just in case
2230
if ((metadata.ALBUMARTIST || metadata.artist) && metadata.title)
2331
{
@@ -31,8 +39,9 @@ const fetchers = {
3139
if (result.data.resultCount > 0 && result.data.results[0] !== undefined)
3240
{
3341
return {
34-
fetchedFrom: "Apple Music",
42+
artworkFrom: "Apple Music",
3543
artworkUrl: result.data.results[0].artworkUrl100,
44+
joinFrom: "Apple Music",
3645
joinUrl: result.data.results[0].trackViewUrl
3746
};
3847
}
@@ -44,9 +53,6 @@ const fetchers = {
4453
"deezer": async (metadata) => {
4554
return musichoardersFetcher.fetch("deezer", metadata);
4655
},
47-
"musichoarders": async (metadata) => {
48-
return musichoardersFetcher.fetch("musichoarders", metadata);
49-
},
5056
"qobuz": async (metadata) => {
5157
return musichoardersFetcher.fetch("qobuz", metadata);
5258
},
@@ -64,8 +70,9 @@ const fetchers = {
6470
if (result.items.length > 0)
6571
{
6672
return {
67-
fetchedFrom: "Youtube",
73+
artworkFrom: undefined,
6874
artworkUrl: undefined,
75+
joinFrom: "Youtube",
6976
joinUrl: result.items[0].url
7077
};
7178
}
@@ -76,7 +83,7 @@ const fetchers = {
7683
* Safe wrapper for calling a fetcher in try-catch block
7784
* @param {string} fetcherName name of the fetcher to use
7885
* @param {Object} metadata VLC metadata
79-
* @returns {!{fetchedFrom: string, artworkUrl: string, joinUrl: string}}
86+
* @returns {!{artworkFrom: ?string, artworkUrl: ?string, joinFrom: ?string, joinUrl: ?string}}
8087
*/
8188
async function fetchSafely(fetcherName, metadata)
8289
{
@@ -100,19 +107,19 @@ async function fetchSafely(fetcherName, metadata)
100107
* @param {string} preferredArtworkProvider name of preferred artwork fetcher
101108
* @param {string} preferredJoinProvider name of preferred join fetcher
102109
* @param {Object} metadata VLC metadata
103-
* @returns {!{artworkUrl: string, artworkFrom: string, joinUrl: string, joinFrom: string}}
110+
* @returns {!{artworkFrom: ?string, artworkUrl: ?string, joinFrom: ?string, joinUrl: ?string}}
104111
*/
105112
async function combinedFetch(preferredArtworkProvider, preferredJoinProvider, metadata)
106113
{
107-
let artworkUrl, artworkFrom, joinUrl, joinFrom;
114+
let artworkFrom, artworkUrl, joinFrom, joinUrl;
108115
let results = [];
109116

110117
// First try fetching artwork URL using preferred provider
111118
results[preferredArtworkProvider] = await fetchSafely(preferredArtworkProvider, metadata);
112119
if(results[preferredArtworkProvider].artworkUrl)
113120
{
121+
artworkFrom = results[preferredArtworkProvider].artworkFrom;
114122
artworkUrl = results[preferredArtworkProvider].artworkUrl;
115-
artworkFrom = results[preferredArtworkProvider].fetchedFrom;
116123
}
117124

118125
// Next try fetching join URL from preferred provider
@@ -123,20 +130,20 @@ async function combinedFetch(preferredArtworkProvider, preferredJoinProvider, me
123130
// Set it separately, in case both preferred providers are the same
124131
if (results[preferredJoinProvider].joinUrl)
125132
{
133+
joinFrom = results[preferredJoinProvider].joinFrom;
126134
joinUrl = results[preferredJoinProvider].joinUrl;
127-
joinFrom = results[preferredJoinProvider].fetchedFrom;
128135
}
129136

130137
// Try using preferred join provider as a backup artwork provider and vice versa
131138
if (!artworkUrl && results[preferredJoinProvider].artworkUrl)
132139
{
140+
artworkFrom = results[preferredJoinProvider].artworkFrom;
133141
artworkUrl = results[preferredJoinProvider].artworkUrl;
134-
artworkFrom = results[preferredJoinProvider].fetchedFrom;
135142
}
136143
if (!joinUrl && results[preferredArtworkProvider].joinUrl)
137144
{
145+
joinFrom = results[preferredArtworkProvider].joinFrom;
138146
joinUrl = results[preferredArtworkProvider].joinUrl;
139-
joinFrom = results[preferredArtworkProvider].fetchedFrom;
140147
}
141148

142149
// In case either still isn't set, iterate all other providers
@@ -148,13 +155,13 @@ async function combinedFetch(preferredArtworkProvider, preferredJoinProvider, me
148155
results[availableProviderNames[ii]] = await fetchSafely(availableProviderNames[ii], metadata);
149156
if(!artworkUrl && results[availableProviderNames[ii]].artworkUrl)
150157
{
158+
artworkFrom = results[availableProviderNames[ii]].artworkFrom;
151159
artworkUrl = results[availableProviderNames[ii]].artworkUrl;
152-
artworkFrom = results[availableProviderNames[ii]].fetchedFrom;
153160
}
154161
if (!joinUrl && results[availableProviderNames[ii]].joinUrl)
155162
{
163+
joinFrom = results[availableProviderNames[ii]].joinFrom;
156164
joinUrl = results[availableProviderNames[ii]].joinUrl;
157-
joinFrom = results[availableProviderNames[ii]].fetchedFrom;
158165
}
159166
}
160167
}

src/rpc/musichoardersFetcher.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class MusicHoardersFetcher
8686
* Fetch artwork and join URLs if not cached, otherwise return cached
8787
* @param {string} service service name, e.g. "spotify"
8888
* @param {Object} metadata VLC metadata
89-
* @returns {?{fetchedFrom: string, artworkUrl: string, joinUrl: string}}
89+
* @returns {?{artworkFrom: ?string, artworkUrl: ?string, joinFrom: ?string, joinUrl: ?string}}
9090
*/
9191
async fetch(service, metadata)
9292
{
@@ -152,8 +152,9 @@ class MusicHoardersFetcher
152152
for (let serviceKey in bestResults)
153153
{
154154
bestResults[serviceKey] = {
155-
fetchedFrom: MusicHoardersFetcher.#services[bestResults[serviceKey].album.source],
155+
artworkFrom: MusicHoardersFetcher.#services[bestResults[serviceKey].album.source],
156156
artworkUrl: bestResults[serviceKey].album.smallCoverUrl,
157+
joinFrom: MusicHoardersFetcher.#services[bestResults[serviceKey].album.source],
157158
joinUrl: bestResults[serviceKey].album.releaseInfo.url,
158159
};
159160
};

src/rpc/staticOverridesFetcher.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
2+
/**
3+
* Fetcher of static overrides
4+
*/
5+
class StaticOverridesFetcher
6+
{
7+
/** @type {!Object} #data structure for storing the lookup data */
8+
#data = {};
9+
10+
constructor(rawData)
11+
{
12+
for (let v of rawData)
13+
{
14+
// Use key stringified with sorted keys
15+
this.#data[JSON.stringify(v.key, Object.keys(v.key).sort())] = v.value;
16+
}
17+
}
18+
19+
/**
20+
* @param {!Object} VLC metadata
21+
* @returns {!{artworkFrom: ?string, artworkUrl: ?string, joinFrom: ?string, joinUrl: ?string}}
22+
*/
23+
fetch(metadata)
24+
{
25+
let result = {};
26+
27+
for (let v of StaticOverridesFetcher.createPowerset(metadata.ALBUMARTIST || metadata.artist,
28+
metadata.album))
29+
{
30+
let lookup_result = this.#data[JSON.stringify(v)];
31+
32+
if (lookup_result)
33+
{
34+
if (!result.artworkUrl && lookup_result.artworkUrl)
35+
{
36+
result.artworkFrom = lookup_result.artworkFrom;
37+
result.artworkUrl = lookup_result.artworkUrl;
38+
}
39+
if (!result.joinUrl && lookup_result.joinUrl)
40+
{
41+
result.joinFrom = lookup_result.joinFrom;
42+
result.joinUrl = lookup_result.joinUrl;
43+
}
44+
}
45+
}
46+
47+
return result;
48+
}
49+
50+
static createPowerset(albumArtist, albumName)
51+
{
52+
let result = [];
53+
54+
if (albumArtist && albumName)
55+
result.push({albumArtist, albumName});
56+
if (albumArtist)
57+
result.push({albumArtist});
58+
if (albumName)
59+
result.push({albumName});
60+
61+
return result;
62+
}
63+
}
64+
65+
module.exports = StaticOverridesFetcher;

0 commit comments

Comments
 (0)