Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨🐛 Add Scobble percent & Fix Last.fm login #1286

5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "esbenp.prettier-vscode",
"cSpell.words": [
jaredcat marked this conversation as resolved.
Show resolved Hide resolved
"scrobble"
]
}
8 changes: 7 additions & 1 deletion src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,8 @@ const store = new Conf<StoreSchema>({
api_key: "2a69bcf769a7a28a8bf2f6a5100accad",
secret: "46eea23770a459a49eb4d26cbf46b41c",
token: null,
sessionKey: null
sessionKey: null,
scrobblePercent: 50
Alipoodle marked this conversation as resolved.
Show resolved Hide resolved
},
developer: {
enableDevTools: false
Expand All @@ -384,6 +385,11 @@ const store = new Conf<StoreSchema>({
if (!store.has("appearance.zoom")) {
store.set("appearance.zoom", 100);
}
},
">=2.0.1": store => {
if (!store.has("lastfm.scrobblePercent")) {
store.set("lastfm.scrobblePercent", 50);
}
}
}
});
Expand Down
26 changes: 18 additions & 8 deletions src/main/integrations/last-fm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ export default class LastFM implements IIntegration {
const response = await fetch(`https://ws.audioscrobbler.com/2.0/` + `?${this.createQueryString(params, api_sig)}`);

const json = (await response.json()) as LastfmSessionResponse;

if (json.error) {
await this.authenticateUser();
} else if (json.session) {
Expand Down Expand Up @@ -95,16 +94,23 @@ export default class LastFM implements IIntegration {

clearTimeout(this.scrobbleTimer);

// Track must be longer than 30 seconds
// https://www.last.fm/api/scrobbling "When is a scrobble a scrobble?"
if (state.videoDetails.durationSeconds < 30) {
return;
}

this.updateNowPlaying(state.videoDetails);

this.lastfmDetails.scrobblePercent = this.store.get("lastfm.scrobblePercent");
const scrobblePercentDecimal = this.lastfmDetails.scrobblePercent / 100;
const scrobbleTimeRequired = Math.min(
// Scrobble the track if it has been played for more than 50% of its duration
Math.round(state.videoDetails.durationSeconds / 2),
// OR if it has been played for more than 4 minutes
// Scrobble the track if it has been played to the percent picked by the user
Math.round(state.videoDetails.durationSeconds * scrobblePercentDecimal),
// OR if it has been played for more than 4 minutes, scrobble maximum time: https://www.last.fm/api/scrobbling
240
);
const scrobbleTime = new Date().getTime();

this.scrobbleTimer = setTimeout(() => {
this.scrobbleSong(state.videoDetails, scrobbleTime);
}, scrobbleTimeRequired * 1000);
Expand Down Expand Up @@ -295,9 +301,13 @@ export default class LastFM implements IIntegration {

private async saveSettings(): Promise<void> {
try {
this.store.set("lastfm.sessionKey", safeStorage.encryptString(this.lastfmDetails.sessionKey).toString("hex"));
this.store.set("lastfm.token", safeStorage.encryptString(this.lastfmDetails.token).toString("hex"));
} catch {
if (this.lastfmDetails.sessionKey) {
this.store.set("lastfm.sessionKey", safeStorage.encryptString(this.lastfmDetails.sessionKey).toString("hex"));
}
Alipoodle marked this conversation as resolved.
Show resolved Hide resolved
if (this.lastfmDetails.token) {
this.store.set("lastfm.token", safeStorage.encryptString(this.lastfmDetails.token).toString("hex"));
}
} catch (error) {
// Do nothing, the values are not valid and can be ignored
}
}
Expand Down
24 changes: 24 additions & 0 deletions src/renderer/windows/settings/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ const shortcutVolumeUp = ref<string>(shortcuts.volumeUp);
const shortcutVolumeDown = ref<string>(shortcuts.volumeDown);

const lastFMSessionKey = ref<string>(lastFM.sessionKey);
const scrobblePercent = ref<number>(lastFM.scrobblePercent);

store.onDidAnyChange(async newState => {
disableHardwareAcceleration.value = newState.general.disableHardwareAcceleration;
Expand All @@ -94,6 +95,8 @@ store.onDidAnyChange(async newState => {
companionServerCORSWildcardEnabled.value = newState.integrations.companionServerCORSWildcardEnabled;
discordPresenceEnabled.value = newState.integrations.discordPresenceEnabled;
lastFMEnabled.value = newState.integrations.lastFMEnabled;
lastFMSessionKey.value = newState.lastfm.sessionKey;
scrobblePercent.value = newState.lastfm.scrobblePercent;

shortcutPlayPause.value = newState.shortcuts.playPause;
shortcutNext.value = newState.shortcuts.next;
Expand Down Expand Up @@ -161,6 +164,7 @@ async function settingsChanged() {
store.set("integrations.companionServerCORSWildcardEnabled", companionServerCORSWildcardEnabled.value);
store.set("integrations.discordPresenceEnabled", discordPresenceEnabled.value);
store.set("integrations.lastFMEnabled", lastFMEnabled.value);
store.set("lastfm.scrobblePercent", scrobblePercent.value);

store.set("shortcuts.playPause", shortcutPlayPause.value);
store.set("shortcuts.next", shortcutNext.value);
Expand Down Expand Up @@ -229,6 +233,13 @@ function checkForUpdates() {
checkingForUpdate.value = true;
}

async function logoutLastFM() {
store.set("lastfm.sessionKey", null);
lastFMEnabled.value = false;
lastFMSessionKey.value = null;
await settingsChanged();
}

window.ytmd.handleCheckingForUpdate(() => {
checkingForUpdate.value = true;
});
Expand Down Expand Up @@ -399,7 +410,20 @@ window.ytmd.handleUpdateDownloaded(() => {
<span v-else style="color: #ff1100">No</span>
</p>
</div>
<button v-if="lastFMSessionKey" @click="logoutLastFM">Logout</button>
</div>
<YTMDSetting
v-if="lastFMEnabled"
v-model="scrobblePercent"
class="settings indented"
type="range"
name="Scrobble percent"
description="Determines when a song is scrobbled"
min="50"
max="95"
step="5"
@change="settingsChanged"
/>
</div>

<div v-if="currentTab === 5" class="shortcuts-tab">
Expand Down
11 changes: 6 additions & 5 deletions src/shared/store/schema.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export type StoreSchema = {
metadata: {
version: 1
}
version: 1;
};
general: {
disableHardwareAcceleration: boolean;
hideToTrayOnClose: boolean;
Expand Down Expand Up @@ -50,14 +50,15 @@ export type StoreSchema = {
secret: string;
token: string | null;
sessionKey: string | null;
scrobblePercent: number;
};
developer: {
enableDevTools: boolean
}
enableDevTools: boolean;
};
};

export type MemoryStoreSchema = {
discordPresenceConnectionFailed: boolean
discordPresenceConnectionFailed: boolean;
shortcutsPlayPauseRegisterFailed: boolean;
shortcutsNextRegisterFailed: boolean;
shortcutsPreviousRegisterFailed: boolean;
Expand Down