Skip to content

Commit

Permalink
Merge pull request #29 from sdasda7777/sdasda7777_staticOverrides
Browse files Browse the repository at this point in the history
Implemented static overrides
  • Loading branch information
greendoescode authored Aug 3, 2023
2 parents 1bd41ba + d744f18 commit 64f9754
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 22 deletions.
Empty file added config/dummy
Empty file.
11 changes: 6 additions & 5 deletions src/helpers/configs/default_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,14 @@ module.exports = {
// How frequently in milliseconds to check for updates
updateInterval: 1000,

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

// Preferred provider of the rpc button (as above + "youtube")
changeButtonProvider: "spotify",
changeButtonProvider: "staticoverrides",

// Whether to use persistent cache for MusicHoarders queries
persistentMusicHoardersCache: false,
Expand Down
44 changes: 44 additions & 0 deletions src/helpers/configs/default_staticoverrides.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

// Include your static overrides here
// Override's key may use album artist name or album name, most specific combination being used first
// Override's value must contain artworkFrom and artworkUrl or joinFrom and joinUrl or all four
// For example:
/*
module.exports = [
{key: {albumArtist: "Artist1", albumName: "Album1"},
value: {artworkFrom: "Example1", artworkUrl: "example1.jpg", joinFrom: "Example1", joinUrl: "example1"}},
{key: {albumName: "Album2"},
value: {joinUrl: "example2a"}},
{key: {albumArtist: "Artist1", albumName: "Album2"},
value: {artworkFrom: "Example2b", artworkUrl: "example2b.jpg", joinFrom: "Example2b", joinUrl: "example2b"}},
{key: {albumArtist: "Artist1"},
value: {artworkFrom: "Example3", artworkUrl: "example3.jpg"}},
{key: {albumName: "Album4"},
value: {joinFrom: "Example4", joinUrl: "example4.jpg"}},
]
*/
// will return:

// for "Album1" by "Artist1":
// {artworkFrom: "Example1", artworkUrl: "example1.jpg", joinFrom: "Example1", joinUrl: "example1"}
// (no tricks here, the key is an exact match)

// for "Album2" by "Artist1":
// {artworkFrom: "Example2b", artworkUrl: "example2b.jpg", joinFrom: "Example2b", joinUrl: "example2b"}
// (because the most specific key is used first)

// for "Album3" by "Artist1":
// {fetchedFrom: "Example3", artworkUrl: "example3.jpg"}
// (because it is the best match for given album)

// for "Album4" by "Artist1":
// {artworkFrom: "Example3", artworkUrl: "example3.jpg", joinFrom: "Example4", joinUrl: "example4.jpg"}
// (partial matches for "Album4" and "Artist1" get combined)


module.exports = [

]
37 changes: 22 additions & 15 deletions src/rpc/format.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@

const fs = require('fs');
const log = require('../helpers/lager.js');
const config = require('../helpers/configLoader.js').getOrInit('config.js');
const cl = require('../helpers/configLoader.js');
const config = cl.getOrInit('config.js');
const axios = require('axios');
const yt = require("ytsr");
const path = require("path");

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

// These functions, 'fetchers', provide uniform inteface for simple access to the APIs
Expand All @@ -18,6 +20,12 @@ let musichoardersFetcher = new (require('./musichoardersFetcher.js'))(config.rpc
// In order to be as simple as possible, the functions may throw exceptions or not return anything.
// They are expected to be called through the `fetchSafely()` wrapper.
const fetchers = {
"staticoverrides": async (metadata) => {
return staticOverridesFetcher.fetch(metadata);
},
"musichoarders": async (metadata) => {
return musichoardersFetcher.fetch("musichoarders", metadata);
},
"apple": async (metadata) => { // Doesn't rely on MusicHoarders, keep it that way, just in case
if ((metadata.ALBUMARTIST || metadata.artist) && metadata.title)
{
Expand All @@ -31,8 +39,9 @@ const fetchers = {
if (result.data.resultCount > 0 && result.data.results[0] !== undefined)
{
return {
fetchedFrom: "Apple Music",
artworkFrom: "Apple Music",
artworkUrl: result.data.results[0].artworkUrl100,
joinFrom: "Apple Music",
joinUrl: result.data.results[0].trackViewUrl
};
}
Expand All @@ -44,9 +53,6 @@ const fetchers = {
"deezer": async (metadata) => {
return musichoardersFetcher.fetch("deezer", metadata);
},
"musichoarders": async (metadata) => {
return musichoardersFetcher.fetch("musichoarders", metadata);
},
"qobuz": async (metadata) => {
return musichoardersFetcher.fetch("qobuz", metadata);
},
Expand All @@ -64,8 +70,9 @@ const fetchers = {
if (result.items.length > 0)
{
return {
fetchedFrom: "Youtube",
artworkFrom: undefined,
artworkUrl: undefined,
joinFrom: "Youtube",
joinUrl: result.items[0].url
};
}
Expand All @@ -76,7 +83,7 @@ const fetchers = {
* Safe wrapper for calling a fetcher in try-catch block
* @param {string} fetcherName name of the fetcher to use
* @param {Object} metadata VLC metadata
* @returns {!{fetchedFrom: string, artworkUrl: string, joinUrl: string}}
* @returns {!{artworkFrom: ?string, artworkUrl: ?string, joinFrom: ?string, joinUrl: ?string}}
*/
async function fetchSafely(fetcherName, metadata)
{
Expand All @@ -100,19 +107,19 @@ async function fetchSafely(fetcherName, metadata)
* @param {string} preferredArtworkProvider name of preferred artwork fetcher
* @param {string} preferredJoinProvider name of preferred join fetcher
* @param {Object} metadata VLC metadata
* @returns {!{artworkUrl: string, artworkFrom: string, joinUrl: string, joinFrom: string}}
* @returns {!{artworkFrom: ?string, artworkUrl: ?string, joinFrom: ?string, joinUrl: ?string}}
*/
async function combinedFetch(preferredArtworkProvider, preferredJoinProvider, metadata)
{
let artworkUrl, artworkFrom, joinUrl, joinFrom;
let artworkFrom, artworkUrl, joinFrom, joinUrl;
let results = [];

// First try fetching artwork URL using preferred provider
results[preferredArtworkProvider] = await fetchSafely(preferredArtworkProvider, metadata);
if(results[preferredArtworkProvider].artworkUrl)
{
artworkFrom = results[preferredArtworkProvider].artworkFrom;
artworkUrl = results[preferredArtworkProvider].artworkUrl;
artworkFrom = results[preferredArtworkProvider].fetchedFrom;
}

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

// Try using preferred join provider as a backup artwork provider and vice versa
if (!artworkUrl && results[preferredJoinProvider].artworkUrl)
{
artworkFrom = results[preferredJoinProvider].artworkFrom;
artworkUrl = results[preferredJoinProvider].artworkUrl;
artworkFrom = results[preferredJoinProvider].fetchedFrom;
}
if (!joinUrl && results[preferredArtworkProvider].joinUrl)
{
joinFrom = results[preferredArtworkProvider].joinFrom;
joinUrl = results[preferredArtworkProvider].joinUrl;
joinFrom = results[preferredArtworkProvider].fetchedFrom;
}

// In case either still isn't set, iterate all other providers
Expand All @@ -148,13 +155,13 @@ async function combinedFetch(preferredArtworkProvider, preferredJoinProvider, me
results[availableProviderNames[ii]] = await fetchSafely(availableProviderNames[ii], metadata);
if(!artworkUrl && results[availableProviderNames[ii]].artworkUrl)
{
artworkFrom = results[availableProviderNames[ii]].artworkFrom;
artworkUrl = results[availableProviderNames[ii]].artworkUrl;
artworkFrom = results[availableProviderNames[ii]].fetchedFrom;
}
if (!joinUrl && results[availableProviderNames[ii]].joinUrl)
{
joinFrom = results[availableProviderNames[ii]].joinFrom;
joinUrl = results[availableProviderNames[ii]].joinUrl;
joinFrom = results[availableProviderNames[ii]].fetchedFrom;
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/rpc/musichoardersFetcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class MusicHoardersFetcher
* Fetch artwork and join URLs if not cached, otherwise return cached
* @param {string} service service name, e.g. "spotify"
* @param {Object} metadata VLC metadata
* @returns {?{fetchedFrom: string, artworkUrl: string, joinUrl: string}}
* @returns {?{artworkFrom: ?string, artworkUrl: ?string, joinFrom: ?string, joinUrl: ?string}}
*/
async fetch(service, metadata)
{
Expand Down Expand Up @@ -152,8 +152,9 @@ class MusicHoardersFetcher
for (let serviceKey in bestResults)
{
bestResults[serviceKey] = {
fetchedFrom: MusicHoardersFetcher.#services[bestResults[serviceKey].album.source],
artworkFrom: MusicHoardersFetcher.#services[bestResults[serviceKey].album.source],
artworkUrl: bestResults[serviceKey].album.smallCoverUrl,
joinFrom: MusicHoardersFetcher.#services[bestResults[serviceKey].album.source],
joinUrl: bestResults[serviceKey].album.releaseInfo.url,
};
};
Expand Down
65 changes: 65 additions & 0 deletions src/rpc/staticOverridesFetcher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@

/**
* Fetcher of static overrides
*/
class StaticOverridesFetcher
{
/** @type {!Object} #data structure for storing the lookup data */
#data = {};

constructor(rawData)
{
for (let v of rawData)
{
// Use key stringified with sorted keys
this.#data[JSON.stringify(v.key, Object.keys(v.key).sort())] = v.value;
}
}

/**
* @param {!Object} VLC metadata
* @returns {!{artworkFrom: ?string, artworkUrl: ?string, joinFrom: ?string, joinUrl: ?string}}
*/
fetch(metadata)
{
let result = {};

for (let v of StaticOverridesFetcher.createPowerset(metadata.ALBUMARTIST || metadata.artist,
metadata.album))
{
let lookup_result = this.#data[JSON.stringify(v)];

if (lookup_result)
{
if (!result.artworkUrl && lookup_result.artworkUrl)
{
result.artworkFrom = lookup_result.artworkFrom;
result.artworkUrl = lookup_result.artworkUrl;
}
if (!result.joinUrl && lookup_result.joinUrl)
{
result.joinFrom = lookup_result.joinFrom;
result.joinUrl = lookup_result.joinUrl;
}
}
}

return result;
}

static createPowerset(albumArtist, albumName)
{
let result = [];

if (albumArtist && albumName)
result.push({albumArtist, albumName});
if (albumArtist)
result.push({albumArtist});
if (albumName)
result.push({albumName});

return result;
}
}

module.exports = StaticOverridesFetcher;

0 comments on commit 64f9754

Please sign in to comment.