Pipris is an extensible MPRIS scrobbler written with Deno.
at main 65 lines 2.0 kB view raw
1const TEN_MINUTES_MS = 10 * 60 * 1000; 2 3/** 4 * Build the data object expected by the stub module. 5 * 6 * @param {object} metadata Raw MPRIS Metadata dict 7 * @param {string} playbackStatus "Playing" | "Paused" | "Stopped" 8 * @param {number} positionUs Current position in microseconds 9 * @param {string} playedTime ISO timestamp of when the track was first seen 10 * @returns {object|null} Formatted data, or null if metadata is missing 11 */ 12export function formatTrackData(metadata, playbackStatus, positionUs, playedTime) { 13 const title = metaString(metadata, "xesam:title"); 14 if (!title) return null; 15 16 const artistList = metaStringArray(metadata, "xesam:artist"); 17 const album = metaString(metadata, "xesam:album") ?? ""; 18 const artUrl = metaString(metadata, "mpris:artUrl") ?? ""; 19 const lengthUs = metaInt(metadata, "mpris:length") ?? 0; 20 21 const now = Date.now(); 22 const positionMs = Math.floor(positionUs / 1000); 23 const lengthMs = Math.floor(lengthUs / 1000); 24 25 let expiry; 26 if (playbackStatus === "Paused") { 27 expiry = new Date(now + TEN_MINUTES_MS).toISOString(); 28 } else { 29 const remainingMs = Math.max(0, lengthMs - positionMs); 30 expiry = new Date(now + remainingMs).toISOString(); 31 } 32 33 return { 34 artists: artistList.map((name) => ({ artistName: name })), 35 trackName: title, 36 playbackStatus, 37 playedTime, 38 releaseName: album, 39 artUrl, 40 duration: Math.round(lengthMs / 1000), 41 expiry, 42 }; 43} 44 45// --- helpers for reading dbus-next Variant values ---- 46 47function metaString(metadata, key) { 48 const v = metadata[key]; 49 if (!v) return undefined; 50 return typeof v.value === "string" ? v.value : String(v.value); 51} 52 53function metaStringArray(metadata, key) { 54 const v = metadata[key]; 55 if (!v) return []; 56 const arr = v.value; 57 return Array.isArray(arr) ? arr.map(String) : [String(arr)]; 58} 59 60function metaInt(metadata, key) { 61 const v = metadata[key]; 62 if (!v) return undefined; 63 const n = Number(v.value); 64 return Number.isFinite(n) ? n : undefined; 65}