presence.ts 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. const presence = new Presence({
  2. clientId: "1023277091392868372",
  3. }),
  4. browsingTimestamp = Math.floor(Date.now() / 1000);
  5. presence.on("UpdateData", async () => {
  6. const presenceData: PresenceData = {
  7. largeImageKey:
  8. "https://cdn.rcd.gg/PreMiD/websites/M/mod.io/assets/logo.png",
  9. startTimestamp: browsingTimestamp,
  10. },
  11. { pathname, href, hostname, search } = window.location,
  12. pathSplit = pathname.split("/").filter(x => x);
  13. switch (hostname) {
  14. case "mod.io": {
  15. switch (pathSplit[0] ?? "") {
  16. case "": {
  17. presenceData.details = "Browsing homepage";
  18. break;
  19. }
  20. case "g": {
  21. if (pathSplit[1] === "add") {
  22. presenceData.details = "Adding a game";
  23. presenceData.state =
  24. document.querySelector<HTMLHeadingElement>("h1").textContent;
  25. } else if ((pathSplit[1] ?? "") === "") {
  26. presenceData.details = "Browsing games";
  27. break;
  28. } else {
  29. const gameImageURL = getComputedStyle(
  30. document.querySelector<HTMLDivElement>("#container [role=img]")
  31. ).backgroundImage.match(/url\("(.+)"\)/)?.[1],
  32. gameName = document.querySelector<HTMLAnchorElement>(
  33. "#container li > a[href*='/g/']"
  34. ).textContent;
  35. switch (pathSplit[2] ?? "") {
  36. case "": {
  37. presenceData.details = `Browsing mods for ${gameName}`;
  38. presenceData.largeImageKey = gameImageURL;
  39. presenceData.buttons = [
  40. {
  41. label: "View game mods",
  42. url: href,
  43. },
  44. ];
  45. break;
  46. }
  47. case "m": {
  48. if (pathSplit[4] === "admin") {
  49. presenceData.details = "Managing a mod";
  50. presenceData.state =
  51. document.querySelector<HTMLHeadingElement>(
  52. "h1"
  53. ).textContent;
  54. } else {
  55. presenceData.details = `Viewing a mod for ${gameName}`;
  56. presenceData.state =
  57. document.querySelector<HTMLHeadingElement>(
  58. "h1"
  59. ).textContent;
  60. presenceData.smallImageKey = gameImageURL;
  61. presenceData.smallImageText = gameName;
  62. presenceData.largeImageKey = getComputedStyle(
  63. document.querySelector<HTMLDivElement>(
  64. "a[href*='/m/'] > div[role=img]"
  65. )
  66. ).backgroundImage.match(/url\("(.+)"\)/)[1];
  67. presenceData.buttons = [
  68. {
  69. label: "View mod",
  70. url: href,
  71. },
  72. ];
  73. }
  74. break;
  75. }
  76. case "r": {
  77. if (pathSplit[3]) {
  78. presenceData.details = `Reading a guide for ${gameName}`;
  79. presenceData.state =
  80. document.querySelector<HTMLHeadingElement>(
  81. "h1"
  82. ).textContent;
  83. presenceData.smallImageKey = gameImageURL;
  84. presenceData.smallImageText = gameName;
  85. presenceData.largeImageKey = getComputedStyle(
  86. document.querySelector<HTMLDivElement>(
  87. "a[href*='/r/'] > div[role=img]"
  88. )
  89. ).backgroundImage.match(/url\("(.+)"\)/)[1];
  90. presenceData.buttons = [
  91. {
  92. label: "View guide",
  93. url: href,
  94. },
  95. ];
  96. } else {
  97. presenceData.details = `Browsing guides for ${gameName}`;
  98. presenceData.largeImageKey = gameImageURL;
  99. }
  100. break;
  101. }
  102. case "u": {
  103. presenceData.details = "Viewing a user's profile";
  104. presenceData.state =
  105. document.querySelector<HTMLHeadingElement>("h1").textContent;
  106. presenceData.smallImageKey =
  107. document.querySelector<HTMLImageElement>(
  108. "#container img[src*='/members/']"
  109. )?.src;
  110. break;
  111. }
  112. }
  113. }
  114. break;
  115. }
  116. case "me": {
  117. switch (pathSplit[1]) {
  118. case "account": {
  119. presenceData.details = "Managing account settings";
  120. break;
  121. }
  122. case "library": {
  123. presenceData.details = "Browsing their library";
  124. break;
  125. }
  126. case "comments": {
  127. presenceData.details = "Browsing their comments";
  128. break;
  129. }
  130. case "followers": {
  131. presenceData.details = "Browsing their followers";
  132. break;
  133. }
  134. case "access": {
  135. presenceData.details = "Managing their API keys";
  136. break;
  137. }
  138. case "privacy": {
  139. presenceData.details = "Managing their privacy settings";
  140. break;
  141. }
  142. }
  143. break;
  144. }
  145. case "u": {
  146. presenceData.details = "Viewing a user's profile";
  147. presenceData.state =
  148. document.querySelector<HTMLHeadingElement>("h1").textContent;
  149. presenceData.smallImageKey = document.querySelector<HTMLImageElement>(
  150. "#container img[src*='/members/']"
  151. )?.src;
  152. break;
  153. }
  154. default: {
  155. presenceData.details = "Browsing";
  156. presenceData.state =
  157. document.querySelector<HTMLHeadingElement>("h1").textContent ??
  158. document.title.match(/(.*) - mod\.io/)[1];
  159. }
  160. }
  161. break;
  162. }
  163. case "blog.mod.io": {
  164. switch (pathSplit[0] ?? "") {
  165. case "": {
  166. presenceData.details = "Browsing the blog";
  167. presenceData.state = "Home page";
  168. break;
  169. }
  170. case "search": {
  171. presenceData.details = "Searching the blog";
  172. presenceData.state = new URLSearchParams(search).get("q");
  173. break;
  174. }
  175. case "tagged": {
  176. presenceData.details = "Browsing articles by tag";
  177. presenceData.state = pathSplit[1];
  178. break;
  179. }
  180. default: {
  181. presenceData.details = "Reading an article";
  182. presenceData.state =
  183. document.querySelector<HTMLHeadingElement>("h1").textContent;
  184. presenceData.buttons = [
  185. {
  186. label: "Read article",
  187. url: href,
  188. },
  189. ];
  190. }
  191. }
  192. break;
  193. }
  194. case "docs.mod.io": {
  195. presenceData.details = "Browsing documentation";
  196. presenceData.state =
  197. document.querySelector<HTMLAnchorElement>(
  198. ".active.toc-link"
  199. ).textContent;
  200. break;
  201. }
  202. case "old.mod.io": {
  203. switch (pathSplit[0] ?? "") {
  204. case "": {
  205. presenceData.details = "Browsing";
  206. presenceData.state = "Home page";
  207. break;
  208. }
  209. case "games": {
  210. if (pathSplit[1] === "add") {
  211. presenceData.details = "Adding a game";
  212. presenceData.state =
  213. document.querySelector<HTMLInputElement>("#gamesname").value;
  214. } else presenceData.details = "Browsing games";
  215. break;
  216. }
  217. case "guides": {
  218. presenceData.details = "Browsing guides";
  219. break;
  220. }
  221. case "members": {
  222. presenceData.details = "Viewing a user's profile";
  223. presenceData.state =
  224. document.querySelector<HTMLHeadingElement>("h2.title").textContent;
  225. const profileImage = document.querySelector<HTMLImageElement>(
  226. ".container img[src*='/members/']"
  227. );
  228. if (profileImage) presenceData.smallImageKey = profileImage.src;
  229. break;
  230. }
  231. case "messages": {
  232. presenceData.details = "Viewing their direct messages";
  233. break;
  234. }
  235. default: {
  236. presenceData.details = "Browsing";
  237. presenceData.state = document.title.match(/(.*) - mod\.io/)[1];
  238. }
  239. }
  240. break;
  241. }
  242. // Old subdomains
  243. default: {
  244. const gameName = document.querySelector<HTMLAnchorElement>(
  245. ".navbar-start .navbar-item[href*='.old.mod.io']"
  246. ).textContent,
  247. gameImage =
  248. document.querySelector<HTMLImageElement>("[src*='/games/']").src;
  249. switch (pathSplit[0] ?? "") {
  250. case "":
  251. case "page": {
  252. presenceData.details = `Browsing mods for ${gameName}`;
  253. presenceData.largeImageKey = gameImage;
  254. break;
  255. }
  256. case "guides": {
  257. presenceData.largeImageKey = gameImage;
  258. switch (pathSplit[1] ?? "") {
  259. case "": {
  260. presenceData.details = `Browsing guides for ${gameName}`;
  261. break;
  262. }
  263. case "add": {
  264. presenceData.details = `Creating a guide for ${gameName}`;
  265. presenceData.state =
  266. document.querySelector<HTMLInputElement>("#articlesname").value;
  267. break;
  268. }
  269. default: {
  270. presenceData.details = `Viewing a guide for ${gameName}`;
  271. presenceData.state =
  272. document.querySelector<HTMLHeadingElement>("h1").textContent;
  273. presenceData.buttons = [
  274. {
  275. label: "Read guide",
  276. url: href,
  277. },
  278. ];
  279. break;
  280. }
  281. }
  282. break;
  283. }
  284. default: {
  285. presenceData.state = document.querySelector<HTMLAnchorElement>(
  286. ".navbar-start > .navbar-item:nth-of-type(4)"
  287. ).textContent;
  288. presenceData.largeImageKey = gameImage;
  289. switch (pathSplit[1] ?? "") {
  290. case "": {
  291. presenceData.details = `Viewing a mod for ${gameName}`;
  292. presenceData.smallImageKey = gameImage;
  293. presenceData.smallImageText = gameName;
  294. presenceData.largeImageKey =
  295. document.querySelector<HTMLImageElement>("[src*='/mods/']").src;
  296. presenceData.buttons = [
  297. {
  298. label: "View mod",
  299. url: href,
  300. },
  301. ];
  302. break;
  303. }
  304. case "edit": {
  305. presenceData.details = `Editing a mod for ${gameName}`;
  306. presenceData.state =
  307. document.querySelector<HTMLInputElement>("#modsname").value;
  308. break;
  309. }
  310. case "history": {
  311. presenceData.details = `Viewing the history of a mod for ${gameName}`;
  312. break;
  313. }
  314. case "contact": {
  315. presenceData.details = "Contacting a mod developer";
  316. break;
  317. }
  318. case "stats": {
  319. presenceData.details = `Viewing the stats of a mod for ${gameName}`;
  320. break;
  321. }
  322. }
  323. }
  324. }
  325. }
  326. }
  327. if (presenceData.details) presence.setActivity(presenceData);
  328. else presence.setActivity();
  329. });