presence.ts 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. const presence = new Presence({
  2. clientId: "501842028569559061", // Official Wolfy Discord App Client ID, owned by Wolfy's Admin
  3. });
  4. const enum Assets {
  5. Logo = "https://cdn.rcd.gg/PreMiD/websites/W/Wolfy/assets/logo.png",
  6. Skin = "https://cdn.rcd.gg/PreMiD/websites/W/Wolfy/assets/0.png",
  7. Shop = "https://cdn.rcd.gg/PreMiD/websites/W/Wolfy/assets/1.png",
  8. Leaderboard = "https://cdn.rcd.gg/PreMiD/websites/W/Wolfy/assets/2.png",
  9. }
  10. let path,
  11. prev: string,
  12. elapsed: number,
  13. prevState: string,
  14. cp: number,
  15. currTime: string;
  16. const waitingString = {
  17. en: "WAITING",
  18. fr: "EN ATTENTE",
  19. };
  20. function getTime(list: string[]): number {
  21. let ret = 0;
  22. for (let index = list.length - 1; index >= 0; index--)
  23. ret += (parseInt(list[index]) * 60) ** index;
  24. return ret;
  25. }
  26. function getTimestamps(audioTime: number, audioDuration: string): number[] {
  27. return [
  28. Date.now(),
  29. audioTime + getTime(audioDuration.split(":").reverse()) * 1000,
  30. ];
  31. }
  32. function addButton(presenceData: PresenceData, label: string, url: string) {
  33. if (!presenceData.buttons) {
  34. presenceData.buttons = [
  35. {
  36. label,
  37. url,
  38. },
  39. ];
  40. } else {
  41. presenceData.buttons[1] = {
  42. label,
  43. url,
  44. };
  45. }
  46. }
  47. function addConsultArticleButton(presenceData: PresenceData, url: string) {
  48. addButton(presenceData, "Consulter l'article", url);
  49. }
  50. function addConsultCategoryButton(presenceData: PresenceData, url: string) {
  51. addButton(presenceData, "Consulter la catégorie", url);
  52. }
  53. function addConsultEventButton(presenceData: PresenceData, href: string) {
  54. addButton(presenceData, "Consulter l'évènement", href);
  55. }
  56. async function addJoinGameButton(presenceData: PresenceData, gameId: string) {
  57. if (!(await presence.getSetting("joinGameButton"))) return;
  58. addButton(
  59. presenceData,
  60. `(${
  61. document.querySelector("div[class*='Header_timeState']")?.textContent
  62. }) Rejoindre la partie`,
  63. `https://wolfy.net/game/${gameId}`
  64. );
  65. }
  66. function addVisitHelpCenterButton(presenceData: PresenceData) {
  67. addButton(
  68. presenceData,
  69. "Consulter le centre d'aide",
  70. "https://help.wolfy.net"
  71. );
  72. }
  73. async function addVisitProfilButton(
  74. presenceData: PresenceData,
  75. username: string
  76. ) {
  77. if (!username) return;
  78. if (!(await presence.getSetting("visitProfileButton"))) return;
  79. let label = `Visiter le profil de ${username}`;
  80. if (label.length > 32) label = `${label.slice(0, 31)}…`;
  81. addButton(presenceData, label, `https://wolfy.net/leaderboard/${username}`);
  82. }
  83. function addVisitWolfyButton(presenceData: PresenceData) {
  84. addButton(presenceData, "Visiter le site de Wolfy", "https://wolfy.net");
  85. }
  86. async function handleCheckingLeaderboard(
  87. presenceData: PresenceData,
  88. username?: string
  89. ) {
  90. presenceData.smallImageKey = Assets.Leaderboard;
  91. presenceData.smallImageText = "Consulte le classement";
  92. if (!username) {
  93. presenceData.details = "Regarde le classement";
  94. presenceData.state = `Niveau ${
  95. document.querySelector("div[class*='ProfilePicture_levelMarker']")
  96. .textContent
  97. }`;
  98. } else {
  99. presenceData.details = `Regarde le profil de ${username}`;
  100. presenceData.state = `Niveau ${
  101. document.querySelector("div[class*='ProfilePicture_levelMarker']")
  102. .textContent
  103. }`;
  104. await addVisitProfilButton(presenceData, username);
  105. }
  106. }
  107. function isWaitingGame(state: string, lang: string) {
  108. return state === waitingString[resolveLanguage(lang)];
  109. }
  110. function resolveLanguage(lang: string): keyof typeof waitingString {
  111. if (Object.keys(waitingString).includes(lang))
  112. return lang as keyof typeof waitingString;
  113. return "en";
  114. }
  115. presence.on("UpdateData", async () => {
  116. const presenceData: PresenceData = {
  117. largeImageKey: Assets.Logo,
  118. };
  119. path = document.location.pathname.split("/");
  120. if (path[1] === document.querySelector("html")?.lang) path = path.slice(2);
  121. else path = path.slice(1);
  122. if (window.location.href !== prev && !path.includes("game")) {
  123. delete presenceData.startTimestamp;
  124. delete presenceData.endTimestamp;
  125. prev = window.location.href;
  126. elapsed = Math.floor(Date.now() / 1000);
  127. }
  128. presenceData.startTimestamp = elapsed;
  129. if (document.location.hostname.includes("help.wolfy")) {
  130. if (path.includes("article") && path[1]) {
  131. presenceData.details = "Lit l'article ⤵️";
  132. presenceData.state = document.querySelector("h1")?.textContent;
  133. addConsultArticleButton(presenceData, document.location.href);
  134. addVisitHelpCenterButton(presenceData);
  135. } else if (path.includes("category") && path[1]) {
  136. presenceData.details = "Consulte la catégorie ⤵️";
  137. presenceData.state = document.querySelector(
  138. "span.csh-category-badge"
  139. )?.textContent;
  140. addConsultCategoryButton(presenceData, document.location.href);
  141. } else {
  142. presenceData.details = "Consulte le centre d'aide";
  143. presenceData.state = "Page d'accueil";
  144. addVisitHelpCenterButton(presenceData);
  145. }
  146. } else if (path.includes("articles") && path[1]) {
  147. presenceData.details = "Lis l'article ⤵️";
  148. presenceData.smallImageKey = Assets.Reading;
  149. presenceData.smallImageText = "Lis un article";
  150. presenceData.state = document.querySelector("body h1").textContent;
  151. } else if (path.includes("game") && path[1]) {
  152. presenceData.state = document
  153. .querySelector("div[class*='Header_nameState']")
  154. .textContent.toUpperCase();
  155. if (presenceData.state !== prevState) {
  156. delete presenceData.startTimestamp;
  157. delete presenceData.endTimestamp;
  158. prevState = presenceData.state;
  159. cp = Date.now();
  160. currTime = document.querySelector(
  161. "div[class*='Header_timer']"
  162. ).textContent;
  163. }
  164. await addVisitProfilButton(
  165. presenceData,
  166. document.querySelector("span[class*='ChatMain_username']")?.textContent // Will be the anonymous username if used
  167. );
  168. if (
  169. isWaitingGame(presenceData.state, document.querySelector("html")?.lang)
  170. ) {
  171. presenceData.state += ` (${
  172. document.querySelector("div[class*='Header_timeState']")?.textContent
  173. })`;
  174. await addJoinGameButton(presenceData, path[1]);
  175. }
  176. presenceData.details = "En jeu";
  177. presenceData.smallImageKey = Assets.Live;
  178. if (currTime?.includes(":")) {
  179. [presenceData.startTimestamp, presenceData.endTimestamp] = getTimestamps(
  180. cp,
  181. currTime
  182. );
  183. } else presenceData.startTimestamp = cp;
  184. } else if (path.includes("leaderboard")) {
  185. await addVisitProfilButton(
  186. presenceData,
  187. document.querySelector("p.Social_username__qpX4D")?.textContent
  188. );
  189. await handleCheckingLeaderboard(presenceData, path[1]);
  190. } else if (path.includes("event") && path[1]) {
  191. if (document.querySelector("div[class*='Event_eventIntroduction']'")) {
  192. presenceData.details = "Participe à un évènement";
  193. presenceData.state = `Top ${parseInt(
  194. document.querySelector(
  195. "div[class*='Event_lineLeaderboard'][class*='Event_me'] > div[class*='Event_rank']"
  196. ).textContent
  197. ).toLocaleString()} - ${parseInt(
  198. document.querySelector(
  199. "div[class*='Event_lineLeaderboard Event_me'][class*='Event_me'] > div[class*='Event_points']"
  200. ).textContent
  201. ).toLocaleString()} points`;
  202. } else {
  203. presenceData.details = "Consulte un évènement à venir ⤵️";
  204. presenceData.state = document.querySelector(
  205. "div[class*='Event_title']"
  206. )?.textContent;
  207. }
  208. addConsultEventButton(presenceData, document.location.href);
  209. } else {
  210. await addVisitProfilButton(
  211. presenceData,
  212. document.querySelector("p[class*='Social_username']")?.textContent
  213. );
  214. presenceData.details = "Dans un menu";
  215. switch (path[0]) {
  216. case "skin":
  217. presenceData.smallImageKey = Assets.Skin;
  218. presenceData.smallImageText = "Choisis ton skin";
  219. presenceData.state = "Consulte ses Skins";
  220. break;
  221. case "settings":
  222. presenceData.state = "Change ses paramètres";
  223. break;
  224. case "shop":
  225. presenceData.smallImageKey = Assets.Shop;
  226. presenceData.smallImageText = "Achète des skins";
  227. presenceData.state = "Consulte la Boutique";
  228. break;
  229. case "articles":
  230. presenceData.state = "Consulte les dernières actualités";
  231. presenceData.smallImageKey = Assets.Reading;
  232. presenceData.smallImageText = "En train de lire";
  233. break;
  234. default:
  235. presenceData.state = "Page d'accueil";
  236. }
  237. }
  238. if (!presenceData.buttons || !presenceData.buttons[1])
  239. addVisitWolfyButton(presenceData);
  240. presence.setActivity(presenceData);
  241. });