style: auto-fix linting issues

This commit is contained in:
mclovin123456789 authored and github-actions[bot] committed 2026-09-20 14:38:39 +00:00
1 parent 3726d5d731
commit 3eb5271c3e
8 files changed
+79 -138

No files matched your search

+1
View File
@@ -99,6 +99,7 @@ The application is configured via environment variables. Copy `.env.example` to
### Authentication (Better Auth)
Monochrome uses Better Auth for user authentication (defaulting to `https://auth.monochrome.st`). You can configure a custom auth instance using:
- `AUTH_URL`: Your Better Auth endpoint (e.g., `https://auth.monochrome.st`).
### Database (PocketBase)
+9 -9
View File
@@ -27,15 +27,15 @@ PLEASE do not use any rehost of monochrome and complain to us about features not
### Official & Community APIs
| Provider | URL | Notes |
| ----------------- | ----------------------------------- | ----------------------------------------------------------------------- |
| **Monochrome** | `https://api.monochrome.tf` | Official API |
| **Lucida (QQDL)** | `https://wolf.qqdl.site` | Community hosted |
| | `https://maus.qqdl.site` | Community hosted |
| | `https://vogel.qqdl.site` | Community hosted |
| | `https://katze.qqdl.site` | Community hosted |
| | `https://hund.qqdl.site` | Community hosted |
| **Kinoplus** | `https://tidal.kinoplus.online` | Community hosted - [Limited/No-Sub](https://rentry.co/limitedtidalaccs) |
| Provider | URL | Notes |
| ----------------- | ------------------------------- | ----------------------------------------------------------------------- |
| **Monochrome** | `https://api.monochrome.tf` | Official API |
| **Lucida (QQDL)** | `https://wolf.qqdl.site` | Community hosted |
| | `https://maus.qqdl.site` | Community hosted |
| | `https://vogel.qqdl.site` | Community hosted |
| | `https://katze.qqdl.site` | Community hosted |
| | `https://hund.qqdl.site` | Community hosted |
| **Kinoplus** | `https://tidal.kinoplus.online` | Community hosted - [Limited/No-Sub](https://rentry.co/limitedtidalaccs) |
---
+20 -39
View File
@@ -1279,7 +1279,12 @@
</p>
<div style="margin-bottom: 1rem">
<label style="display: block; margin-bottom: 0.5rem; font-size: 0.9rem">PocketBase URL</label>
<input type="url" id="custom-pb-url" class="template-input" placeholder="https://data.monochrome.st" />
<input
type="url"
id="custom-pb-url"
class="template-input"
placeholder="https://data.monochrome.st"
/>
</div>
<div style="margin-bottom: 1rem">
<label style="display: block; margin-bottom: 0.5rem; font-size: 0.9rem">Auth Endpoint</label>
@@ -4220,24 +4225,12 @@
</div>
<select id="streaming-quality-setting">
<option value="auto">Auto (Adaptive)</option>
<option value="DOLBY_ATMOS_EAC3_HIGH">
Dolby Atmos — E-AC-3 High
</option>
<option value="DOLBY_ATMOS_EAC3_LOW">
Dolby Atmos — E-AC-3 Low
</option>
<option value="DOLBY_ATMOS_AC4_HIGH">
Dolby Atmos — AC-4 High
</option>
<option value="DOLBY_ATMOS_AC4_LOW">
Dolby Atmos — AC-4 Low
</option>
<option value="HI_RES_LOSSLESS">
Hi-Res Lossless (24-bit)
</option>
<option value="LOSSLESS">
Lossless (16-bit)
</option>
<option value="DOLBY_ATMOS_EAC3_HIGH">Dolby Atmos — E-AC-3 High</option>
<option value="DOLBY_ATMOS_EAC3_LOW">Dolby Atmos — E-AC-3 Low</option>
<option value="DOLBY_ATMOS_AC4_HIGH">Dolby Atmos — AC-4 High</option>
<option value="DOLBY_ATMOS_AC4_LOW">Dolby Atmos — AC-4 Low</option>
<option value="HI_RES_LOSSLESS">Hi-Res Lossless (24-bit)</option>
<option value="LOSSLESS">Lossless (16-bit)</option>
<option value="HIGH">High</option>
<option value="LOW">Low</option>
</select>
@@ -5528,24 +5521,12 @@
>
</div>
<select id="download-quality-setting">
<option value="DOLBY_ATMOS_EAC3_HIGH">
Dolby Atmos — E-AC-3 High
</option>
<option value="DOLBY_ATMOS_EAC3_LOW">
Dolby Atmos — E-AC-3 Low
</option>
<option value="DOLBY_ATMOS_AC4_HIGH">
Dolby Atmos — AC-4 High
</option>
<option value="DOLBY_ATMOS_AC4_LOW">
Dolby Atmos — AC-4 Low
</option>
<option value="HI_RES_LOSSLESS">
Hi-Res Lossless (24-bit)
</option>
<option value="LOSSLESS">
Lossless (16-bit)
</option>
<option value="DOLBY_ATMOS_EAC3_HIGH">Dolby Atmos — E-AC-3 High</option>
<option value="DOLBY_ATMOS_EAC3_LOW">Dolby Atmos — E-AC-3 Low</option>
<option value="DOLBY_ATMOS_AC4_HIGH">Dolby Atmos — AC-4 High</option>
<option value="DOLBY_ATMOS_AC4_LOW">Dolby Atmos — AC-4 Low</option>
<option value="HI_RES_LOSSLESS">Hi-Res Lossless (24-bit)</option>
<option value="LOSSLESS">Lossless (16-bit)</option>
<option value="HIGH">High</option>
<option value="LOW">Low</option>
</select>
@@ -6176,8 +6157,8 @@
<p class="version">Version 2.5.0</p>
<p class="version" id="about-commit-info"></p>
<p class="disclaimer">
This is an independent client and is not affiliated with or endorsed by any
music streaming service.
This is an independent client and is not affiliated with or endorsed by any music
streaming service.
</p>
<p class="disclaimer">
This application does not host, store, or distribute any media files. <br />
+9 -17
View File
@@ -9,11 +9,7 @@ import {
normalizeAppleArtist,
normalizeAppleSearchResults,
} from './apple-music-api.js';
import {
TracksStreamerAPI,
tracksStreamerAPI,
normalizeTracksSearchResults,
} from './tracks-api.js';
import { TracksStreamerAPI, tracksStreamerAPI, normalizeTracksSearchResults } from './tracks-api.js';
import { getCommunityPlaylist } from './community-playlists.js';
/**
@@ -169,7 +165,8 @@ export class MusicAPI {
}
} catch (error) {
if (error.name === 'AbortError') throw error;
if (import.meta.env.DEV) console.warn('[searchTracks] Tracks Streamer unavailable, trying fallbacks', error);
if (import.meta.env.DEV)
console.warn('[searchTracks] Tracks Streamer unavailable, trying fallbacks', error);
}
return this.searchSection('tracks', 'songs', query, options, () => this.getAPI().searchTracks(query, options));
}
@@ -185,7 +182,8 @@ export class MusicAPI {
}
} catch (error) {
if (error.name === 'AbortError') throw error;
if (import.meta.env.DEV) console.warn('[searchArtists] Tracks Streamer unavailable, trying fallbacks', error);
if (import.meta.env.DEV)
console.warn('[searchArtists] Tracks Streamer unavailable, trying fallbacks', error);
}
return this.searchSection('artists', 'artists', query, options, () =>
this.getAPI().searchArtists(query, options)
@@ -203,7 +201,8 @@ export class MusicAPI {
}
} catch (error) {
if (error.name === 'AbortError') throw error;
if (import.meta.env.DEV) console.warn('[searchAlbums] Tracks Streamer unavailable, trying fallbacks', error);
if (import.meta.env.DEV)
console.warn('[searchAlbums] Tracks Streamer unavailable, trying fallbacks', error);
}
return this.searchSection('albums', 'albums', query, options, () => this.getAPI().searchAlbums(query, options));
}
@@ -488,10 +487,7 @@ export class MusicAPI {
// Stream methods
async getStreamUrl(id, quality, options = {}) {
let track =
options?.track ||
this.getCachedTracksTrack(id) ||
this.getCachedAppleTrack(id);
let track = options?.track || this.getCachedTracksTrack(id) || this.getCachedAppleTrack(id);
if (!track && (this.isTracksId(id) || this.isAppleId(id) || /^\d{17,20}$/.test(String(id)))) {
track = await this.getTrackMetadata(id).catch(() => null);
@@ -660,11 +656,7 @@ export class MusicAPI {
if (type === 'artist' && this.tracksArtistIds.has(id)) return true;
if (type === 'track' && this.tracksTrackCache.has(id)) return true;
if (!type) {
return (
this.tracksTrackCache.has(id) ||
this.tracksAlbumIds.has(id) ||
this.tracksArtistIds.has(id)
);
return this.tracksTrackCache.has(id) || this.tracksAlbumIds.has(id) || this.tracksArtistIds.has(id);
}
}
return false;
-1
View File
@@ -1509,7 +1509,6 @@ export class Player {
let resolvedStreamInfo = await streamInfoPromise;
if (this.playbackSequence !== currentSequence) return;
streamUrl = resolvedStreamInfo.url;
this.currentStreamInfo = resolvedStreamInfo;
this.currentStreamProvider = resolvedStreamInfo.provider || null;
+18 -60
View File
@@ -33,16 +33,9 @@ export function normalizeTracksTrack(item) {
const trackId = String(item.trackId || item.id || '');
const id = trackId;
const artistId =
item.artistIds?.[0] ||
item.artists?.[0]?.artistId ||
item.artists?.[0]?.id ||
'';
const artistId = item.artistIds?.[0] || item.artists?.[0]?.artistId || item.artists?.[0]?.id || '';
const artistName =
item.artistNames?.[0] ||
item.artists?.[0]?.name ||
item.artists?.[0]?.displayName ||
'Unknown Artist';
item.artistNames?.[0] || item.artists?.[0]?.name || item.artists?.[0]?.displayName || 'Unknown Artist';
const primaryArtist = {
id: artistId ? String(artistId) : '',
@@ -86,11 +79,7 @@ export function normalizeTracksTrack(item) {
const releaseId = item.releaseId ? String(item.releaseId) : '';
const artwork = item.artwork || item.cover || '';
const albumTitle =
item.albumTitle ||
item.releaseTitle ||
(item.release && item.release.title) ||
'';
const albumTitle = item.albumTitle || item.releaseTitle || (item.release && item.release.title) || '';
const album = {
id: releaseId,
@@ -148,16 +137,9 @@ export function normalizeTracksRelease(item) {
const releaseId = String(item.releaseId || item.id || '');
const id = releaseId;
const artistId =
item.artistIds?.[0] ||
item.artists?.[0]?.artistId ||
item.artists?.[0]?.id ||
'';
const artistId = item.artistIds?.[0] || item.artists?.[0]?.artistId || item.artists?.[0]?.id || '';
const artistName =
item.artistNames?.[0] ||
item.artists?.[0]?.name ||
item.artists?.[0]?.displayName ||
'Unknown Artist';
item.artistNames?.[0] || item.artists?.[0]?.name || item.artists?.[0]?.displayName || 'Unknown Artist';
const primaryArtist = {
id: artistId ? String(artistId) : '',
@@ -186,9 +168,7 @@ export function normalizeTracksRelease(item) {
: [primaryArtist];
const artwork = item.artwork || item.cover || '';
const trackCount =
item.trackCount ||
(Array.isArray(item.tracks) ? item.tracks.length : 0);
const trackCount = item.trackCount || (Array.isArray(item.tracks) ? item.tracks.length : 0);
return {
id,
@@ -251,10 +231,7 @@ export function normalizeTracksPlaylist(item) {
if (!item) return null;
const playlistId = String(item.playlistId || item.id || '');
const id = playlistId;
const image =
typeof item.thumbnail === 'string' && item.thumbnail.startsWith('http')
? item.thumbnail
: '';
const image = typeof item.thumbnail === 'string' && item.thumbnail.startsWith('http') ? item.thumbnail : '';
return {
id,
@@ -336,9 +313,7 @@ export function extractTracksSuggestions(results, query) {
seen.add(normalizedQuery);
}
const rawTracks = Array.isArray(results)
? results
: results?.tracks?.items || results?.tracks || [];
const rawTracks = Array.isArray(results) ? results : results?.tracks?.items || results?.tracks || [];
for (const raw of rawTracks) {
if (!raw) continue;
@@ -387,24 +362,18 @@ export function scoreTrackCandidate(candidate, target) {
if (targetTitleClean && candidateTitleClean) {
if (targetTitleClean === candidateTitleClean) {
score += 100;
} else if (
targetTitleClean.includes(candidateTitleClean) ||
candidateTitleClean.includes(targetTitleClean)
) {
} else if (targetTitleClean.includes(candidateTitleClean) || candidateTitleClean.includes(targetTitleClean)) {
score += 65;
}
}
const targetArtistName = cleanString(
target.artist?.name || target.artists?.[0]?.name || target.artist || ''
);
const candidateArtistNames = (
candidate.artistNames || [candidate.artist?.name || '']
).map(cleanString);
const targetArtistName = cleanString(target.artist?.name || target.artists?.[0]?.name || target.artist || '');
const candidateArtistNames = (candidate.artistNames || [candidate.artist?.name || '']).map(cleanString);
if (targetArtistName) {
const hasArtistMatch = candidateArtistNames.some(
(cName) => cName === targetArtistName || cName.includes(targetArtistName) || targetArtistName.includes(cName)
(cName) =>
cName === targetArtistName || cName.includes(targetArtistName) || targetArtistName.includes(cName)
);
if (hasArtistMatch) {
score += 50;
@@ -412,14 +381,9 @@ export function scoreTrackCandidate(candidate, target) {
}
// Check duration similarity (within 6 seconds)
const targetDur =
target.duration > 1000
? Math.round(target.duration / 1000)
: Math.round(target.duration || 0);
const targetDur = target.duration > 1000 ? Math.round(target.duration / 1000) : Math.round(target.duration || 0);
const candDur =
candidate.duration > 1000
? Math.round(candidate.duration / 1000)
: Math.round(candidate.duration || 0);
candidate.duration > 1000 ? Math.round(candidate.duration / 1000) : Math.round(candidate.duration || 0);
if (targetDur > 0 && candDur > 0) {
const diff = Math.abs(targetDur - candDur);
@@ -460,9 +424,7 @@ export class TracksStreamerAPI {
});
if (
(response.status === 502 ||
response.status === 503 ||
response.status === 504) &&
(response.status === 502 || response.status === 503 || response.status === 504) &&
attempt < retries
) {
await new Promise((r) => setTimeout(r, 200 * (attempt + 1)));
@@ -854,12 +816,8 @@ export class TracksStreamerAPI {
* @returns {Promise<Object|null>} Stream info or null if unresolved
*/
async resolveTrackStream(idOrTrack, quality = 'LOSSLESS', options = {}) {
const inputTrack =
options.track || (typeof idOrTrack === 'object' ? idOrTrack : null);
const id =
typeof idOrTrack === 'string'
? idOrTrack
: String(inputTrack?.id || '');
const inputTrack = options.track || (typeof idOrTrack === 'object' ? idOrTrack : null);
const id = typeof idOrTrack === 'string' ? idOrTrack : String(inputTrack?.id || '');
// 1. Direct match: Already a tracks.monochrome.st track
if (inputTrack?.tracksTrackId || inputTrack?.recordingId) {
+16 -11
View File
@@ -3691,10 +3691,8 @@ export class UIRenderer {
`Community Year-End ${year}${communityAgg.totalLists ? ` · ${communityAgg.totalLists} lists` : ''}`,
communityAgg.items
);
if (topRated?.items?.length)
this.renderAOTYRankedRows(contentDiv, `Top Rated ${year}`, topRated.items);
if (!contentDiv.children.length)
contentDiv.innerHTML = createPlaceholder('No chart data found.');
if (topRated?.items?.length) this.renderAOTYRankedRows(contentDiv, `Top Rated ${year}`, topRated.items);
if (!contentDiv.children.length) contentDiv.innerHTML = createPlaceholder('No chart data found.');
} catch (e) {
console.error(e);
contentDiv.innerHTML = createPlaceholder('Failed to load charts.');
@@ -3872,7 +3870,15 @@ export class UIRenderer {
this.renderAOTYSection(contentDiv, `Albums matching “${q.trim()}”`, data.albums);
return;
}
const rows = data.artists || data.labels || data.lists || data.items || data.news || data.tags || data.users || [];
const rows =
data.artists ||
data.labels ||
data.lists ||
data.items ||
data.news ||
data.tags ||
data.users ||
[];
if (!rows.length) {
contentDiv.innerHTML = createPlaceholder('No results found.');
return;
@@ -3920,7 +3926,10 @@ export class UIRenderer {
};
container.querySelector('#aoty-search-form').addEventListener('submit', (e) => {
e.preventDefault();
void runSearch(container.querySelector('#aoty-search-q').value, container.querySelector('#aoty-search-scope').value);
void runSearch(
container.querySelector('#aoty-search-q').value,
container.querySelector('#aoty-search-scope').value
);
});
}
@@ -4031,11 +4040,7 @@ export class UIRenderer {
</div>`;
row.querySelector('.row-title').textContent = itemTitle || item.title || '';
const metaParts = [
itemArtist,
item.date,
...(item.genres?.slice(0, 2) || []),
].filter(Boolean);
const metaParts = [itemArtist, item.date, ...(item.genres?.slice(0, 2) || [])].filter(Boolean);
row.querySelector('.row-meta').textContent = metaParts.join(' · ');
row.appendChild(scoreEl);
if (embeddedScore == null) scoreTargets.push({ item, scoreEl });
+6 -1
View File
@@ -1562,7 +1562,12 @@
</p>
<div style="margin-bottom: 1rem">
<label style="display: block; margin-bottom: 0.5rem; font-size: 0.9rem">PocketBase URL</label>
<input type="url" id="custom-pb-url" class="template-input" placeholder="https://data.monochrome.st" />
<input
type="url"
id="custom-pb-url"
class="template-input"
placeholder="https://data.monochrome.st"
/>
</div>
<div style="margin-bottom: 1rem">
<label style="display: block; margin-bottom: 0.5rem; font-size: 0.9rem">Auth Endpoint</label>