presence.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. const presence = new Presence({ clientId: "760624576550928455" }),
  2. browsingTimestamp = Math.floor(Date.now() / 1000);
  3. const enum Assets {
  4. Logo = "https://cdn.rcd.gg/PreMiD/websites/F/FurAffinity/assets/logo.png",
  5. }
  6. async function getStrings() {
  7. return presence.getStrings(
  8. {
  9. browse: "general.browsing",
  10. search: "general.searchFor",
  11. viewHome: "general.viewHome",
  12. buttonViewPage: "general.buttonViewPage",
  13. buttonViewProfile: "general.buttonViewProfile",
  14. },
  15. await presence.getSetting<string>("lang").catch(() => "en")
  16. );
  17. }
  18. function imgPath(path: string, hostname: string) {
  19. if (!path) return Assets.Logo;
  20. if (path.includes(hostname)) return `https://${path.replace("//", "")}`;
  21. else return `https://${hostname}${path}`;
  22. }
  23. let strings: Awaited<ReturnType<typeof getStrings>>,
  24. oldLang: string = null;
  25. presence.on("UpdateData", async () => {
  26. const presenceData: PresenceData = {
  27. largeImageKey: Assets.Logo,
  28. startTimestamp: browsingTimestamp,
  29. },
  30. search = document.querySelector<HTMLInputElement>('input[type="search"]'),
  31. { pathname, hash, hostname, href } = document.location,
  32. [newLang, privacy, buttons, covers] = await Promise.all([
  33. presence.getSetting<string>("lang").catch(() => "en"),
  34. presence.getSetting<boolean>("privacy"),
  35. presence.getSetting<boolean>("buttons"),
  36. presence.getSetting<boolean>("covers"),
  37. ]),
  38. username = document.querySelector("username")?.textContent?.trim(),
  39. profilePic = imgPath(
  40. document
  41. .querySelector("userpage-nav-avatar > a > img")
  42. ?.getAttribute("src") ?? "",
  43. hostname
  44. ),
  45. current = document
  46. .querySelectorAll('[class="current"]')?.[1]
  47. ?.textContent?.toLowerCase();
  48. if (oldLang !== newLang || !strings) {
  49. oldLang = newLang;
  50. strings = await getStrings();
  51. }
  52. if (privacy) {
  53. presenceData.details = strings.browse;
  54. presence.setActivity(presenceData);
  55. return;
  56. }
  57. if (search?.value) {
  58. presenceData.details = strings.search;
  59. presenceData.state = search.value;
  60. presenceData.smallImageKey = Assets.Search;
  61. presence.setActivity(presenceData);
  62. return;
  63. }
  64. switch (pathname.split("/")[1]) {
  65. case "": {
  66. presenceData.details = strings.viewHome;
  67. break;
  68. }
  69. case "help": {
  70. presenceData.details = "Browsing help articles";
  71. break;
  72. }
  73. case "browse": {
  74. presenceData.details = `Browsing page ${
  75. document
  76. .querySelector('[class="highlight"]')
  77. ?.textContent?.split("#")[1]
  78. }`;
  79. break;
  80. }
  81. case "journals": {
  82. const journalName = document
  83. .querySelector('form input[name*="subject"')
  84. ?.getAttribute("value");
  85. if (pathname.includes("journals/")) {
  86. presenceData.details = `Reading ${document
  87. .querySelector("username")
  88. ?.textContent.trim()}'s journal`;
  89. presenceData.largeImageKey = profilePic;
  90. } else if (!journalName) presenceData.details = "Creates a Journal";
  91. else {
  92. presenceData.details = "Updating a journal";
  93. presenceData.state = journalName;
  94. }
  95. presenceData.buttons = [
  96. {
  97. label: "Read Journal",
  98. url: href,
  99. },
  100. ];
  101. break;
  102. }
  103. case "msg": {
  104. switch (hash) {
  105. case "#message": {
  106. presenceData.details = "Reading a note";
  107. presenceData.state = `"${
  108. document.querySelector("#message h2").textContent
  109. }"`;
  110. break;
  111. }
  112. case "#MsgForm": {
  113. presenceData.details = "Writing a note";
  114. break;
  115. }
  116. }
  117. break;
  118. }
  119. case "view": {
  120. if (
  121. document.querySelector(".rating-box").textContent.trim() !== "General"
  122. )
  123. presenceData.details = "Viewing a post";
  124. else {
  125. presenceData.details = document.querySelector(
  126. '[class="submission-title"]'
  127. )?.textContent;
  128. presenceData.state = document.querySelector(
  129. '[class="submission-id-sub-container"] > a > strong'
  130. )?.textContent;
  131. presenceData.buttons = [
  132. {
  133. label: "View post",
  134. url: href,
  135. },
  136. ];
  137. }
  138. break;
  139. }
  140. default: {
  141. if (document.querySelector("userpage-nav-header") && username) {
  142. if (current === "home") {
  143. presenceData.details = `Viewing ${username}'s profile`;
  144. presenceData.buttons = [
  145. {
  146. label: strings.buttonViewProfile,
  147. url: href,
  148. },
  149. ];
  150. } else {
  151. presenceData.details = `Viewing ${username}'s
  152. ${current}`;
  153. }
  154. presenceData.largeImageKey = profilePic;
  155. } else if (document.querySelector('[class="section-header"]')) {
  156. presenceData.details = `Reading ${
  157. document
  158. .querySelector('[class="section-header"]')
  159. ?.querySelector("h2")?.textContent
  160. }`;
  161. } else presenceData.details = strings.browse;
  162. }
  163. }
  164. if (!presenceData.buttons && pathname !== "/") {
  165. presenceData.buttons = [
  166. {
  167. label: strings.buttonViewPage,
  168. url: href,
  169. },
  170. ];
  171. }
  172. if (!buttons && presenceData.buttons) delete presenceData.buttons;
  173. if (!covers && presenceData.largeImageKey !== Assets.Logo)
  174. presenceData.largeImageKey = Assets.Logo;
  175. if (presenceData.details) presence.setActivity(presenceData);
  176. else presence.setActivity();
  177. });