presence.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. const presence = new Presence({
  2. clientId: "609364070684033044",
  3. });
  4. let currentURL = new URL(document.location.href),
  5. currentPath = currentURL.pathname.replace(/^\/|\/$/g, "").split("/");
  6. const browsingTimestamp = Math.floor(Date.now() / 1000);
  7. let presenceData: PresenceData = {
  8. details: "Viewing an unsupported page",
  9. largeImageKey:
  10. "https://cdn.rcd.gg/PreMiD/websites/W/Wikipedia/assets/logo.png",
  11. startTimestamp: browsingTimestamp,
  12. };
  13. const updateCallback = {
  14. _function: null as () => void,
  15. get function(): () => void {
  16. return this._function;
  17. },
  18. set function(parameter) {
  19. this._function = parameter;
  20. },
  21. get present(): boolean {
  22. return this._function !== null;
  23. },
  24. },
  25. /**
  26. * Initialize/reset presenceData.
  27. */
  28. resetData = (
  29. defaultData: PresenceData = {
  30. details: "Viewing an unsupported page",
  31. largeImageKey:
  32. "https://cdn.rcd.gg/PreMiD/websites/W/Wikipedia/assets/logo.png",
  33. startTimestamp: browsingTimestamp,
  34. }
  35. ): void => {
  36. currentURL = new URL(document.location.href);
  37. currentPath = currentURL.pathname.replace(/^\/|\/$/g, "").split("/");
  38. presenceData = { ...defaultData };
  39. },
  40. /**
  41. * Search for URL parameters.
  42. * @param urlParam The parameter that you want to know about the value.
  43. */
  44. getURLParam = (urlParam: string): string => {
  45. return currentURL.searchParams.get(urlParam);
  46. };
  47. ((): void => {
  48. if (currentURL.hostname === "www.wikipedia.org")
  49. presenceData.details = "On the home page";
  50. else {
  51. let title: string;
  52. const actionResult = (): string =>
  53. getURLParam("action") || getURLParam("veaction"),
  54. [lang] = currentURL.hostname.split("."),
  55. titleFromURL = (): string => {
  56. return decodeURI(
  57. (currentPath[1] === "index.php"
  58. ? getURLParam("title")
  59. : currentPath.slice(1).join("/")
  60. ).replaceAll("_", " ")
  61. );
  62. };
  63. try {
  64. title = document.querySelector("h1").textContent;
  65. } catch (e) {
  66. title = titleFromURL();
  67. }
  68. /**
  69. * Returns details based on the namespace.
  70. * @link https://en.wikipedia.org/wiki/Wikipedia:Namespace
  71. */
  72. const namespaceDetails = (): string => {
  73. const details: { [index: string]: string } = {
  74. "-2": "Viewing a media",
  75. "-1": "Viewing a special page",
  76. 0: "Reading an article",
  77. 1: "Viewing a talk page",
  78. 2: "Viewing a user page",
  79. 3: "Viewing a user talk page",
  80. 4: "Viewing a project page",
  81. 5: "Viewing a project talk page",
  82. 6: "Viewing a file",
  83. 7: "Viewing a file talk page",
  84. 8: "Viewing an interface page",
  85. 9: "Viewing an interface talk page",
  86. 10: "Viewing a template",
  87. 11: "Viewing a template talk page",
  88. 12: "Viewing a help page",
  89. 13: "Viewing a help talk page",
  90. 14: "Viewing a category",
  91. 15: "Viewing a category talk page",
  92. 100: "Viewing a portal",
  93. 101: "Viewing a portal talk page",
  94. 118: "Viewing a draft",
  95. 119: "Viewing a draft talk page",
  96. 710: "Viewing a media's subtitles",
  97. 711: "Viewing a media's subtitles talk page",
  98. 828: "Viewing a module",
  99. 829: "Viewing a module talk page",
  100. 108: "Viewing a Wikipedia book",
  101. 109: "Viewing a Wikipedia book talk page",
  102. 446: "Viewing an Education Program page",
  103. 447: "Viewing an Education Program talk page",
  104. 2300: "Viewing a gadget",
  105. 2301: "Viewing a gadget talk page",
  106. 2302: "Viewing a gadget definition page",
  107. 2303: "Viewing a gadget definition talk page",
  108. 2600: "Viewing a topic",
  109. };
  110. return (
  111. details[
  112. [...document.querySelector("body").classList]
  113. .find(v => /ns--?\d/.test(v))
  114. .split("[", 1)[0]
  115. .slice(3)
  116. ] || "Viewing a page"
  117. );
  118. };
  119. //
  120. // Important note:
  121. //
  122. // When checking for the current location, avoid using the URL.
  123. // The URL is going to be different in other languages.
  124. // Use the elements on the page instead.
  125. //
  126. if (
  127. (
  128. (document.querySelector("#n-mainpage a") ||
  129. document.querySelector("#p-navigation a") ||
  130. document.querySelector(".mw-wiki-logo")) as HTMLAnchorElement
  131. ).href === currentURL.href
  132. )
  133. presenceData.details = "On the main page";
  134. else if (document.querySelector("#wpLoginAttempt"))
  135. presenceData.details = "Logging in";
  136. else if (document.querySelector("#wpCreateaccount"))
  137. presenceData.details = "Creating an account";
  138. else if (document.querySelector(".searchresults")) {
  139. presenceData.details = "Searching for a page";
  140. presenceData.state = (
  141. document.querySelector("input[type=search]") as HTMLInputElement
  142. ).value;
  143. } else if (actionResult() === "history") {
  144. presenceData.details = "Viewing revision history";
  145. presenceData.state = titleFromURL();
  146. } else if (getURLParam("diff")) {
  147. presenceData.details = "Viewing difference between revisions";
  148. presenceData.state = titleFromURL();
  149. } else if (getURLParam("oldid")) {
  150. presenceData.details = "Viewing an old revision of a page";
  151. presenceData.state = titleFromURL();
  152. } else if (
  153. document.querySelector("#ca-ve-edit") ||
  154. getURLParam("veaction")
  155. ) {
  156. presenceData.state = `${
  157. title.toLowerCase() === titleFromURL().toLowerCase()
  158. ? `${title}`
  159. : `${title} (${titleFromURL()})`
  160. }`;
  161. updateCallback.function = (): void => {
  162. if (actionResult() === "edit" || actionResult() === "editsource")
  163. presenceData.details = "Editing a page";
  164. else presenceData.details = namespaceDetails();
  165. };
  166. } else if (actionResult() === "edit") {
  167. presenceData.details = document.querySelector("#ca-edit")
  168. ? "Editing a page"
  169. : "Viewing source";
  170. presenceData.state = titleFromURL();
  171. } else {
  172. presenceData.details = namespaceDetails();
  173. presenceData.state = `${
  174. title.toLowerCase() === titleFromURL().toLowerCase()
  175. ? `${title}`
  176. : `${title} (${titleFromURL()})`
  177. }`;
  178. }
  179. if (lang !== "en") {
  180. if (presenceData.state) presenceData.state += ` (${lang})`;
  181. else presenceData.details += ` (${lang})`;
  182. }
  183. }
  184. })();
  185. if (updateCallback.present) {
  186. const defaultData = { ...presenceData };
  187. presence.on("UpdateData", async () => {
  188. resetData(defaultData);
  189. updateCallback.function();
  190. presence.setActivity(presenceData);
  191. });
  192. } else {
  193. presence.on("UpdateData", async () => {
  194. presence.setActivity(presenceData);
  195. });
  196. }