add custom last.fm api credential support
This commit is contained in:
parent
61551c2218
commit
19baee21aa
4 changed files with 218 additions and 2 deletions
59
index.html
59
index.html
|
|
@ -2620,6 +2620,65 @@
|
||||||
<span class="slider"></span>
|
<span class="slider"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item" id="lastfm-custom-creds-toggle-setting" style="display: none">
|
||||||
|
<div class="info">
|
||||||
|
<span class="label">Use Custom API Credentials</span>
|
||||||
|
<span class="description">Use your own Last.fm API key and secret</span>
|
||||||
|
</div>
|
||||||
|
<label class="toggle-switch">
|
||||||
|
<input type="checkbox" id="lastfm-custom-creds-toggle" />
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item" id="lastfm-custom-creds-setting" style="display: none">
|
||||||
|
<div class="info" style="flex: 1; min-width: 0">
|
||||||
|
<span class="label">Custom API Credentials</span>
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 8px; margin-top: 8px">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="lastfm-custom-api-key"
|
||||||
|
placeholder="API Key"
|
||||||
|
style="
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
background: var(--background);
|
||||||
|
color: var(--foreground);
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
id="lastfm-custom-api-secret"
|
||||||
|
placeholder="API Secret"
|
||||||
|
style="
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
background: var(--background);
|
||||||
|
color: var(--foreground);
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<div style="display: flex; gap: 8px; margin-top: 4px">
|
||||||
|
<button
|
||||||
|
id="lastfm-save-custom-creds"
|
||||||
|
class="btn-secondary"
|
||||||
|
style="padding: 6px 12px; font-size: 0.85rem"
|
||||||
|
>
|
||||||
|
Save Credentials
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
id="lastfm-clear-custom-creds"
|
||||||
|
class="btn-secondary danger"
|
||||||
|
style="padding: 6px 12px; font-size: 0.85rem; display: none"
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="settings-group">
|
<div class="settings-group">
|
||||||
|
|
|
||||||
19
js/lastfm.js
19
js/lastfm.js
|
|
@ -3,8 +3,8 @@ import { lastFMStorage } from './storage.js';
|
||||||
|
|
||||||
export class LastFMScrobbler {
|
export class LastFMScrobbler {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.API_KEY = '85214f5abbc730e78770f27784b9bdf7';
|
this.DEFAULT_API_KEY = '85214f5abbc730e78770f27784b9bdf7';
|
||||||
this.API_SECRET = '2c2c37fd86739191860db810dd063292';
|
this.DEFAULT_API_SECRET = '2c2c37fd86739191860db810dd063292';
|
||||||
this.API_URL = 'https://ws.audioscrobbler.com/2.0/';
|
this.API_URL = 'https://ws.audioscrobbler.com/2.0/';
|
||||||
|
|
||||||
this.sessionKey = null;
|
this.sessionKey = null;
|
||||||
|
|
@ -15,9 +15,24 @@ export class LastFMScrobbler {
|
||||||
this.hasScrobbled = false;
|
this.hasScrobbled = false;
|
||||||
this.isScrobbling = false;
|
this.isScrobbling = false;
|
||||||
|
|
||||||
|
this.loadCredentials();
|
||||||
this.loadSession();
|
this.loadSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadCredentials() {
|
||||||
|
if (lastFMStorage.useCustomCredentials()) {
|
||||||
|
this.API_KEY = lastFMStorage.getCustomApiKey() || this.DEFAULT_API_KEY;
|
||||||
|
this.API_SECRET = lastFMStorage.getCustomApiSecret() || this.DEFAULT_API_SECRET;
|
||||||
|
} else {
|
||||||
|
this.API_KEY = this.DEFAULT_API_KEY;
|
||||||
|
this.API_SECRET = this.DEFAULT_API_SECRET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reloadCredentials() {
|
||||||
|
this.loadCredentials();
|
||||||
|
}
|
||||||
|
|
||||||
loadSession() {
|
loadSession() {
|
||||||
try {
|
try {
|
||||||
const session = localStorage.getItem('lastfm-session');
|
const session = localStorage.getItem('lastfm-session');
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,13 @@ export function initializeSettings(scrobbler, player, api, ui) {
|
||||||
const lastfmToggleSetting = document.getElementById('lastfm-toggle-setting');
|
const lastfmToggleSetting = document.getElementById('lastfm-toggle-setting');
|
||||||
const lastfmLoveToggle = document.getElementById('lastfm-love-toggle');
|
const lastfmLoveToggle = document.getElementById('lastfm-love-toggle');
|
||||||
const lastfmLoveSetting = document.getElementById('lastfm-love-setting');
|
const lastfmLoveSetting = document.getElementById('lastfm-love-setting');
|
||||||
|
const lastfmCustomCredsToggle = document.getElementById('lastfm-custom-creds-toggle');
|
||||||
|
const lastfmCustomCredsToggleSetting = document.getElementById('lastfm-custom-creds-toggle-setting');
|
||||||
|
const lastfmCustomCredsSetting = document.getElementById('lastfm-custom-creds-setting');
|
||||||
|
const lastfmCustomApiKey = document.getElementById('lastfm-custom-api-key');
|
||||||
|
const lastfmCustomApiSecret = document.getElementById('lastfm-custom-api-secret');
|
||||||
|
const lastfmSaveCustomCreds = document.getElementById('lastfm-save-custom-creds');
|
||||||
|
const lastfmClearCustomCreds = document.getElementById('lastfm-clear-custom-creds');
|
||||||
|
|
||||||
function updateLastFMUI() {
|
function updateLastFMUI() {
|
||||||
if (scrobbler.lastfm.isAuthenticated()) {
|
if (scrobbler.lastfm.isAuthenticated()) {
|
||||||
|
|
@ -132,12 +139,30 @@ export function initializeSettings(scrobbler, player, api, ui) {
|
||||||
lastfmLoveSetting.style.display = 'flex';
|
lastfmLoveSetting.style.display = 'flex';
|
||||||
lastfmToggle.checked = lastFMStorage.isEnabled();
|
lastfmToggle.checked = lastFMStorage.isEnabled();
|
||||||
lastfmLoveToggle.checked = lastFMStorage.shouldLoveOnLike();
|
lastfmLoveToggle.checked = lastFMStorage.shouldLoveOnLike();
|
||||||
|
lastfmCustomCredsToggleSetting.style.display = 'flex';
|
||||||
|
lastfmCustomCredsToggle.checked = lastFMStorage.useCustomCredentials();
|
||||||
|
updateCustomCredsUI();
|
||||||
} else {
|
} else {
|
||||||
lastfmStatus.textContent = 'Connect your Last.fm account to scrobble tracks';
|
lastfmStatus.textContent = 'Connect your Last.fm account to scrobble tracks';
|
||||||
lastfmConnectBtn.textContent = 'Connect Last.fm';
|
lastfmConnectBtn.textContent = 'Connect Last.fm';
|
||||||
lastfmConnectBtn.classList.remove('danger');
|
lastfmConnectBtn.classList.remove('danger');
|
||||||
lastfmToggleSetting.style.display = 'none';
|
lastfmToggleSetting.style.display = 'none';
|
||||||
lastfmLoveSetting.style.display = 'none';
|
lastfmLoveSetting.style.display = 'none';
|
||||||
|
lastfmCustomCredsToggleSetting.style.display = 'none';
|
||||||
|
lastfmCustomCredsSetting.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCustomCredsUI() {
|
||||||
|
const useCustom = lastFMStorage.useCustomCredentials();
|
||||||
|
lastfmCustomCredsSetting.style.display = useCustom ? 'flex' : 'none';
|
||||||
|
|
||||||
|
if (useCustom) {
|
||||||
|
lastfmCustomApiKey.value = lastFMStorage.getCustomApiKey();
|
||||||
|
lastfmCustomApiSecret.value = lastFMStorage.getCustomApiSecret();
|
||||||
|
|
||||||
|
const hasCreds = lastFMStorage.getCustomApiKey() && lastFMStorage.getCustomApiSecret();
|
||||||
|
lastfmClearCustomCreds.style.display = hasCreds ? 'inline-block' : 'none';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,6 +248,78 @@ export function initializeSettings(scrobbler, player, api, ui) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Custom Credentials Toggle
|
||||||
|
if (lastfmCustomCredsToggle) {
|
||||||
|
lastfmCustomCredsToggle.addEventListener('change', (e) => {
|
||||||
|
lastFMStorage.setUseCustomCredentials(e.target.checked);
|
||||||
|
updateCustomCredsUI();
|
||||||
|
|
||||||
|
// Reload credentials in the scrobbler
|
||||||
|
scrobbler.lastfm.reloadCredentials();
|
||||||
|
|
||||||
|
// If credentials are being disabled, clear any existing session
|
||||||
|
if (!e.target.checked && scrobbler.lastfm.isAuthenticated()) {
|
||||||
|
scrobbler.lastfm.disconnect();
|
||||||
|
updateLastFMUI();
|
||||||
|
alert('Switched to default API credentials. Please reconnect to Last.fm.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save Custom Credentials
|
||||||
|
if (lastfmSaveCustomCreds) {
|
||||||
|
lastfmSaveCustomCreds.addEventListener('click', () => {
|
||||||
|
const apiKey = lastfmCustomApiKey.value.trim();
|
||||||
|
const apiSecret = lastfmCustomApiSecret.value.trim();
|
||||||
|
|
||||||
|
if (!apiKey || !apiSecret) {
|
||||||
|
alert('Please enter both API Key and API Secret');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastFMStorage.setCustomApiKey(apiKey);
|
||||||
|
lastFMStorage.setCustomApiSecret(apiSecret);
|
||||||
|
|
||||||
|
// Reload credentials
|
||||||
|
scrobbler.lastfm.reloadCredentials();
|
||||||
|
|
||||||
|
updateCustomCredsUI();
|
||||||
|
alert('Custom API credentials saved! Please reconnect to Last.fm to use them.');
|
||||||
|
|
||||||
|
// Disconnect current session if authenticated
|
||||||
|
if (scrobbler.lastfm.isAuthenticated()) {
|
||||||
|
scrobbler.lastfm.disconnect();
|
||||||
|
updateLastFMUI();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear Custom Credentials
|
||||||
|
if (lastfmClearCustomCreds) {
|
||||||
|
lastfmClearCustomCreds.addEventListener('click', () => {
|
||||||
|
if (confirm('Clear custom API credentials?')) {
|
||||||
|
lastFMStorage.clearCustomCredentials();
|
||||||
|
lastfmCustomApiKey.value = '';
|
||||||
|
lastfmCustomApiSecret.value = '';
|
||||||
|
lastfmCustomCredsToggle.checked = false;
|
||||||
|
|
||||||
|
// Reload credentials
|
||||||
|
scrobbler.lastfm.reloadCredentials();
|
||||||
|
|
||||||
|
updateCustomCredsUI();
|
||||||
|
|
||||||
|
// Disconnect current session if authenticated
|
||||||
|
if (scrobbler.lastfm.isAuthenticated()) {
|
||||||
|
scrobbler.lastfm.disconnect();
|
||||||
|
updateLastFMUI();
|
||||||
|
alert(
|
||||||
|
'Custom credentials cleared. Switched to default API credentials. Please reconnect to Last.fm.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// ========================================
|
// ========================================
|
||||||
// Global Scrobble Settings
|
// Global Scrobble Settings
|
||||||
// ========================================
|
// ========================================
|
||||||
|
|
|
||||||
|
|
@ -282,6 +282,9 @@ export const lastFMStorage = {
|
||||||
STORAGE_KEY: 'lastfm-enabled',
|
STORAGE_KEY: 'lastfm-enabled',
|
||||||
LOVE_ON_LIKE_KEY: 'lastfm-love-on-like',
|
LOVE_ON_LIKE_KEY: 'lastfm-love-on-like',
|
||||||
SCROBBLE_PERCENTAGE_KEY: 'lastfm-scrobble-percentage',
|
SCROBBLE_PERCENTAGE_KEY: 'lastfm-scrobble-percentage',
|
||||||
|
CUSTOM_API_KEY: 'lastfm-custom-api-key',
|
||||||
|
CUSTOM_API_SECRET: 'lastfm-custom-api-secret',
|
||||||
|
USE_CUSTOM_CREDENTIALS_KEY: 'lastfm-use-custom-credentials',
|
||||||
|
|
||||||
isEnabled() {
|
isEnabled() {
|
||||||
try {
|
try {
|
||||||
|
|
@ -320,6 +323,48 @@ export const lastFMStorage = {
|
||||||
const validPercentage = Math.max(1, Math.min(100, parseInt(percentage, 10) || 75));
|
const validPercentage = Math.max(1, Math.min(100, parseInt(percentage, 10) || 75));
|
||||||
localStorage.setItem(this.SCROBBLE_PERCENTAGE_KEY, validPercentage.toString());
|
localStorage.setItem(this.SCROBBLE_PERCENTAGE_KEY, validPercentage.toString());
|
||||||
},
|
},
|
||||||
|
|
||||||
|
useCustomCredentials() {
|
||||||
|
try {
|
||||||
|
return localStorage.getItem(this.USE_CUSTOM_CREDENTIALS_KEY) === 'true';
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setUseCustomCredentials(enabled) {
|
||||||
|
localStorage.setItem(this.USE_CUSTOM_CREDENTIALS_KEY, enabled ? 'true' : 'false');
|
||||||
|
},
|
||||||
|
|
||||||
|
getCustomApiKey() {
|
||||||
|
try {
|
||||||
|
return localStorage.getItem(this.CUSTOM_API_KEY) || '';
|
||||||
|
} catch {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setCustomApiKey(key) {
|
||||||
|
localStorage.setItem(this.CUSTOM_API_KEY, key);
|
||||||
|
},
|
||||||
|
|
||||||
|
getCustomApiSecret() {
|
||||||
|
try {
|
||||||
|
return localStorage.getItem(this.CUSTOM_API_SECRET) || '';
|
||||||
|
} catch {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setCustomApiSecret(secret) {
|
||||||
|
localStorage.setItem(this.CUSTOM_API_SECRET, secret);
|
||||||
|
},
|
||||||
|
|
||||||
|
clearCustomCredentials() {
|
||||||
|
localStorage.removeItem(this.CUSTOM_API_KEY);
|
||||||
|
localStorage.removeItem(this.CUSTOM_API_SECRET);
|
||||||
|
localStorage.removeItem(this.USE_CUSTOM_CREDENTIALS_KEY);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const nowPlayingSettings = {
|
export const nowPlayingSettings = {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue