presence.ts 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. const presence = new Presence({
  2. clientId: "1273851679191728160",
  3. }),
  4. strings = presence.getStrings({
  5. play: "general.playing",
  6. pause: "general.paused",
  7. live: "general.live",
  8. }),
  9. baseImage =
  10. "https://cdn.rcd.gg/PreMiD/websites/I/iHeartRadio/assets/logo.png";
  11. function checkLength(string: string): string {
  12. if (string.length > 128) return `${string.substring(0, 125)}...`;
  13. else return string;
  14. }
  15. /**
  16. * @param {string} stationName
  17. * @returns {string|null}
  18. */
  19. async function getStationDesc(stationName: string) {
  20. const stationInfoReq = await fetch(
  21. `https://api.iheart.com/api/v2/content/liveStations?q=${new URLSearchParams(
  22. stationName
  23. )}`
  24. ),
  25. stationInfoRes = await stationInfoReq.json();
  26. if (stationInfoRes.total === 0) return null;
  27. return stationInfoRes.hits[0].description;
  28. }
  29. let stationDescription: string | null = null;
  30. presence.on("UpdateData", async () => {
  31. const presenceData: PresenceData = {
  32. largeImageKey: baseImage,
  33. details: "Browsing iHeartRadio...",
  34. };
  35. if (document.location.href.includes("www.iheart.com")) {
  36. switch (document.location.pathname) {
  37. case "/for-you/": {
  38. presenceData.details = "Viewing For You";
  39. break;
  40. }
  41. case "/your-library/": {
  42. presenceData.details = "Viewing Library";
  43. break;
  44. }
  45. case "/your-library/recently-played/": {
  46. presenceData.details = "Viewing Recently Played Library";
  47. break;
  48. }
  49. case "/your-library/saved-stations/": {
  50. presenceData.details = "Viewing Saved Stations Library";
  51. break;
  52. }
  53. case "/your-library/podcasts/": {
  54. presenceData.details = "Viewing Podcasts Library";
  55. break;
  56. }
  57. case "/your-library/playlists/": {
  58. presenceData.details = "Viewing Playlists Library";
  59. break;
  60. }
  61. case "/artist/": {
  62. presenceData.details = "Viewing Popular Artists";
  63. break;
  64. }
  65. case "/artist/genre/alternative/": {
  66. presenceData.details = "Viewing Alternative Artists";
  67. break;
  68. }
  69. case "/artist/genre/christian-gospel/": {
  70. presenceData.details = "Viewing Christian & Gospel Artists";
  71. break;
  72. }
  73. case "/artist/genre/classic-rock/": {
  74. presenceData.details = "Viewing Classic Rock Artists";
  75. break;
  76. }
  77. case "/artist/genre/classical/": {
  78. presenceData.details = "Viewing Classical Artists";
  79. break;
  80. }
  81. case "/artist/genre/college-radio/": {
  82. presenceData.details = "Viewing College Radio Artists";
  83. break;
  84. }
  85. case "/artist/genre/comedy/": {
  86. presenceData.details = "Viewing Comedy Artists";
  87. break;
  88. }
  89. case "/artist/genre/country/": {
  90. presenceData.details = "Viewing Country Artists";
  91. break;
  92. }
  93. case "/artist/genre/dance-electronic/": {
  94. presenceData.details = "Viewing Dance & Electronic Artists";
  95. break;
  96. }
  97. case "/artist/genre/hip-hop/": {
  98. presenceData.details = "Viewing Hip-Hop Artists";
  99. break;
  100. }
  101. case "/artist/genre/jazz-blues/": {
  102. presenceData.details = "Viewing Jazz & Blues Artists";
  103. break;
  104. }
  105. case "/artist/genre/kids-family/": {
  106. presenceData.details = "Viewing Kids & Family Artists";
  107. break;
  108. }
  109. case "/artist/genre/latin/": {
  110. presenceData.details = "Viewing Latin Artists";
  111. break;
  112. }
  113. case "/artist/genre/mix-variety/": {
  114. presenceData.details = "Viewing Mix & Variety Artists";
  115. break;
  116. }
  117. case "/artist/genre/oldies-classic-hits/": {
  118. presenceData.details = "Viewing Oldies & Classic Hits Artists";
  119. break;
  120. }
  121. case "/artist/genre/public-radio/": {
  122. presenceData.details = "Viewing Public Radio Artists";
  123. break;
  124. }
  125. case "/artist/genre/rb-throwbacks/": {
  126. presenceData.details = "Viewing R&B & Throwbacks Artists";
  127. break;
  128. }
  129. case "/artist/genre/reggae-island/": {
  130. presenceData.details = "Viewing Reggae & Island Artists";
  131. break;
  132. }
  133. case "/artist/genre/rock/": {
  134. presenceData.details = "Viewing Rock Artists";
  135. break;
  136. }
  137. case "/artist/genre/soft-rock/": {
  138. presenceData.details = "Viewing Soft Rock Artists";
  139. break;
  140. }
  141. case "/artist/genre/top-40-pop/": {
  142. presenceData.details = "Viewing Top 40 & Pop Artists";
  143. break;
  144. }
  145. case "/playlist/": {
  146. presenceData.details = "Viewing Playlists";
  147. break;
  148. }
  149. }
  150. if (
  151. (document.location.href.includes("live") &&
  152. document.querySelector('div[data-test="hero-container"]') &&
  153. !document.location.href.includes("/live/country/")) ||
  154. (document.location.href.includes("live") &&
  155. document.querySelector('div[data-test="hero-container"]') &&
  156. document.location.pathname !== "/live/")
  157. ) {
  158. const stationName = document
  159. .querySelector('div[data-test="hero-container"]')
  160. ?.querySelector("h1")?.textContent,
  161. stationDesc = document
  162. .querySelector('div[data-test="hero-container"]')
  163. ?.querySelector("h2")?.textContent;
  164. presenceData.details = stationName
  165. ? `Viewing ${stationName} Station`
  166. : "Viewing Station Page";
  167. presenceData.state = stationDesc;
  168. presenceData.largeImageKey =
  169. document
  170. .querySelector('div[data-test="hero-container"]')
  171. ?.querySelector("img")?.src ?? baseImage;
  172. presenceData.buttons = [
  173. {
  174. label: "View Station",
  175. url: document.location.href,
  176. },
  177. ];
  178. }
  179. if (
  180. document.location.href.includes("artist") &&
  181. document
  182. .querySelector('h1[data-test="artist-title"]')
  183. ?.querySelector("p")
  184. ?.querySelector("span") &&
  185. document.location.pathname !== "/artist/"
  186. ) {
  187. const artistName = document
  188. .querySelector('h1[data-test="artist-title"]')
  189. ?.querySelector("p")
  190. ?.querySelector("span")?.textContent;
  191. presenceData.details = "Viewing Artist";
  192. presenceData.state = artistName;
  193. presenceData.largeImageKey =
  194. document
  195. .querySelector('div[data-test="hero-artist"]')
  196. ?.querySelector("img")?.src ?? baseImage;
  197. presenceData.buttons = [
  198. {
  199. label: "View Artist",
  200. url: document.location.href,
  201. },
  202. ];
  203. }
  204. if (
  205. document.querySelector('div[data-test="control-set"]') &&
  206. document
  207. .querySelector('div[data-test="control-set"]')
  208. ?.querySelector('svg[aria-label="Stop Icon"]')
  209. ) {
  210. const playerArtwork = document
  211. .querySelector('div[data-test="player-artwork-image"]')
  212. ?.querySelector("div")
  213. ?.querySelector("img")?.src,
  214. metadataText =
  215. document
  216. .querySelector('div[data-test="player-text"]')
  217. ?.querySelectorAll("a") ?? null;
  218. presenceData.state = document
  219. .querySelector('div[data-test="player-text"]')
  220. ?.querySelector("a")?.textContent;
  221. presenceData.largeImageKey = playerArtwork ?? baseImage;
  222. presenceData.smallImageKey = Assets.Live;
  223. presenceData.smallImageText = (await strings).live;
  224. if (
  225. metadataText &&
  226. metadataText[0] &&
  227. metadataText[1] &&
  228. metadataText[2]
  229. ) {
  230. presenceData.details =
  231. metadataText[1]?.textContent && metadataText[2]?.textContent
  232. ? `${metadataText[1]?.textContent} · ${metadataText[2]?.textContent}`
  233. : "";
  234. presenceData.buttons = [
  235. {
  236. label: "View Station",
  237. url: metadataText[0]?.href ?? null,
  238. },
  239. ];
  240. }
  241. if (
  242. metadataText &&
  243. metadataText[1]?.getAttribute("href")?.includes("song") &&
  244. metadataText[2]?.getAttribute("href")?.includes("artist")
  245. ) {
  246. presenceData.buttons = [
  247. {
  248. label: "View Song",
  249. url:
  250. document.location.origin + metadataText[1]?.getAttribute("href"),
  251. },
  252. {
  253. label: "View Artist",
  254. url:
  255. document.location.origin + metadataText[2]?.getAttribute("href"),
  256. },
  257. ];
  258. }
  259. }
  260. if (
  261. document.querySelector('div[data-test="control-set"]') &&
  262. document
  263. .querySelector('div[data-test="control-set"]')
  264. ?.querySelector('svg[aria-label="Pause Icon"]')
  265. ) {
  266. const playerArtwork = document
  267. .querySelector('div[data-test="player-artwork-image"]')
  268. ?.querySelector("div")
  269. ?.querySelector("img")?.src,
  270. metadataText =
  271. document
  272. .querySelector('div[data-test="player-text"]')
  273. ?.querySelectorAll("a") ?? null,
  274. currentTime = presence.timestampFromFormat(
  275. document.querySelector('div[aria-label="Seekbar Position"]')
  276. ?.textContent
  277. ),
  278. timestamps = presence.getTimestamps(
  279. currentTime,
  280. presence.timestampFromFormat(
  281. document.querySelector('div[aria-label="Seekbar Duration"]')
  282. ?.textContent
  283. )
  284. );
  285. presenceData.state = document
  286. .querySelector('div[data-test="player-text"]')
  287. ?.querySelector("a")?.textContent;
  288. presenceData.details =
  289. metadataText &&
  290. metadataText[1]?.textContent &&
  291. metadataText[2]?.textContent
  292. ? `${metadataText[1]?.textContent} · ${metadataText[2]?.textContent}`
  293. : "";
  294. presenceData.largeImageKey = playerArtwork ?? baseImage;
  295. presenceData.smallImageKey = Assets.Play;
  296. presenceData.smallImageText = (await strings).play;
  297. presenceData.startTimestamp = timestamps[0];
  298. presenceData.endTimestamp = timestamps[1];
  299. if (
  300. metadataText &&
  301. metadataText[1]?.getAttribute("href")?.includes("song") &&
  302. metadataText[2]?.getAttribute("href")?.includes("artist")
  303. ) {
  304. presenceData.buttons = [
  305. {
  306. label: "View Song",
  307. url:
  308. document.location.origin + metadataText[1]?.getAttribute("href"),
  309. },
  310. {
  311. label: "View Artist",
  312. url:
  313. document.location.origin + metadataText[2]?.getAttribute("href"),
  314. },
  315. ];
  316. }
  317. }
  318. await presence.setActivity(presenceData);
  319. } else if (document.location.href.includes("listen.iheart.com")) {
  320. presenceData.details = "Browsing iHeartRadio [BETA]";
  321. switch (document.location.pathname) {
  322. case "/browse/live": {
  323. presenceData.details = "Viewing Search Stations";
  324. break;
  325. }
  326. case "/search": {
  327. presenceData.details = "Searching for Stations";
  328. break;
  329. }
  330. case "/library/live": {
  331. presenceData.details = "Viewing Library of Followed Stations";
  332. break;
  333. }
  334. case "/browse/artists": {
  335. presenceData.details = "Viewing Search Artists";
  336. break;
  337. }
  338. case "/browse/podcasts": {
  339. presenceData.details = "Viewing Search Podcasts";
  340. break;
  341. }
  342. case "/browse/playlists": {
  343. presenceData.details = "Viewing Search Playlists";
  344. break;
  345. }
  346. case "/library/artists": {
  347. presenceData.details = "Viewing Artists Library";
  348. break;
  349. }
  350. case "/library/podcasts": {
  351. presenceData.details = "Viewing Podcasts Library";
  352. break;
  353. }
  354. case "/library/playlists": {
  355. presenceData.details = "Viewing Playlists Library";
  356. break;
  357. }
  358. }
  359. if (
  360. document.location.href.includes("live") &&
  361. document.querySelector('main[data-test="main"]') &&
  362. !document.location.href.includes("/browse/live")
  363. ) {
  364. const stationName = document
  365. .querySelector('main[data-test="main"]')
  366. ?.querySelector("h1")?.textContent,
  367. stationArtwork = document
  368. .querySelector('main[data-test="main"]')
  369. ?.querySelector('div[data-test="image-container"]')
  370. ?.querySelector("img").src;
  371. presenceData.details = stationName
  372. ? `Viewing ${stationName} Station`
  373. : "Viewing Station Page";
  374. presenceData.state = document
  375. .querySelector('main[data-test="main"]')
  376. ?.querySelector("p").textContent;
  377. presenceData.largeImageKey = stationArtwork ?? baseImage;
  378. presenceData.buttons = [
  379. {
  380. label: "View Station",
  381. url: document.location.href,
  382. },
  383. ];
  384. }
  385. if (
  386. document.location.href.includes("artist") &&
  387. document.querySelector('main[data-test="main"]') &&
  388. !document.location.href.includes("/browse/artists")
  389. ) {
  390. const artistArtwork = document
  391. .querySelector('main[data-test="main"]')
  392. ?.querySelector('div[data-test="image-container"]')
  393. ?.querySelector("img").src;
  394. presenceData.details = "Viewing Artist";
  395. presenceData.state =
  396. document.querySelector('main[data-test="main"]')?.querySelector("h1")
  397. ?.textContent ?? "Unknown Artist";
  398. presenceData.largeImageKey = artistArtwork ?? baseImage;
  399. presenceData.buttons = [
  400. {
  401. label: "View Artist",
  402. url: document.location.href,
  403. },
  404. ];
  405. }
  406. if (
  407. document.location.href.includes("song") &&
  408. document.querySelector('main[data-test="main"]') &&
  409. document
  410. .querySelector('div[data-test="song-hero"]')
  411. ?.querySelector("p")
  412. ?.querySelector("a")
  413. ) {
  414. const songName = document
  415. .querySelector('main[data-test="main"]')
  416. ?.querySelector("h1")?.textContent,
  417. songArtwork = document
  418. .querySelector('main[data-test="main"]')
  419. ?.querySelector('div[data-test="image-container"]')
  420. ?.querySelector("img").src,
  421. songArtist = document
  422. .querySelector('div[data-test="song-hero"]')
  423. ?.querySelector("p")
  424. ?.querySelector("a");
  425. presenceData.details = "Viewing Song";
  426. presenceData.state =
  427. songName && songArtist?.textContent
  428. ? `${songName} · ${songArtist?.textContent}`
  429. : "Unknown Song";
  430. presenceData.largeImageKey = songArtwork;
  431. presenceData.buttons = [
  432. {
  433. label: "View Song",
  434. url: document.location.href,
  435. },
  436. {
  437. label: "View Artist",
  438. url: songArtist?.href ?? null,
  439. },
  440. ];
  441. }
  442. if (
  443. document.location.href.includes("album") &&
  444. document.querySelector('main[data-test="main"]') &&
  445. document
  446. .querySelector('div[data-test="album-hero"]')
  447. ?.querySelector("p")
  448. ?.querySelector("a")
  449. ) {
  450. const albumName = document
  451. .querySelector('main[data-test="main"]')
  452. ?.querySelector("h1")?.textContent,
  453. albumArtwork = document
  454. .querySelector('main[data-test="main"]')
  455. ?.querySelector('div[data-test="image-container"]')
  456. ?.querySelector("img").src,
  457. albumArtist = document
  458. .querySelector('div[data-test="album-hero"]')
  459. ?.querySelector("p")
  460. ?.querySelector("a");
  461. presenceData.details = "Viewing Album";
  462. presenceData.state =
  463. albumName && albumArtist?.textContent
  464. ? `${albumName} · ${albumArtist?.textContent}`
  465. : "Unknown Album";
  466. presenceData.largeImageKey = albumArtwork ?? baseImage;
  467. presenceData.buttons = [
  468. {
  469. label: "View Album",
  470. url: document.location.href,
  471. },
  472. {
  473. label: "View Artist",
  474. url: albumArtist?.href ?? null,
  475. },
  476. ];
  477. }
  478. if (
  479. document.location.href.includes("playlist") &&
  480. document.querySelector('main[data-test="main"]') &&
  481. document
  482. .querySelector('div[data-test="hero-container"]')
  483. ?.querySelector("h1")?.textContent
  484. ) {
  485. const playlistTitle = document
  486. .querySelector('div[data-test="hero-container"]')
  487. ?.querySelector("h1")?.textContent,
  488. playlistCreator = document
  489. .querySelector('div[data-test="hero-container"]')
  490. ?.querySelectorAll("p")[1]?.textContent;
  491. presenceData.details = "Viewing Playlist";
  492. presenceData.state =
  493. playlistTitle && playlistCreator
  494. ? `${playlistTitle} · ${playlistCreator}`
  495. : "Unknown Playlist";
  496. presenceData.largeImageKey =
  497. document
  498. .querySelector('div[data-test="image-container"]')
  499. ?.querySelector("img").src ?? baseImage;
  500. presenceData.buttons = [
  501. {
  502. label: "View Playlist",
  503. url: document.location.href,
  504. },
  505. ];
  506. }
  507. if (
  508. document.location.href.includes("podcast") &&
  509. document.querySelector('main[data-test="main"]') &&
  510. !document.location.href.includes("browse/podcasts")
  511. ) {
  512. const podcastName = document
  513. .querySelector('div[data-test="hero-container"]')
  514. ?.querySelector("h1")?.textContent,
  515. podcastIcon = document
  516. .querySelector('div[data-test="hero-container"]')
  517. ?.querySelector('div[data-test="image-container"]')
  518. ?.querySelector("img")?.src;
  519. presenceData.details = "Viewing Podcast";
  520. presenceData.state = podcastName ?? "Unknown Podcast";
  521. presenceData.largeImageKey = podcastIcon ?? baseImage;
  522. presenceData.buttons = [
  523. {
  524. label: "View Podcast",
  525. url: document.location.href,
  526. },
  527. ];
  528. }
  529. if (
  530. document.location.href.includes("episode") &&
  531. document.querySelector('main[data-test="main"]') &&
  532. !document.location.href.includes("browse/podcasts")
  533. ) {
  534. const episodeName = document
  535. .querySelector('main[data-test="main"]')
  536. ?.querySelector("h1")?.textContent,
  537. podcastIcon = document
  538. .querySelector('main[data-test="main"]')
  539. ?.querySelector('div[data-test="image-container"]')
  540. ?.querySelector("img")?.src,
  541. podcastName = document
  542. .querySelector('main[data-test="main"]')
  543. ?.querySelector("a");
  544. presenceData.details = episodeName
  545. ? `Viewing ${episodeName}`
  546. : "Viewing Unknown Episode";
  547. presenceData.state = podcastName?.textContent ?? "Unknown Podcast";
  548. presenceData.largeImageKey = podcastIcon ?? baseImage;
  549. presenceData.buttons = [
  550. {
  551. label: "View Episode",
  552. url: document.location.href,
  553. },
  554. {
  555. label: "View Podcast",
  556. url: podcastName?.href ?? null,
  557. },
  558. ];
  559. }
  560. if (
  561. document.querySelector('div[data-test="player-controls"]') &&
  562. document
  563. .querySelector('div[data-test="player-controls"]')
  564. ?.querySelector('button[data-test="player-play-button"]')
  565. ?.querySelector('svg[aria-label="Pause Icon"]')
  566. ) {
  567. const playerArtwork =
  568. document
  569. .querySelector('div[data-test="player-metadata"]')
  570. ?.querySelector('div[data-test="image-container"]')
  571. ?.querySelector("img")?.src ?? baseImage,
  572. songTitle = document.querySelector('a[data-test="title-link"]'),
  573. artist = document.querySelector('a[data-test="description-link"]'),
  574. stationName = document.querySelector('a[data-test="subtitle-link"]'),
  575. songPosition = document.querySelector(
  576. 'span[aria-label="position"][role="timer"][data-kind="caption-4"]'
  577. ),
  578. songDuration = document.querySelector(
  579. 'span[aria-label="duration"][role="timer"][data-kind="caption-4"]'
  580. ),
  581. timestamps = presence.getTimestamps(
  582. presence.timestampFromFormat(songPosition?.textContent),
  583. presence.timestampFromFormat(songDuration?.textContent)
  584. );
  585. presenceData.largeImageKey = playerArtwork
  586. ? `${playerArtwork}`
  587. : baseImage;
  588. presenceData.details =
  589. songTitle?.textContent && artist?.textContent
  590. ? `${songTitle?.textContent} · ${artist?.textContent}`
  591. : "";
  592. presenceData.state = stationName?.textContent;
  593. presenceData.smallImageKey = Assets.Play;
  594. presenceData.smallImageText = (await strings).play;
  595. presenceData.startTimestamp = timestamps[0];
  596. presenceData.endTimestamp = timestamps[1];
  597. if (
  598. artist?.getAttribute("href")?.includes("podcast") &&
  599. stationName?.getAttribute("href")?.includes("episode")
  600. ) {
  601. presenceData.details = checkLength(artist?.textContent);
  602. presenceData.state = checkLength(stationName?.textContent);
  603. presenceData.buttons = [
  604. {
  605. label: "View Episode",
  606. url: document.location.origin + stationName?.getAttribute("href"),
  607. },
  608. {
  609. label: "View Podcast",
  610. url: document.location.origin + artist?.getAttribute("href"),
  611. },
  612. ];
  613. }
  614. if (
  615. artist?.getAttribute("href")?.includes("artist") &&
  616. songTitle?.getAttribute("href")?.includes("song")
  617. ) {
  618. presenceData.buttons = [
  619. {
  620. label: "View Song",
  621. url: document.location.origin + songTitle?.getAttribute("href"),
  622. },
  623. {
  624. label: "View Artist",
  625. url: document.location.origin + artist?.getAttribute("href"),
  626. },
  627. ];
  628. }
  629. }
  630. if (
  631. document.querySelector('div[data-test="player-controls"]') &&
  632. document
  633. .querySelector('div[data-test="player-controls"]')
  634. ?.querySelector('button[data-test="player-play-button"]')
  635. ?.querySelector('svg[aria-label="Stop Icon"]')
  636. ) {
  637. const stationName = document.querySelector(
  638. 'a[data-test="subtitle-link"]'
  639. ),
  640. stationFallbackName = document.querySelector(
  641. 'a[data-test="fallback-subtitle-link"]'
  642. ),
  643. stationMetaTitle = document.querySelector('a[data-test="title-link"]'),
  644. stationFallbackDesc = document.querySelector(
  645. 'a[data-test="fallback-description-link"]'
  646. ),
  647. stationMetaDesc = document.querySelector(
  648. 'a[data-test="description-link"]'
  649. ),
  650. stationArtwork = document
  651. .querySelector('div[data-test="image-container"]')
  652. ?.querySelector("img")?.src;
  653. let stationArtWorkFixed;
  654. if (stationDescription && stationFallbackDesc?.textContent)
  655. stationDescription = null;
  656. if (!stationDescription && !stationFallbackDesc?.textContent) {
  657. stationName?.textContent
  658. ? (stationDescription = await getStationDesc(
  659. stationName?.textContent
  660. ))
  661. : (stationDescription = await getStationDesc(
  662. stationFallbackName?.textContent
  663. ));
  664. }
  665. if (stationArtwork && stationArtwork.includes("ops=cover"))
  666. stationArtWorkFixed = stationArtwork.replace("(400,400)", "(500,500)");
  667. presenceData.state =
  668. stationName?.textContent && stationDescription
  669. ? `${stationName?.textContent} · ${stationDescription}`
  670. : stationFallbackDesc?.textContent ?? stationName?.textContent;
  671. presenceData.details =
  672. stationMetaTitle && stationMetaDesc
  673. ? `${stationMetaTitle?.textContent} · ${stationMetaDesc?.textContent}`
  674. : stationFallbackName?.textContent;
  675. presenceData.smallImageKey = Assets.Live;
  676. presenceData.smallImageText = (await strings).live;
  677. presenceData.largeImageKey = stationArtWorkFixed
  678. ? `${stationArtWorkFixed}`
  679. : stationArtwork
  680. ? `${stationArtwork}`
  681. : baseImage;
  682. if (
  683. stationFallbackDesc?.getAttribute("href")?.includes("live") ||
  684. stationFallbackName?.getAttribute("href")?.includes("live")
  685. ) {
  686. presenceData.buttons = [
  687. {
  688. label: "View Station",
  689. url: stationFallbackDesc?.getAttribute("href")
  690. ? document.location.origin +
  691. stationFallbackDesc?.getAttribute("href")
  692. : document.location.origin +
  693. stationFallbackName?.getAttribute("href"),
  694. },
  695. ];
  696. }
  697. if (
  698. stationMetaTitle?.getAttribute("href")?.includes("song") &&
  699. stationMetaDesc?.getAttribute("href")?.includes("artist")
  700. ) {
  701. presenceData.buttons = [
  702. {
  703. label: "View Song",
  704. url:
  705. document.location.origin + stationMetaTitle?.getAttribute("href"),
  706. },
  707. {
  708. label: "View Artist",
  709. url:
  710. document.location.origin + stationMetaDesc?.getAttribute("href"),
  711. },
  712. ];
  713. }
  714. }
  715. await presence.setActivity(presenceData);
  716. }
  717. });