presence.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. const presence = new Presence({
  2. clientId: "1139510267311562842",
  3. }),
  4. browsingTimestamp = Math.floor(Date.now() / 1000);
  5. const enum Assets {
  6. Logo = "https://cdn.rcd.gg/PreMiD/websites/M/Moopa/assets/logo.png",
  7. }
  8. function getTitle(titleLang: number) {
  9. const metaTitle = document.querySelector('meta[name="title"]'),
  10. romajiTitle = metaTitle?.getAttribute("data-title-romaji");
  11. switch (titleLang) {
  12. case 0: {
  13. return romajiTitle;
  14. }
  15. case 1: {
  16. return metaTitle?.getAttribute("data-title-english") || romajiTitle;
  17. }
  18. case 2: {
  19. return metaTitle?.getAttribute("data-title-native") || romajiTitle;
  20. }
  21. default: {
  22. return null;
  23. }
  24. }
  25. }
  26. presence.on("UpdateData", async () => {
  27. const presenceData: PresenceData = {
  28. largeImageKey: Assets.Logo,
  29. startTimestamp: browsingTimestamp,
  30. },
  31. titleLang = (await presence.getSetting("title")) as number,
  32. { pathname, href } = document.location;
  33. if (pathname === "/" || pathname === "/en/")
  34. presenceData.details = "Browsing Homepage";
  35. else if (pathname.includes("/id/"))
  36. presenceData.details = "Browsing Anime/Manga";
  37. else if (pathname.includes("/profile/")) {
  38. presenceData.details =
  39. document.querySelector("h1.font-karla.font-bold.text-2xl.pt-7")
  40. ?.textContent || "Getting data...";
  41. presenceData.state = "Viewing profile";
  42. } else if (pathname === "/en/anime/trending/")
  43. presenceData.details = "Browsing trending Anime";
  44. else if (pathname === "/en/anime/popular/")
  45. presenceData.details = "Browsing popular Anime";
  46. else if (
  47. pathname.includes("/anime/") &&
  48. !pathname.includes("/watch/") &&
  49. !pathname.includes("/search/")
  50. ) {
  51. if (document.querySelector('img[alt="404"]')) {
  52. presenceData.state = "404 | Not Found";
  53. presenceData.details = "Browsing Anime/Manga";
  54. } else {
  55. delete presenceData.startTimestamp;
  56. const title = getTitle(titleLang);
  57. presenceData.largeImageKey =
  58. document
  59. .querySelector('img[alt="poster anime"]')
  60. ?.getAttribute("src") || Assets.Logo;
  61. presenceData.details = title || "Getting data...";
  62. presenceData.state = "Viewing info";
  63. if (title) {
  64. presenceData.buttons = [
  65. {
  66. label: "View Anime",
  67. url: href,
  68. },
  69. ];
  70. }
  71. }
  72. } else if (
  73. pathname.includes("/manga/") &&
  74. !pathname.includes("/read/") &&
  75. !pathname.includes("/search/")
  76. ) {
  77. if (document.querySelector('img[alt="404"]')) {
  78. presenceData.state = "404 | Not Found";
  79. presenceData.details = "Browsing Anime/Manga";
  80. } else {
  81. delete presenceData.startTimestamp;
  82. const title = document.querySelector("h1.title")?.textContent;
  83. presenceData.largeImageKey =
  84. document.querySelector('img[alt="cover image"]')?.getAttribute("src") ||
  85. Assets.Logo;
  86. presenceData.details = title || "Getting data...";
  87. presenceData.state = "Viewing info";
  88. if (title) {
  89. presenceData.buttons = [
  90. {
  91. label: "View Manga",
  92. url: href,
  93. },
  94. ];
  95. }
  96. }
  97. } else if (pathname.includes("/watch/")) {
  98. if (document.querySelector('img[alt="404"]')) {
  99. presenceData.state = "404 | Not Found";
  100. presenceData.details = "Browsing Anime/Manga";
  101. } else {
  102. const playingEpisode = document
  103. .querySelector("h3")
  104. ?.textContent?.replace("Episode ", ""),
  105. video: HTMLVideoElement = document.querySelector("video");
  106. if (video && !Number.isNaN(Number(video.duration))) {
  107. [presenceData.startTimestamp, presenceData.endTimestamp] =
  108. presence.getTimestampsfromMedia(video);
  109. if (video.paused) {
  110. presenceData.smallImageText = "Paused";
  111. presenceData.smallImageKey = Assets.Pause;
  112. delete presenceData.startTimestamp;
  113. delete presenceData.endTimestamp;
  114. } else {
  115. presenceData.smallImageText = "Playing";
  116. presenceData.smallImageKey = Assets.Play;
  117. }
  118. }
  119. const total = document
  120. .querySelector("div.grid.w-full.pl-5")
  121. ?.getAttribute("data-episode"),
  122. title = getTitle(titleLang);
  123. if (title) {
  124. presenceData.buttons = [
  125. {
  126. label: "Stream Anime",
  127. url: href,
  128. },
  129. ];
  130. }
  131. presenceData.largeImageKey =
  132. document.querySelector('img[alt="Anime Cover"]')?.getAttribute("src") ||
  133. Assets.Logo;
  134. presenceData.details = title || "Getting data...";
  135. if (playingEpisode) {
  136. presenceData.state = `Episode ${playingEpisode} of ${
  137. total === "0" ? "???" : total
  138. }`;
  139. }
  140. }
  141. } else if (pathname.includes("/read/")) {
  142. const title = document
  143. .querySelector("title")
  144. ?.textContent.replace("Manga - ", "");
  145. presenceData.largeImageKey =
  146. document
  147. .querySelector('meta[id="CoverImage"]')
  148. .getAttribute("data-manga-cover") || Assets.Logo;
  149. presenceData.details = title || "Getting data...";
  150. presenceData.state = `Reading Chapter ${document
  151. .querySelector('input[id="chapter-progress"]')
  152. .getAttribute("value")}`;
  153. presenceData.smallImageKey = Assets.Reading;
  154. presenceData.smallImageText = "Reading";
  155. if (title) {
  156. presenceData.buttons = [
  157. {
  158. label: "Read Manga",
  159. url: href,
  160. },
  161. ];
  162. }
  163. } else if (pathname.includes("/search/") && pathname.includes("/anime/")) {
  164. presenceData.details = "Browsing Anime";
  165. presenceData.state = "Searching...";
  166. presenceData.smallImageKey = Assets.Search;
  167. } else if (pathname.includes("/search/") && pathname.includes("/manga/")) {
  168. presenceData.details = "Browsing Manga";
  169. presenceData.state = "Searching...";
  170. presenceData.smallImageKey = Assets.Search;
  171. } else presenceData.details = "Browsing Anime/Manga";
  172. if (presenceData.details) presence.setActivity(presenceData);
  173. else presence.setActivity();
  174. });