diff --git a/README.md b/README.md index c22a0e0..1612601 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Pipris ![Version 0.0.3](https://img.shields.io/badge/version-0.0.3-blue) +# Pipris ![Version 0.1.0](https://img.shields.io/badge/version-0.1.0-blue) Pipris is an extensible MPRIS scrobbler written with Deno. It was originally created for [teal.fm](https://teal.fm), but can be extended to support a wide variety of diff --git a/src/index.js b/src/index.js index 0fbc8b3..8cf175f 100644 --- a/src/index.js +++ b/src/index.js @@ -94,7 +94,7 @@ let cleanupWatch = null; let currentTrackId = null; let currentPlayedTime = null; -async function emitCurrentState() { +async function emitCurrentState(overridePositionUs, seeked = false) { if (!activePlayer) return; try { @@ -113,10 +113,11 @@ async function emitCurrentState() { const data = formatTrackData( metadata, playbackStatus, - positionUs, + overridePositionUs ?? positionUs, currentPlayedTime, ); if (data) { + data.seeked = seeked; callModules(data); } } catch (err) { @@ -154,8 +155,8 @@ async function attachToPlayer(playerName) { await emitCurrentState(); } }, - async (_positionUs) => { - await emitCurrentState(); + async (positionUs) => { + await emitCurrentState(positionUs, true); }, ); } diff --git a/src/modules/discord.js b/src/modules/discord.js index c01efa7..142139c 100644 --- a/src/modules/discord.js +++ b/src/modules/discord.js @@ -73,7 +73,7 @@ export async function onData(data) { const artistString = data.artists.map((a) => a.artistName).join(", "); const paused = data.playbackStatus !== "Playing"; - function buildActivity(imageUrl) { + function buildActivity(imageUrl, forceNoTimestamps = false) { const activity = new ActivityStatus( config.name ?? "Music", ActivityType.LISTENING, @@ -82,7 +82,7 @@ export async function onData(data) { activity.setState(paused ? "Paused" : `by ${artistString}`); activity.setStatusDisplayType(DisplayType.DETAILS); - if (!paused) { + if (!paused && !forceNoTimestamps) { const endMs = new Date(data.expiry).getTime(); const startMs = endMs - data.duration * 1000; activity.setTimestamps({ @@ -108,8 +108,21 @@ export async function onData(data) { // Use cached URL if available, otherwise fallback const artUrl = data.artUrl || lastArtUrl; const cachedUrl = getCachedArtUrl(artUrl); + + // On seek, send a completely different activity so Discord resets timestamps + if (data.seeked && !paused) { + try { + client.setActivity( + new ActivityStatus("Idle", ActivityType.LISTENING), + ); + } catch { + // ignore + } + await new Promise((r) => setTimeout(r, 250)); + } + try { - client.setActivity(buildActivity(cachedUrl)); + client.setActivity(buildActivity(cachedUrl, false)); } catch (err) { console.error(`[discord] Failed to set activity: ${err.message}`); } @@ -119,7 +132,7 @@ export async function onData(data) { uploadArt(artUrl).then((url) => { if (url && client) { try { - client.setActivity(buildActivity(url)); + client.setActivity(buildActivity(url, false)); } catch { // ignore } diff --git a/src/modules/teal.js b/src/modules/teal.js index b5945f4..cc21d3e 100644 --- a/src/modules/teal.js +++ b/src/modules/teal.js @@ -1,7 +1,7 @@ import { Client } from "@atcute/client"; import { PasswordSession } from "@atcute/password-session"; -const AGENT_STRING = "pipris/0.0.3 (https://tangled.org/clay.rip/pipris)"; +const AGENT_STRING = "pipris/0.1.0 (https://tangled.org/clay.rip/pipris)"; const PLAY_FINISH_TOLERANCE_MS = 5000; let rpc;