| 
									
										
										
										
											2023-07-13 15:33:59 +00:00
										 |  |  | const rpc = require("discord-rpc"); | 
					
						
							|  |  |  | const fetch = require("request-promise"); | 
					
						
							|  |  |  | const prettyMilliseconds = require("pretty-ms"); | 
					
						
							|  |  |  | const fs = require("fs"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const config = JSON.parse(fs.readFileSync("config.json")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const updateInterval = 5000; | 
					
						
							|  |  |  | const retryInterval = 30000; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | let rp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function formatNumber(number) { | 
					
						
							|  |  |  |   var x = number.split("."); | 
					
						
							|  |  |  |   var x1 = x[0]; | 
					
						
							|  |  |  |   var x2 = x.length > 1 ? "." + x[1] : ""; | 
					
						
							|  |  |  |   var rgx = /(\d+)(\d{3})/; | 
					
						
							|  |  |  |   while (rgx.test(x1)) { | 
					
						
							|  |  |  |     x1 = x1.replace(rgx, "$1" + "," + "$2"); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return x1 + x2; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function createClient() { | 
					
						
							|  |  |  |   rp = new rpc.Client({ transport: "ipc" }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   rp.on("ready", () => { | 
					
						
							|  |  |  |     console.log("Connected to Discord!"); | 
					
						
							|  |  |  |     updateStatus(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   rp.on("disconnected", () => { | 
					
						
							|  |  |  |     console.log("Disconnected from Discord!"); | 
					
						
							|  |  |  |     rp = null; | 
					
						
							|  |  |  |     setTimeout(createClient, retryInterval); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   rp.login({ clientId: config.clientId }).catch((error) => { | 
					
						
							|  |  |  |     console.error("Error connecting to Discord:", error); | 
					
						
							|  |  |  |     rp = null; | 
					
						
							|  |  |  |     setTimeout(createClient, retryInterval); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | createClient(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | async function updateStatus() { | 
					
						
							|  |  |  |   try { | 
					
						
							|  |  |  |     const data = await fetchCurrentScrobble(config.username); | 
					
						
							|  |  |  |     if (!data || !rp) { | 
					
						
							|  |  |  |       console.log("Reconnecting to Discord..."); | 
					
						
							|  |  |  |       setTimeout(updateStatus, retryInterval); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     await rp.setActivity({ | 
					
						
							|  |  |  |       largeImageKey: data.album !== "Unknown Album" ? data.cover : "default_cover", | 
					
						
							|  |  |  |       largeImageText: `${data.playcount} plays.`, | 
					
						
							|  |  |  |       smallImageKey: data.whenScrobbled ? "playing" : "stopped", | 
					
						
							|  |  |  |       smallImageText: data.scrobbleStatus, | 
					
						
							|  |  |  |       details: data.trackName, | 
					
						
							|  |  |  |       state: `${data.artist} - ${data.album}`, | 
					
						
							|  |  |  |       buttons: [ | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2023-07-13 14:36:18 -04:00
										 |  |  | 	        label: `${formatNumber(data.scrobbles)} ${config.label}`, | 
					
						
							|  |  |  | 	        url: JSON.parse(config.clickable) ? `https://www.last.fm/user/${config.username}/` : "javascript:void(0);" | 
					
						
							| 
									
										
										
										
											2023-07-13 15:33:59 +00:00
										 |  |  |         }, | 
					
						
							|  |  |  |       ], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     console.log("Discord status updated."); | 
					
						
							|  |  |  |     setTimeout(updateStatus, updateInterval); | 
					
						
							|  |  |  |   } catch (error) { | 
					
						
							|  |  |  |     console.error("Failed to update status:", error); | 
					
						
							|  |  |  |     rp = null; | 
					
						
							|  |  |  |     setTimeout(updateStatus, retryInterval); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | async function fetchCurrentScrobble(user) { | 
					
						
							|  |  |  |   try { | 
					
						
							|  |  |  |     const optionsGetTrack = { | 
					
						
							|  |  |  |       uri: "http://ws.audioscrobbler.com/2.0/", | 
					
						
							|  |  |  |       json: true, | 
					
						
							|  |  |  |       qs: { | 
					
						
							|  |  |  |         method: "user.getrecenttracks", | 
					
						
							|  |  |  |         user: user, | 
					
						
							|  |  |  |         api_key: config.apiKey, | 
					
						
							|  |  |  |         format: "json", | 
					
						
							|  |  |  |         limit: "1", | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const lastTrack = await fetch(optionsGetTrack); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let lastArtist = lastTrack.recenttracks.track[0].artist["#text"]; | 
					
						
							|  |  |  |     let lastTrackName = lastTrack.recenttracks.track[0].name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const options = { | 
					
						
							|  |  |  |       uri: "http://ws.audioscrobbler.com/2.0/", | 
					
						
							|  |  |  |       json: true, | 
					
						
							|  |  |  |       qs: { | 
					
						
							|  |  |  |         method: "track.getInfo", | 
					
						
							|  |  |  |         user: user, | 
					
						
							|  |  |  |         track: lastTrackName, | 
					
						
							|  |  |  |         artist: lastArtist, | 
					
						
							|  |  |  |         api_key: config.apiKey, | 
					
						
							|  |  |  |         format: "json", | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const rData = await fetch(options); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let images = lastTrack.recenttracks.track[0].image; | 
					
						
							|  |  |  |     let coverURL = images && images[images.length - 1]["#text"].trim() ? images[images.length - 1]["#text"].trim() : "default_cover"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const data = { | 
					
						
							|  |  |  |       artist: lastArtist, | 
					
						
							|  |  |  |       album: lastTrack.recenttracks.track[0].album["#text"] || "Unknown Album", | 
					
						
							|  |  |  |       trackName: lastTrackName, | 
					
						
							|  |  |  |       playcount: rData.track.userplaycount ? rData.track.userplaycount : "0", | 
					
						
							|  |  |  |       scrobbles: lastTrack.recenttracks["@attr"].total, | 
					
						
							|  |  |  |       whenScrobbled: lastTrack.recenttracks.track[0]["@attr"], | 
					
						
							|  |  |  |       scrobbleStatus: !lastTrack.recenttracks.track[0]["@attr"] ? `Last scrobbled ${prettyMilliseconds(Date.now() - lastTrack.recenttracks.track[0].date.uts * 1000)} ago.` : "Now scrobbling.", | 
					
						
							|  |  |  |       cover: coverURL, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return data; | 
					
						
							|  |  |  |   } catch (error) { | 
					
						
							|  |  |  |     console.error("Failed to fetch current scrobble:", error); | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |