4.4 KiB
4.4 KiB
Replace Tidal OAuth2 Backend with Public Web API + Self-Hosted Proxy
Goal
Replace Monochrome's Tidal OAuth2 backend (which is blocked in your country) with the SpotiFLAC tidal-web approach that uses:
- Tidal public web endpoints (
tidal.com/v1/) with a public token for metadata/search - Self-hosted proxy (SpotiFLAC Go backend) for audio streaming/downloads
Changes
1. js/HiFi.ts - Complete rewrite
- Remove OAuth2 token flow (
auth.tidal.com/v1/oauth2/token) - Use public web token (
x-tidal-tokenheader, default:49YxDN9a2aFV6RTG) - Change API base from
api.tidal.com/v1/totidal.com/v1/ - Keep all TypeScript type interfaces (TidalTrack, TidalAlbum, etc.)
- Keep
TidalResponseclass - Update
query()to usetidal.com/v1/endpoints - Methods updated:
getInfo,getTrack,getAlbum,getPlaylist,getPlaylistItems,getArtist,search,getVideo,getLyrics,getSimilarArtists,getSimilarAlbums - Constructor accepts:
publicToken,countryCode,locale,deviceType - Remove:
#fetchAppToken,#fetchAuthenticated,#fetchJson(OAuth2-based),fetchToken,getTrackManifest
2. js/api.js - Rewrite LosslessAPI
fetchWithRetry()- Remove HiFiClient OAuth2 fallback, remove proxy instance iteration for metadata (use HiFiClient directly). Keep proxy logic only for streaming if needed.search(),searchTracks(),searchArtists(),searchAlbums(),searchPlaylists(),searchVideos()- Update to use new HiFiClient.search()getAlbum()- Update to handle pages API response structure (pages/albumreturns page modules withALBUM_HEADERandALBUM_ITEMS)getPlaylist()- Update to use new HiFiClient methodsgetArtist()- Update to handle pages API response (pages/artistreturnsARTIST_HEADERmodule)getTrack()- Route through self-hosted proxy instead of Tidal OpenAPIgetStreamUrl()- Route through self-hosted proxygetVideo()- Update for new endpointsdownloadTrack()- Stream URLs come from self-hosted proxyenrichTrack()- Update to use proxy for playback infonormalizeTrackManifestResponse()- Adapt to proxy response format- Keep:
getCoverUrl(),getCoverSrcset(),getArtistPictureUrl(),getArtistPictureSrcset(),getVideoCoverUrl(), cache methods, prepare methods
3. js/storage.js - Add tidalWebSettings
export const tidalWebSettings = {
STORAGE_KEY: 'tidal-web-settings',
DEFAULT_PROXY_URL: '', // User must set their self-hosted proxy
DEFAULT_PUBLIC_TOKEN: '49YxDN9a2aFV6RTG',
DEFAULT_COUNTRY_CODE: 'US',
getProxyUrl() { ... },
setProxyUrl(url) { ... },
getPublicToken() { ... },
setPublicToken(token) { ... },
getCountryCode() { ... },
setCountryCode(code) { ... },
};
4. js/proxy-utils.js - Simplify
- Remove tidal CDN URL proxying (no longer needed - streaming goes through self-hosted proxy)
- Keep CORS proxy list for any remaining direct stream URLs
5. js/music-api.js - Minimal changes
getTrack(),getStreamUrl(),downloadTrack()already delegate to LosslessAPI- No structural changes needed
6. js/app.js - Update initialization
- Change
HiFiClient.initialize()to passpublicToken,countryCodefrom tidalWebSettings - Remove OAuth2 token/tokenExpiry storage references
Self-Hosted Proxy API Contract
The self-hosted SpotiFLAC Go backend must expose:
POST {proxyUrl}/v1/dl/tid2
Body: { "id": "123456", "quality": "HI_RES_LOSSLESS" }
Response:
{
"data": {
"manifest": "base64-encoded-manifest",
"manifestMimeType": "application/dash+xml",
"audioQuality": "HI_RES_LOSSLESS",
"bitDepth": 24,
"sampleRate": 96000,
"trackPresentation": "FULL"
}
}
Alternative response format (from mirror proxies):
[{ "OriginalTrackUrl": "https://direct-stream-url.flac" }]
Deployment Notes
The SpotiFLAC Go backend is at go_backend/ in the SpotiFLAC-Mobile repo:
- Build:
cd go_backend && go build - Run:
./go_backend(listens on port) - Configure with Tidal credentials or public token
Files Modified
js/HiFi.ts- Full rewritejs/api.js- Major rewrite (LosslessAPI class)js/storage.js- Add tidalWebSettingsjs/proxy-utils.js- Simplifyjs/music-api.js- Minimal changesjs/app.js- Update initialization
Files NOT Modified
- Server-side functions (Cloudflare Workers for SEO) - continue using OAuth2
- Frontend UI components
- Player, downloads, metadata embedding logic (unchanged interfaces)