presence.ts 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. interface Channel {
  2. id: string;
  3. name: string;
  4. track: string;
  5. artist: string;
  6. cover: string;
  7. listeners: number;
  8. timeStart: string;
  9. timeEnd: string;
  10. }
  11. const presence = new Presence({
  12. clientId: "748660637021896835",
  13. }),
  14. browsingTimestamp = Math.floor(Date.now() / 1000);
  15. let totalListeners: number,
  16. channels: Channel[] = [];
  17. function newStats(): void {
  18. fetch("https://api.reyfm.de/v4?voting=true")
  19. .then(response => response.json())
  20. .then(data => {
  21. totalListeners = data.all_listeners;
  22. const channelList: string[] = data.sequence,
  23. channelArray: Channel[] = [];
  24. for (const channel of channelList) {
  25. channelArray.push({
  26. id: channel,
  27. name: "",
  28. track: "",
  29. artist: "",
  30. cover: "",
  31. listeners: 0,
  32. timeStart: "",
  33. timeEnd: "",
  34. });
  35. }
  36. for (const channel of channelArray) {
  37. const channelData = data.channels[`${channel.id}`];
  38. channel.name = channelData.name;
  39. channel.listeners = channelData.listeners;
  40. channel.track = channelData.now.title;
  41. channel.artist = channelData.now.artist;
  42. channel.cover = channelData.now.cover_urls["500x500"];
  43. channel.timeStart = channelData.now.time.start;
  44. channel.timeEnd = channelData.now.time.end;
  45. }
  46. channels = channelArray;
  47. });
  48. }
  49. function findChannel(): string {
  50. try {
  51. for (const rows of document.querySelector("#container > div.channels")
  52. .children) {
  53. for (const channel of rows.children) {
  54. if (
  55. !channel.className.includes("desktop") &&
  56. (
  57. channel.firstElementChild.children[2]
  58. .firstElementChild as HTMLImageElement
  59. ).src.includes("stop.png")
  60. )
  61. return channel.firstElementChild.id.replace("channel-", "");
  62. }
  63. }
  64. return "YOU FAILED";
  65. } catch (e) {
  66. return "YOU FAILED";
  67. }
  68. }
  69. newStats();
  70. setInterval(() => {
  71. newStats();
  72. }, 10_000);
  73. const enum Assets {
  74. WhiteBackSmall = "https://cdn.rcd.gg/PreMiD/websites/R/REYFM/assets/0.png",
  75. BlackBackSmall = "https://cdn.rcd.gg/PreMiD/websites/R/REYFM/assets/1.png",
  76. ColorBackSmall = "https://cdn.rcd.gg/PreMiD/websites/R/REYFM/assets/2.png",
  77. ColorBack = "https://cdn.rcd.gg/PreMiD/websites/R/REYFM/assets/3.png",
  78. BlackBack = "https://cdn.rcd.gg/PreMiD/websites/R/REYFM/assets/4.png",
  79. WhiteBack = "https://cdn.rcd.gg/PreMiD/websites/R/REYFM/assets/5.png",
  80. Black = "https://cdn.rcd.gg/PreMiD/websites/R/REYFM/assets/6.png",
  81. White = "https://cdn.rcd.gg/PreMiD/websites/R/REYFM/assets/7.png",
  82. Logo = "https://cdn.rcd.gg/PreMiD/websites/R/REYFM/assets/8.png",
  83. }
  84. presence.on("UpdateData", async () => {
  85. const [info, elapsed, format1, format2, format3, buttons, logo] =
  86. await Promise.all([
  87. presence.getSetting<boolean>("sInfo"),
  88. presence.getSetting<boolean>("tElapsed"),
  89. presence.getSetting<string>("sFormat1"),
  90. presence.getSetting<string>("sFormat2"),
  91. presence.getSetting<string>("sListeners"),
  92. presence.getSetting<boolean>("buttons"),
  93. presence.getSetting<number>("logo"),
  94. ]),
  95. logoArr = [
  96. Assets.WhiteBackSmall,
  97. Assets.BlackBackSmall,
  98. Assets.ColorBackSmall,
  99. Assets.WhiteBack,
  100. Assets.BlackBack,
  101. Assets.ColorBack,
  102. Assets.White,
  103. Assets.Black,
  104. Assets.Logo,
  105. ],
  106. presenceData: PresenceData = {
  107. largeImageKey: logoArr[logo] || Assets.WhiteBackSmall,
  108. smallImageKey: Assets.Reading,
  109. };
  110. let showFormat3 = false;
  111. if (info) {
  112. if (document.location.hostname === "status.rey.fm")
  113. presenceData.details = "Viewing status page";
  114. else if (document.location.hostname === "rey.fm") {
  115. if (document.location.pathname.includes("/bots")) {
  116. presenceData.details = "Viewing bots";
  117. presenceData.buttons = [
  118. {
  119. label: "View Bots",
  120. url: "https://rey.fm/bots",
  121. },
  122. ];
  123. } else if (document.location.pathname.includes("/discord-bot")) {
  124. presenceData.details = "Viewing the Discord bot";
  125. presenceData.buttons = [
  126. {
  127. label: "View Bot",
  128. url: "https://rey.fm/discord-bot",
  129. },
  130. ];
  131. } else if (document.location.pathname.includes("/partner"))
  132. presenceData.details = "Viewing partners";
  133. else if (document.location.pathname.includes("/stream-urls"))
  134. presenceData.details = "Viewing streams";
  135. else if (document.location.pathname.includes("/apply"))
  136. presenceData.details = "Viewing job postings";
  137. else if (document.location.pathname.includes("/datenschutz"))
  138. presenceData.details = "Reading the datenschutz";
  139. else if (document.location.pathname.includes("/impressum"))
  140. presenceData.details = "Reading the impressum";
  141. else if (document.location.pathname.includes("/stats"))
  142. presenceData.details = "Viewing the statistics";
  143. else if (document.location.pathname === "/")
  144. presenceData.details = "Browsing...";
  145. }
  146. }
  147. if (elapsed) presenceData.startTimestamp = browsingTimestamp;
  148. if (
  149. document.location.hostname === "rey.fm" &&
  150. document.location.pathname === "/"
  151. ) {
  152. if (
  153. document.querySelector<HTMLElement>("#player").style.cssText !==
  154. "display: none;"
  155. ) {
  156. let track: string, artist: string, cover: string;
  157. if (
  158. !document
  159. .querySelector<HTMLImageElement>("#miniplayer-play")
  160. .src.includes("play.png")
  161. ) {
  162. const channelID = findChannel();
  163. if (channelID !== "YOU FAILED") {
  164. const channel = channels.find(channel => channel.id === channelID);
  165. ({ track, artist, cover } = channel);
  166. presenceData.smallImageKey = Assets.Play;
  167. presenceData.smallImageText = format3
  168. .replace("%listeners%", `${channel.listeners}`)
  169. .replace("%totalListeners%", `${totalListeners}`);
  170. presenceData.startTimestamp = Date.parse(channel.timeStart);
  171. presenceData.endTimestamp = Date.parse(channel.timeEnd);
  172. showFormat3 = true;
  173. presenceData.buttons = [
  174. {
  175. label: "Listen along!",
  176. url: `https://rey.fm/station/${channel.name}`,
  177. },
  178. ];
  179. } else {
  180. artist = document.querySelector(
  181. "#player > div.wrapper > div.current > span.artist"
  182. ).textContent;
  183. track = document.querySelector(
  184. "#player > div.wrapper > div.current > span.title"
  185. ).textContent;
  186. cover = document
  187. .querySelector(
  188. "#player > div.wrapper > div.cover > img#player-coverart"
  189. )
  190. .getAttribute("src");
  191. presenceData.smallImageKey = Assets.Play;
  192. presenceData.smallImageText = "Loading statistics...";
  193. }
  194. } else {
  195. artist = document.querySelector(
  196. "#player > div.wrapper > div.current > span.artist"
  197. ).textContent;
  198. track = document.querySelector(
  199. "#player > div.wrapper > div.current > span.title"
  200. ).textContent;
  201. cover = document
  202. .querySelector(
  203. "#player > div.wrapper > div.cover > img#player-coverart"
  204. )
  205. .getAttribute("src");
  206. presenceData.smallImageKey = Assets.Pause;
  207. presenceData.smallImageText = `Total Listeners: ${totalListeners}`;
  208. delete presenceData.startTimestamp;
  209. }
  210. presenceData.details = format1
  211. .replace("%title%", track)
  212. .replace("%artist%", artist);
  213. presenceData.state = format2
  214. .replace("%title%", track)
  215. .replace("%artist%", artist);
  216. presenceData.largeImageKey = cover;
  217. }
  218. } else if (
  219. document.location.hostname === "rey.fm" &&
  220. document.querySelector("#channel-player") !== null
  221. ) {
  222. const channel = channels.find(
  223. channel =>
  224. channel.id ===
  225. document
  226. .querySelector("#channel-player")
  227. .className.replace("shadow channel-color-", "")
  228. ),
  229. paused = document
  230. .querySelector<HTMLImageElement>("#play")
  231. .src.includes("play.png");
  232. paused
  233. ? (presenceData.smallImageKey = Assets.Pause)
  234. : (presenceData.smallImageKey = Assets.Play);
  235. presenceData.details = format1
  236. .replace("%title%", channel.track)
  237. .replace("%artist%", channel.artist);
  238. presenceData.state = format2
  239. .replace("%title%", channel.track)
  240. .replace("%artist%", channel.artist);
  241. presenceData.smallImageText = format3
  242. .replace("%listeners%", `${channel.listeners}`)
  243. .replace("%totalListeners%", `${totalListeners}`);
  244. presenceData.largeImageKey = channel.cover;
  245. showFormat3 = true;
  246. presenceData.buttons = [{ label: "Listen along!", url: document.URL }];
  247. if (!paused) {
  248. presenceData.startTimestamp = Date.parse(channel.timeStart);
  249. presenceData.endTimestamp = Date.parse(channel.timeEnd);
  250. } else {
  251. delete presenceData.startTimestamp;
  252. delete presenceData.endTimestamp;
  253. }
  254. }
  255. showFormat3
  256. ? presence.showSetting("sListeners")
  257. : presence.hideSetting("sListeners");
  258. if (!buttons) delete presenceData.buttons;
  259. if (presenceData.details) presence.setActivity(presenceData);
  260. else presence.setActivity();
  261. });