presence.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. enum PresenceClients {
  2. X = "802958757909889054",
  3. Twitter = "1172850898624581652",
  4. }
  5. let presence = new Presence({
  6. clientId: PresenceClients.X,
  7. }),
  8. twitterCheck: boolean;
  9. const presences: { [key in PresenceClients]?: Presence } = {
  10. [PresenceClients.X]: presence,
  11. },
  12. capitalize = (text: string): string => {
  13. return text
  14. .replace(/[[{(_)}\]]/g, " ")
  15. .split(" ")
  16. .map(str => {
  17. return str.charAt(0).toUpperCase() + str.slice(1);
  18. })
  19. .join(" ");
  20. };
  21. function setClient(clientId: PresenceClients) {
  22. presence.clearActivity();
  23. if (presences[clientId]) {
  24. presence = presences[clientId];
  25. presence.setActivity();
  26. } else {
  27. presence = new Presence({ clientId });
  28. presences[clientId] = presence;
  29. }
  30. presence.info("Switched presence client!");
  31. }
  32. function stripText(element: HTMLElement, id = "None", log = true): string {
  33. if (element && element.firstChild) return element.firstChild.textContent;
  34. else {
  35. if (log) {
  36. presence.error(
  37. `An error occurred while stripping data off the page. Please contact Bas950 on the PreMiD Discord server, and send him a screenshot of this error. ID: ${id}`
  38. );
  39. }
  40. return null;
  41. }
  42. }
  43. presence.info(
  44. "When using the X presence for PreMiD, make sure you have the latest UI update. Twitter classic and any legacy versions before it will not work with this presence."
  45. );
  46. let oldUrl: string, elapsed: number;
  47. async function getStrings() {
  48. return presence.getStrings(
  49. {
  50. readPost: "x.com.readPost",
  51. viewDms: "x.com.viewDms",
  52. viewPosts: "x.com.viewPosts",
  53. viewPostsWithReplies: "x.com.viewPostsWithReplies",
  54. viewMedia: "x.com.viewMedia",
  55. viewLiked: "x.com.viewLiked",
  56. viewList: "x.com.viewList",
  57. bookmarks: "x.com.bookmarks",
  58. notifs: "x.com.notifs",
  59. explore: "x.com.explore",
  60. settings: "x.com.settings",
  61. terms: "general.terms",
  62. privacy: "general.privacy",
  63. browsing: "general.browsing",
  64. search: "general.searchFor",
  65. searchSomething: "general.searchSomething",
  66. viewing: "general.viewing",
  67. profile: "general.viewProfile",
  68. },
  69. await presence.getSetting<string>("lang").catch(() => "en")
  70. );
  71. }
  72. let strings: Awaited<ReturnType<typeof getStrings>>,
  73. oldLang: string = null;
  74. presence.on("UpdateData", async () => {
  75. //* Update strings if user selected another language.
  76. const [newLang, privacy, time, twitter] = await Promise.all([
  77. presence.getSetting<string>("lang").catch(() => "en"),
  78. presence.getSetting<boolean>("privacy"),
  79. presence.getSetting<boolean>("time"),
  80. presence.getSetting<boolean>("twitter"),
  81. ]);
  82. if (!twitter && twitterCheck !== twitter) {
  83. twitterCheck = twitter;
  84. setClient(PresenceClients.X);
  85. } else if (twitterCheck !== twitter) {
  86. twitterCheck = twitter;
  87. setClient(PresenceClients.Twitter);
  88. }
  89. if (oldLang !== newLang || !strings) {
  90. oldLang = newLang;
  91. strings = await getStrings();
  92. }
  93. let title: string, info: string;
  94. const { pathname, href } = document.location;
  95. if (oldUrl !== href) {
  96. oldUrl = href;
  97. elapsed = Math.floor(Date.now() / 1000);
  98. }
  99. title = strings.browsing;
  100. info = capitalize(pathname.split("/")[1]);
  101. if (pathname.match("/i/")) {
  102. info = capitalize(pathname.split("/")[2]);
  103. if (info === "Bookmarks") info = strings.bookmarks;
  104. }
  105. if (pathname.match("/notifications")) info = strings.notifs;
  106. if (pathname.match("/explore")) info = strings.explore;
  107. if (pathname.match("/tos")) info = strings.terms;
  108. if (pathname.match("/privacy")) info = strings.privacy;
  109. if (pathname.match("/settings/")) info = strings.settings;
  110. if (pathname.match("/search")) {
  111. if (privacy) {
  112. title = strings.searchSomething;
  113. info = null;
  114. } else {
  115. title = strings.search;
  116. info = document.querySelector("input").textContent;
  117. }
  118. }
  119. const objHeader = document.querySelector(
  120. `a[href='/${pathname.split("/")[1]}/header_photo']`
  121. )?.parentElement.children[1]?.children[1] as HTMLElement;
  122. if (objHeader) {
  123. title = strings.viewPosts;
  124. info = `${
  125. stripText(objHeader, "Object Header").split("@")[0]
  126. } // ${capitalize(pathname.split("/")[1])}`;
  127. if (pathname.match("/with_replies")) title = strings.viewPostsWithReplies;
  128. if (pathname.match("/media")) title = strings.viewMedia;
  129. if (pathname.match("/likes")) title = strings.viewLiked;
  130. }
  131. if (!objHeader && pathname.match("/status/")) {
  132. title = strings.readPost;
  133. [info] = stripText(
  134. document.querySelectorAll<HTMLAnchorElement>(
  135. `a[href='/${pathname.split("/")[1]}']`
  136. )[1],
  137. "Post"
  138. ).split("@");
  139. }
  140. if (pathname.match("/messages") && objHeader) {
  141. title = strings.viewDms;
  142. info = stripText(objHeader, "Object Header");
  143. if (privacy) info = null;
  144. }
  145. const etcHeader: HTMLElement = Array.from(
  146. document.querySelectorAll("h2")
  147. ).find(c => c.parentElement.children[1]?.textContent.includes("@"));
  148. if (pathname.match("/moments") && etcHeader) {
  149. title = "Browsing Moments...";
  150. info = capitalize(pathname.split("/")[1]);
  151. }
  152. if (pathname.match("/lists") && etcHeader) {
  153. title = strings.viewList;
  154. info = capitalize(pathname.split("/")[1]);
  155. }
  156. const presenceData: PresenceData = {
  157. details: title,
  158. state: info,
  159. largeImageKey: !twitter
  160. ? "https://cdn.rcd.gg/PreMiD/websites/X/X.com/assets/0.png"
  161. : "https://cdn.rcd.gg/PreMiD/websites/X/X.com/assets/1.png",
  162. };
  163. if (time) presenceData.startTimestamp = elapsed;
  164. presence.setActivity(presenceData);
  165. });