.remove spotfetch api

This commit is contained in:
afkarxyz
2026-04-13 22:50:45 +07:00
parent e23fa2a48e
commit 7997f7e264
9 changed files with 9 additions and 428 deletions
+3 -24
View File
@@ -142,7 +142,7 @@ type DownloadRequest struct {
AlbumArtist string `json:"album_artist,omitempty"`
ReleaseDate string `json:"release_date,omitempty"`
CoverURL string `json:"cover_url,omitempty"`
ApiURL string `json:"api_url,omitempty"`
TidalAPIURL string `json:"tidal_api_url,omitempty"`
OutputDir string `json:"output_dir,omitempty"`
AudioFormat string `json:"audio_format,omitempty"`
FilenameFormat string `json:"filename_format,omitempty"`
@@ -247,27 +247,6 @@ func (a *App) GetSpotifyMetadata(req SpotifyMetadataRequest) (string, error) {
}
}
if err == nil && settings != nil {
if useAPI, ok := settings["useSpotFetchAPI"].(bool); ok && useAPI {
if apiURL, ok := settings["spotFetchAPIUrl"].(string); ok && apiURL != "" {
data, err := backend.GetSpotifyDataWithAPI(ctx, req.URL, true, apiURL, req.Batch, time.Duration(req.Delay*float64(time.Second)), separator, func(tracks interface{}) {
runtime.EventsEmit(a.ctx, "metadata-stream", tracks)
})
if err != nil {
return "", fmt.Errorf("failed to fetch metadata from API: %v", err)
}
jsonData, err := json.MarshalIndent(data, "", " ")
if err != nil {
return "", fmt.Errorf("failed to encode response: %v", err)
}
return string(jsonData), nil
}
}
}
data, err := backend.GetFilteredSpotifyData(ctx, req.URL, req.Batch, time.Duration(req.Delay*float64(time.Second)), separator, func(tracks interface{}) {
runtime.EventsEmit(a.ctx, "metadata-stream", tracks)
})
@@ -518,7 +497,7 @@ func (a *App) DownloadTrack(req DownloadRequest) (DownloadResponse, error) {
}
case "tidal":
if req.ApiURL == "" || req.ApiURL == "auto" {
if req.TidalAPIURL == "" || req.TidalAPIURL == "auto" {
downloader := backend.NewTidalDownloader("")
if req.ServiceURL != "" {
filename, err = downloader.DownloadByURLWithFallback(req.ServiceURL, req.OutputDir, req.AudioFormat, req.FilenameFormat, req.TrackNumber, req.Position, req.TrackName, req.ArtistName, req.AlbumName, req.AlbumArtist, req.ReleaseDate, req.UseAlbumTrackNumber, req.CoverURL, req.EmbedMaxQualityCover, req.SpotifyTrackNumber, req.SpotifyDiscNumber, req.SpotifyTotalTracks, req.SpotifyTotalDiscs, req.Copyright, req.Publisher, req.Composer, metadataSeparator, req.ISRC, spotifyURL, req.AllowFallback, req.UseFirstArtistOnly, req.UseSingleGenre, req.EmbedGenre)
@@ -526,7 +505,7 @@ func (a *App) DownloadTrack(req DownloadRequest) (DownloadResponse, error) {
filename, err = downloader.Download(req.SpotifyID, req.OutputDir, req.AudioFormat, req.FilenameFormat, req.TrackNumber, req.Position, req.TrackName, req.ArtistName, req.AlbumName, req.AlbumArtist, req.ReleaseDate, req.UseAlbumTrackNumber, req.CoverURL, req.EmbedMaxQualityCover, req.SpotifyTrackNumber, req.SpotifyDiscNumber, req.SpotifyTotalTracks, req.SpotifyTotalDiscs, req.Copyright, req.Publisher, req.Composer, metadataSeparator, req.ISRC, spotifyURL, req.AllowFallback, req.UseFirstArtistOnly, req.UseSingleGenre, req.EmbedGenre)
}
} else {
downloader := backend.NewTidalDownloader(req.ApiURL)
downloader := backend.NewTidalDownloader(req.TidalAPIURL)
if req.ServiceURL != "" {
filename, err = downloader.DownloadByURL(req.ServiceURL, req.OutputDir, req.AudioFormat, req.FilenameFormat, req.TrackNumber, req.Position, req.TrackName, req.ArtistName, req.AlbumName, req.AlbumArtist, req.ReleaseDate, req.UseAlbumTrackNumber, req.CoverURL, req.EmbedMaxQualityCover, req.SpotifyTrackNumber, req.SpotifyDiscNumber, req.SpotifyTotalTracks, req.SpotifyTotalDiscs, req.Copyright, req.Publisher, req.Composer, metadataSeparator, req.ISRC, spotifyURL, req.AllowFallback, req.UseFirstArtistOnly, req.UseSingleGenre, req.EmbedGenre)
} else {
-19
View File
@@ -50,25 +50,6 @@ func LoadConfigSettings() (map[string]interface{}, error) {
return settings, nil
}
func GetSpotFetchAPISettings() (bool, string) {
settings, err := LoadConfigSettings()
if err != nil || settings == nil {
return false, ""
}
useAPI, _ := settings["useSpotFetchAPI"].(bool)
if !useAPI {
return false, ""
}
apiURL, _ := settings["spotFetchAPIUrl"].(string)
if apiURL == "" {
apiURL = "https://sp.afkarxyz.qzz.io/api"
}
return true, apiURL
}
func GetRedownloadWithSuffixSetting() bool {
settings, err := LoadConfigSettings()
if err != nil || settings == nil {
-89
View File
@@ -52,20 +52,6 @@ type SpotifyTrackIdentifiers struct {
UPC string `json:"upc,omitempty"`
}
type spotFetchIdentifierResponse struct {
Input string `json:"input"`
TrackID string `json:"track_id"`
GID string `json:"gid"`
CanonicalURI string `json:"canonical_uri"`
Name string `json:"name"`
Artists []string `json:"artists"`
AlbumName string `json:"album_name"`
ReleaseDate string `json:"release_date"`
Label string `json:"label"`
ISRC string `json:"isrc"`
UPC string `json:"upc"`
}
func GetSpotifyTrackIdentifiersDirect(spotifyTrackID string) (SpotifyTrackIdentifiers, error) {
normalizedTrackID, err := extractSpotifyTrackID(spotifyTrackID)
if err != nil {
@@ -82,23 +68,6 @@ func GetSpotifyTrackIdentifiersDirect(spotifyTrackID string) (SpotifyTrackIdenti
identifiers.ISRC = cachedISRC
}
useSpotFetchAPI, spotFetchAPIURL := GetSpotFetchAPISettings()
if useSpotFetchAPI {
apiIdentifiers, resolvedTrackID, err := lookupSpotifyTrackIdentifiersViaSpotFetchAPI(normalizedTrackID, spotFetchAPIURL)
if err == nil {
mergeSpotifyTrackIdentifiers(&identifiers, apiIdentifiers)
if identifiers.ISRC != "" {
fmt.Printf("Found identifiers via SpotFetch API: isrc=%s upc=%s\n", identifiers.ISRC, identifiers.UPC)
cacheResolvedSpotifyTrackISRC(normalizedTrackID, resolvedTrackID, identifiers.ISRC)
}
if identifiers.ISRC != "" && identifiers.UPC != "" {
return identifiers, nil
}
} else {
fmt.Printf("Warning: SpotFetch identifier lookup failed, falling back to Spotify metadata: %v\n", err)
}
}
httpClient := &http.Client{Timeout: 30 * time.Second}
payload, metadataErr := fetchSpotifyTrackRawData(httpClient, normalizedTrackID)
@@ -172,18 +141,6 @@ func cacheResolvedSpotifyTrackISRC(trackID string, resolvedTrackID string, isrc
}
}
func (s *SongLinkClient) lookupSpotifyISRCViaSpotFetchAPI(spotifyTrackID string, apiBaseURL string) (string, string, error) {
identifiers, resolvedTrackID, err := lookupSpotifyTrackIdentifiersViaSpotFetchAPI(spotifyTrackID, apiBaseURL)
if err != nil {
return "", "", err
}
if identifiers.ISRC == "" {
return "", "", fmt.Errorf("ISRC missing in SpotFetch identifier response")
}
return identifiers.ISRC, resolvedTrackID, nil
}
func mergeSpotifyTrackIdentifiers(target *SpotifyTrackIdentifiers, incoming SpotifyTrackIdentifiers) {
if incoming.ISRC != "" {
target.ISRC = strings.TrimSpace(incoming.ISRC)
@@ -193,52 +150,6 @@ func mergeSpotifyTrackIdentifiers(target *SpotifyTrackIdentifiers, incoming Spot
}
}
func lookupSpotifyTrackIdentifiersViaSpotFetchAPI(spotifyTrackID string, apiBaseURL string) (SpotifyTrackIdentifiers, string, error) {
normalizedTrackID := strings.TrimSpace(spotifyTrackID)
baseURL := strings.TrimRight(strings.TrimSpace(apiBaseURL), "/")
if normalizedTrackID == "" {
return SpotifyTrackIdentifiers{}, "", fmt.Errorf("spotify track ID is required")
}
if baseURL == "" {
return SpotifyTrackIdentifiers{}, "", fmt.Errorf("spotfetch api url is required")
}
requestURL := fmt.Sprintf("%s/identifier/%s", baseURL, url.PathEscape(normalizedTrackID))
req, err := http.NewRequest(http.MethodGet, requestURL, nil)
if err != nil {
return SpotifyTrackIdentifiers{}, "", fmt.Errorf("failed to create SpotFetch identifier request: %w", err)
}
req.Header.Set("User-Agent", songLinkUserAgent)
req.Header.Set("Accept", "application/json")
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil {
return SpotifyTrackIdentifiers{}, "", fmt.Errorf("SpotFetch identifier request failed: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
bodyPreview, _ := io.ReadAll(io.LimitReader(resp.Body, 256))
return SpotifyTrackIdentifiers{}, "", fmt.Errorf("SpotFetch identifier returned status %d (%s)", resp.StatusCode, strings.TrimSpace(string(bodyPreview)))
}
var payload spotFetchIdentifierResponse
if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil {
return SpotifyTrackIdentifiers{}, "", fmt.Errorf("failed to decode SpotFetch identifier response: %w", err)
}
identifiers := SpotifyTrackIdentifiers{
ISRC: firstISRCMatch(payload.ISRC),
UPC: strings.TrimSpace(payload.UPC),
}
if identifiers.ISRC == "" && identifiers.UPC == "" {
return SpotifyTrackIdentifiers{}, "", fmt.Errorf("identifiers missing in SpotFetch response")
}
return identifiers, strings.TrimSpace(payload.TrackID), nil
}
func lookupSpotifyAlbumUPC(albumID string) (string, error) {
normalizedAlbumID := strings.TrimSpace(albumID)
if normalizedAlbumID == "" {
-197
View File
@@ -1,197 +0,0 @@
package backend
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"regexp"
"strings"
"time"
)
func streamTrackListChunks(ctx context.Context, tracks []AlbumTrackMetadata, callback MetadataCallback) error {
if callback == nil || len(tracks) == 0 {
return nil
}
const chunkSize = 25
for start := 0; start < len(tracks); start += chunkSize {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
end := start + chunkSize
if end > len(tracks) {
end = len(tracks)
}
callback(tracks[start:end])
if end < len(tracks) {
time.Sleep(15 * time.Millisecond)
}
}
return nil
}
func GetSpotifyDataWithAPI(ctx context.Context, spotifyURL string, useAPI bool, apiBaseURL string, batch bool, delay time.Duration, separator string, callback MetadataCallback) (interface{}, error) {
if !useAPI || apiBaseURL == "" {
return GetFilteredSpotifyData(ctx, spotifyURL, batch, delay, separator, callback)
}
spotifyType, id := parseSpotifyURLToTypeAndID(spotifyURL)
if spotifyType == "" || id == "" {
return nil, fmt.Errorf("invalid Spotify URL: %s", spotifyURL)
}
if spotifyType == "artist" {
return GetFilteredSpotifyData(ctx, spotifyURL, batch, delay, separator, callback)
}
apiURL := fmt.Sprintf("%s/%s/%s", strings.TrimSuffix(apiBaseURL, "/"), spotifyType, id)
req, err := http.NewRequestWithContext(ctx, "GET", apiURL, nil)
if err != nil {
return nil, fmt.Errorf("failed to create API request: %w", err)
}
client := &http.Client{
Timeout: 30 * time.Second,
}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("SpotFetch API request failed: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("SpotFetch API error: HTTP %d", resp.StatusCode)
}
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read API response: %w", err)
}
var data interface{}
switch spotifyType {
case "track":
var trackResp TrackResponse
if err := json.Unmarshal(bodyBytes, &trackResp); err != nil {
return nil, fmt.Errorf("failed to decode track response: %w", err)
}
trackID := strings.TrimSpace(trackResp.Track.SpotifyID)
if trackID == "" {
trackID = strings.TrimSpace(id)
}
if trackID != "" {
if identifiers, _, err := lookupSpotifyTrackIdentifiersViaSpotFetchAPI(trackID, apiBaseURL); err == nil {
if identifiers.UPC != "" {
trackResp.Track.UPC = identifiers.UPC
}
}
}
data = trackResp
case "album":
var albumResp AlbumResponsePayload
if err := json.Unmarshal(bodyBytes, &albumResp); err != nil {
return nil, fmt.Errorf("failed to decode album response: %w", err)
}
data = &albumResp
if callback != nil {
callback(&AlbumResponsePayload{
AlbumInfo: albumResp.AlbumInfo,
TrackList: []AlbumTrackMetadata{},
})
if err := streamTrackListChunks(ctx, albumResp.TrackList, callback); err != nil {
return nil, err
}
}
case "playlist":
var playlistResp PlaylistResponsePayload
if err := json.Unmarshal(bodyBytes, &playlistResp); err != nil {
return nil, fmt.Errorf("failed to decode playlist response: %w", err)
}
data = playlistResp
if callback != nil {
callback(PlaylistResponsePayload{
PlaylistInfo: playlistResp.PlaylistInfo,
TrackList: []AlbumTrackMetadata{},
})
if err := streamTrackListChunks(ctx, playlistResp.TrackList, callback); err != nil {
return nil, err
}
}
case "artist":
var artistResp ArtistDiscographyPayload
if err := json.Unmarshal(bodyBytes, &artistResp); err != nil {
return nil, fmt.Errorf("failed to decode artist response: %w", err)
}
data = &artistResp
if callback != nil {
callback(&ArtistDiscographyPayload{
ArtistInfo: artistResp.ArtistInfo,
AlbumList: artistResp.AlbumList,
TrackList: []AlbumTrackMetadata{},
})
if err := streamTrackListChunks(ctx, artistResp.TrackList, callback); err != nil {
return nil, err
}
}
default:
return nil, fmt.Errorf("unsupported Spotify type: %s", spotifyType)
}
if callback != nil {
switch payload := data.(type) {
case TrackResponse:
t := payload.Track
callback([]AlbumTrackMetadata{{
SpotifyID: t.SpotifyID,
Artists: t.Artists,
Name: t.Name,
AlbumName: t.AlbumName,
AlbumArtist: t.AlbumArtist,
DurationMS: t.DurationMS,
Images: t.Images,
ReleaseDate: t.ReleaseDate,
TrackNumber: t.TrackNumber,
TotalTracks: t.TotalTracks,
DiscNumber: t.DiscNumber,
TotalDiscs: t.TotalDiscs,
ExternalURL: t.ExternalURL,
UPC: t.UPC,
Plays: t.Plays,
PreviewURL: t.PreviewURL,
IsExplicit: t.IsExplicit,
}})
}
}
return data, nil
}
func parseSpotifyURLToTypeAndID(url string) (string, string) {
if strings.HasPrefix(url, "spotify:") {
parts := strings.Split(url, ":")
if len(parts) >= 3 {
return parts[1], parts[2]
}
}
re := regexp.MustCompile(`spotify\.com/(track|album|playlist|artist)/([a-zA-Z0-9]+)`)
matches := re.FindStringSubmatch(url)
if len(matches) == 3 {
return matches[1], matches[2]
}
return "", ""
}
+1 -31
View File
@@ -3,7 +3,7 @@ import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog";
import { Search, X, ArrowUp } from "lucide-react";
import { TooltipProvider } from "@/components/ui/tooltip";
import { getSettings, getSettingsWithDefaults, loadSettings, saveSettings, applyThemeMode, applyFont, updateSettings } from "@/lib/settings";
import { getSettings, getSettingsWithDefaults, loadSettings, saveSettings, applyThemeMode, applyFont } from "@/lib/settings";
import { applyTheme } from "@/lib/themes";
import { OpenFolder, CheckFFmpegInstalled, DownloadFFmpeg, GetBrewPath, GetRecentFetches, InstallFFmpegWithBrew, SaveRecentFetches } from "../wailsjs/go/main/App";
import { EventsOn, EventsOff, Quit } from "../wailsjs/runtime/runtime";
@@ -211,17 +211,6 @@ function App() {
window.removeEventListener("scroll", handleScroll);
};
}, []);
const handleEnableSpotFetchApi = async () => {
try {
await updateSettings({ useSpotFetchAPI: true });
metadata.setShowApiModal(false);
toast.success("SpotFetch API enabled! You can now try fetching again.");
}
catch (err) {
console.error("Failed to enable SpotFetch API:", err);
toast.error("Failed to update settings");
}
};
const scrollToTop = useCallback(() => {
window.scrollTo({ top: 0, behavior: "smooth" });
}, []);
@@ -694,25 +683,6 @@ function App() {
</DialogFooter>
</DialogContent>
</Dialog>
<Dialog open={metadata.showApiModal} onOpenChange={metadata.setShowApiModal}>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>SpotFetch API Recommended</DialogTitle>
<DialogDescription>
Direct fetch failed. This usually happens when your <span className="text-foreground font-bold">country is blocked</span> by Spotify or your IP is restricted. Would you like to enable the <span className="text-foreground font-bold">SpotFetch API</span> to bypass this?
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button variant="outline" onClick={() => metadata.setShowApiModal(false)}>
Cancel
</Button>
<Button onClick={handleEnableSpotFetchApi}>
Enable SpotFetch API
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
</TooltipProvider>);
}
+2 -45
View File
@@ -1,31 +1,8 @@
import { X, Minus, Maximize, SlidersHorizontal, Info, Globe } from "lucide-react";
import { X, Minus, Maximize, SlidersHorizontal, Globe } from "lucide-react";
import { WindowMinimise, WindowToggleMaximise, Quit } from "../../wailsjs/runtime/runtime";
import { Menubar, MenubarContent, MenubarMenu, MenubarItem, MenubarTrigger, MenubarLabel, MenubarSeparator } from "@/components/ui/menubar";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
import { getSettings, updateSettings } from "@/lib/settings";
import { Menubar, MenubarContent, MenubarMenu, MenubarItem, MenubarTrigger } from "@/components/ui/menubar";
import { openExternal } from "@/lib/utils";
import { useState, useEffect } from "react";
export function TitleBar() {
const [useSpotFetchAPI, setUseSpotFetchAPI] = useState(false);
useEffect(() => {
const settings = getSettings();
if (settings) {
setUseSpotFetchAPI(settings.useSpotFetchAPI || false);
}
const handleSettingsUpdate = (event: any) => {
const updatedSettings = event.detail;
if (updatedSettings && typeof updatedSettings.useSpotFetchAPI !== 'undefined') {
setUseSpotFetchAPI(updatedSettings.useSpotFetchAPI);
}
};
window.addEventListener('settingsUpdated', handleSettingsUpdate);
return () => window.removeEventListener('settingsUpdated', handleSettingsUpdate);
}, []);
const handleSpotFetchAPIToggle = () => {
const newValue = !useSpotFetchAPI;
setUseSpotFetchAPI(newValue);
updateSettings({ useSpotFetchAPI: newValue });
};
const handleMinimize = () => {
WindowMinimise();
};
@@ -47,26 +24,6 @@ export function TitleBar() {
<SlidersHorizontal className="w-3.5 h-3.5"/>
</MenubarTrigger>
<MenubarContent align="end" className="min-w-[200px]">
<div className="flex items-center gap-1.5 px-2 py-1.5">
<MenubarLabel className="p-0">SpotFetch API</MenubarLabel>
<TooltipProvider delayDuration={300}>
<Tooltip>
<TooltipTrigger asChild>
<Info className="w-3.5 h-3.5 cursor-help text-muted-foreground"/>
</TooltipTrigger>
<TooltipContent side="left" className="max-w-xs">
<p className="font-semibold mb-2">Spotify Blocked Countries:</p>
<p className="text-xs">Afghanistan, Antarctica, Central African Republic, China, Cuba, Eritrea, Iran, Myanmar, North Korea, Russia, Somalia, South Sudan, Sudan, Syria, Turkmenistan, Yemen</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
<MenubarSeparator />
<MenubarItem onClick={handleSpotFetchAPIToggle} className="justify-between">
<span>Use SpotFetch API</span>
<span className="ml-4">{useSpotFetchAPI ? "✓" : ""}</span>
</MenubarItem>
<MenubarSeparator />
<MenubarItem onClick={() => openExternal("https://afkarxyz.qzz.io")} className="gap-2">
<Globe className="w-4 h-4 opacity-70"/>
<span>Website</span>
+2 -18
View File
@@ -1,5 +1,4 @@
import { useEffect, useRef, useState } from "react";
import { getSettings } from "@/lib/settings";
import { fetchSpotifyMetadata } from "@/lib/api";
import { toastWithSound as toast } from "@/lib/toast-with-sound";
import { logger } from "@/lib/logger";
@@ -12,7 +11,6 @@ export function useMetadata() {
const loadingToastId = useRef<string | number | null>(null);
const fetchedCount = useRef(0);
const currentName = useRef("");
const [showApiModal, setShowApiModal] = useState(false);
const [showAlbumDialog, setShowAlbumDialog] = useState(false);
const [selectedAlbum, setSelectedAlbum] = useState<{
id: string;
@@ -215,13 +213,7 @@ export function useMetadata() {
catch (err) {
const errorMsg = err instanceof Error ? err.message : "Failed to fetch metadata";
logger.error(`fetch failed: ${errorMsg}`);
const settings = getSettings();
if (!settings.useSpotFetchAPI) {
setShowApiModal(true);
}
else {
toast.error(errorMsg);
}
toast.error(errorMsg);
}
finally {
setLoading(false);
@@ -323,13 +315,7 @@ export function useMetadata() {
catch (err) {
const errorMsg = err instanceof Error ? err.message : "Failed to fetch album metadata";
logger.error(`fetch failed: ${errorMsg}`);
const settings = getSettings();
if (!settings.useSpotFetchAPI) {
setShowApiModal(true);
}
else {
toast.error(errorMsg);
}
toast.error(errorMsg);
}
finally {
setLoading(false);
@@ -348,8 +334,6 @@ export function useMetadata() {
handleConfirmAlbumFetch,
handleArtistClick,
loadFromCache,
showApiModal,
setShowApiModal,
resetMetadata: () => setMetadata(null),
};
}
-4
View File
@@ -28,8 +28,6 @@ export interface Settings {
autoOrder: "tidal-qobuz-amazon" | "tidal-amazon-qobuz" | "qobuz-tidal-amazon" | "qobuz-amazon-tidal" | "amazon-tidal-qobuz" | "amazon-qobuz-tidal" | string;
autoQuality: "16" | "24";
allowFallback: boolean;
useSpotFetchAPI: boolean;
spotFetchAPIUrl: string;
createPlaylistFolder: boolean;
playlistOwnerFolderName: boolean;
createM3u8File: boolean;
@@ -118,8 +116,6 @@ export const DEFAULT_SETTINGS: Settings = {
autoOrder: "tidal-qobuz-amazon",
autoQuality: "16",
allowFallback: true,
useSpotFetchAPI: false,
spotFetchAPIUrl: "https://sp.afkarxyz.qzz.io/api",
createPlaylistFolder: true,
playlistOwnerFolderName: false,
createM3u8File: false,
+1 -1
View File
@@ -119,7 +119,7 @@ export interface DownloadRequest {
album_artist?: string;
release_date?: string;
cover_url?: string;
api_url?: string;
tidal_api_url?: string;
output_dir?: string;
audio_format?: string;
folder_name?: string;