.link resolver

This commit is contained in:
afkarxyz
2026-04-02 10:14:49 +07:00
parent e74ac07afc
commit cfcb890469
6 changed files with 115 additions and 14 deletions
+32
View File
@@ -4,6 +4,7 @@ import (
"encoding/json"
"os"
"path/filepath"
"strings"
)
func GetDefaultMusicPath() string {
@@ -67,3 +68,34 @@ func GetSpotFetchAPISettings() (bool, string) {
return true, apiURL
}
func GetLinkResolverSetting() string {
settings, err := LoadConfigSettings()
if err != nil || settings == nil {
return linkResolverProviderSongstats
}
resolver, _ := settings["linkResolver"].(string)
switch strings.TrimSpace(strings.ToLower(resolver)) {
case "songlink", linkResolverProviderDeezerSongLink:
return linkResolverProviderDeezerSongLink
case "", "songstats":
return linkResolverProviderSongstats
default:
return linkResolverProviderSongstats
}
}
func GetLinkResolverAllowFallback() bool {
settings, err := LoadConfigSettings()
if err != nil || settings == nil {
return true
}
allowFallback, ok := settings["allowResolverFallback"].(bool)
if !ok {
return true
}
return allowFallback
}
+27 -14
View File
@@ -30,32 +30,23 @@ func (s *SongLinkClient) resolveSpotifyTrackLinks(spotifyTrackID string, region
}
if links.ISRC != "" {
resolvers := prioritizeProviders("link_resolver", []string{
linkResolverProviderSongstats,
linkResolverProviderDeezerSongLink,
})
resolvers := orderedLinkResolvers()
for _, resolver := range resolvers {
switch resolver {
case linkResolverProviderSongstats:
addedData, songstatsErr := s.resolveLinksViaSongstats(links)
if addedData {
recordProviderSuccess("link_resolver", linkResolverProviderSongstats)
} else if songstatsErr != nil {
recordProviderFailure("link_resolver", linkResolverProviderSongstats)
}
if songstatsErr != nil {
attempts = append(attempts, fmt.Sprintf("songstats: %v", songstatsErr))
} else if addedData {
fmt.Println("Using Songstats as configured link resolver")
}
case linkResolverProviderDeezerSongLink:
addedData, deezerSongLinkErr := s.resolveLinksViaDeezerSongLink(links, region)
if addedData {
recordProviderSuccess("link_resolver", linkResolverProviderDeezerSongLink)
} else if deezerSongLinkErr != nil {
recordProviderFailure("link_resolver", linkResolverProviderDeezerSongLink)
}
if deezerSongLinkErr != nil {
attempts = append(attempts, fmt.Sprintf("deezer-songlink: %v", deezerSongLinkErr))
} else if addedData {
fmt.Println("Using Songlink as configured link resolver")
}
}
@@ -76,6 +67,28 @@ func (s *SongLinkClient) resolveSpotifyTrackLinks(spotifyTrackID string, region
return links, errors.New(strings.Join(attempts, " | "))
}
func orderedLinkResolvers() []string {
preferred := GetLinkResolverSetting()
if !GetLinkResolverAllowFallback() {
if preferred == linkResolverProviderDeezerSongLink {
return []string{linkResolverProviderDeezerSongLink}
}
return []string{linkResolverProviderSongstats}
}
if preferred == linkResolverProviderDeezerSongLink {
return []string{
linkResolverProviderDeezerSongLink,
linkResolverProviderSongstats,
}
}
return []string{
linkResolverProviderSongstats,
linkResolverProviderDeezerSongLink,
}
}
func (s *SongLinkClient) resolveLinksViaSongstats(links *resolvedTrackLinks) (bool, error) {
if links == nil || links.ISRC == "" {
return false, fmt.Errorf("ISRC is required for Songstats resolver")
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

+40
View File
@@ -14,6 +14,8 @@ import { SelectFolder, OpenConfigFolder } from "../../wailsjs/go/main/App";
import { toastWithSound as toast } from "@/lib/toast-with-sound";
import { ApiStatusTab } from "./ApiStatusTab";
import { AmazonIcon, QobuzIcon, TidalIcon } from "./PlatformIcons";
import songlinkIcon from "@/assets/icons/songlink.ico";
import songstatsIcon from "@/assets/icons/songstats.png";
interface SettingsPageProps {
onUnsavedChangesChange?: (hasUnsavedChanges: boolean) => void;
onResetRequest?: (resetFn: () => void) => void;
@@ -230,6 +232,44 @@ export function SettingsPage({ onUnsavedChangesChange, onResetRequest, }: Settin
</div>
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="link-resolver">Link Resolver</Label>
<div className="flex items-center gap-3 flex-wrap">
<Select value={tempSettings.linkResolver} onValueChange={(value: "songstats" | "songlink") => setTempSettings((prev) => ({
...prev,
linkResolver: value,
}))}>
<SelectTrigger id="link-resolver" className="h-9 w-fit min-w-[140px]">
<SelectValue placeholder="Select a link resolver"/>
</SelectTrigger>
<SelectContent>
<SelectItem value="songstats">
<span className="flex items-center gap-2">
<img src={songstatsIcon} alt="Songstats" className="h-4 w-4 shrink-0 rounded-[3px] object-contain" loading="lazy" />
Songstats
</span>
</SelectItem>
<SelectItem value="songlink">
<span className="flex items-center gap-2">
<img src={songlinkIcon} alt="Songlink" className="h-4 w-4 shrink-0 rounded-[3px] object-contain" loading="lazy" />
Songlink
</span>
</SelectItem>
</SelectContent>
</Select>
<div className="flex items-center gap-3">
<Switch id="allow-link-resolver-fallback" checked={tempSettings.allowResolverFallback} onCheckedChange={(checked) => setTempSettings((prev) => ({
...prev,
allowResolverFallback: checked,
}))}/>
<Label htmlFor="allow-link-resolver-fallback" className="text-sm font-normal cursor-pointer">
Allow Fallback
</Label>
</div>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="downloader">Source</Label>
<div className="flex gap-2 flex-wrap">
+16
View File
@@ -5,6 +5,8 @@ export type FilenamePreset = "title" | "title-artist" | "artist-title" | "track-
export interface Settings {
downloadPath: string;
downloader: "auto" | "tidal" | "qobuz" | "amazon";
linkResolver: "songstats" | "songlink";
allowResolverFallback: boolean;
theme: string;
themeMode: "auto" | "light" | "dark";
fontFamily: FontFamily;
@@ -93,6 +95,8 @@ function detectOS(): "Windows" | "linux/MacOS" {
export const DEFAULT_SETTINGS: Settings = {
downloadPath: "",
downloader: "auto",
linkResolver: "songstats",
allowResolverFallback: true,
theme: "yellow",
themeMode: "auto",
fontFamily: "google-sans",
@@ -225,6 +229,12 @@ function getSettingsFromLocalStorage(): Settings {
if (!('allowFallback' in parsed)) {
parsed.allowFallback = true;
}
if (!('linkResolver' in parsed)) {
parsed.linkResolver = "songstats";
}
if (!('allowResolverFallback' in parsed)) {
parsed.allowResolverFallback = true;
}
if (!('separator' in parsed)) {
parsed.separator = "semicolon";
}
@@ -304,6 +314,12 @@ export async function loadSettings(): Promise<Settings> {
if (!('allowFallback' in parsed)) {
parsed.allowFallback = true;
}
if (!('linkResolver' in parsed)) {
parsed.linkResolver = "songstats";
}
if (!('allowResolverFallback' in parsed)) {
parsed.allowResolverFallback = true;
}
if (!('createPlaylistFolder' in parsed)) {
parsed.createPlaylistFolder = true;
}