presence.ts 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. const presence = new Presence({
  2. clientId: "1026195572354449428",
  3. }),
  4. browsingTimestamp = Math.floor(Date.now() / 1000);
  5. let characterCreatorMenu: string[] = ["species"];
  6. setInterval(() => {
  7. if (window.location.pathname === "/") {
  8. characterCreatorMenu = [
  9. ...document.querySelectorAll<HTMLDivElement>("#menuA, #menuB, #menuC"),
  10. ].map(menu => {
  11. return [...menu.children]
  12. .find(listItem => {
  13. return getComputedStyle(listItem).backgroundImage !== "none";
  14. })
  15. ?.textContent.trim()
  16. .toLowerCase();
  17. });
  18. }
  19. }, 1000);
  20. presence.on("UpdateData", async () => {
  21. const presenceData: PresenceData = {
  22. largeImageKey:
  23. "https://cdn.rcd.gg/PreMiD/websites/H/Hero%20Forge/assets/logo.png",
  24. startTimestamp: browsingTimestamp,
  25. },
  26. { pathname } = window.location,
  27. [, path] = pathname.split("/");
  28. switch (path ?? "") {
  29. case "": {
  30. if (
  31. document.querySelector<HTMLImageElement>(
  32. "[src='/static/svg/bug-white.svg']"
  33. )
  34. )
  35. presenceData.details = "Creating a bug report";
  36. else if (document.querySelector("[class*='characterFolder']"))
  37. presenceData.details = "Viewing their characters";
  38. else {
  39. const characterName = document
  40. .querySelector<HTMLDivElement>(
  41. "img[src='/static/svg/character-menu/character.svg'] + div"
  42. )
  43. .textContent.match(/^(.*?)\*?$/)[1],
  44. chosenItemContainer = document.querySelector<HTMLSpanElement>(
  45. "#view span[style*='/static/svg/item-selected.svg']"
  46. ),
  47. chosenItemImage =
  48. chosenItemContainer?.firstElementChild as HTMLImageElement,
  49. chosenItemName = chosenItemImage?.alt.match(/^(.*?) Add Part$/)[1];
  50. let mainState = "",
  51. subState = "";
  52. presenceData.details = `Modifying Character: ${characterName}`;
  53. switch (characterCreatorMenu[0]) {
  54. case "species": {
  55. mainState = "Species";
  56. if (chosenItemContainer) {
  57. subState = `${
  58. /Female_thumb/.test(chosenItemImage.src) ? "Female" : "Male"
  59. } ${
  60. chosenItemContainer.parentElement.nextElementSibling.textContent
  61. }`;
  62. }
  63. break;
  64. }
  65. case "head":
  66. case "gear":
  67. case "stage": {
  68. switch (characterCreatorMenu[0]) {
  69. case "head": {
  70. mainState = "facial features";
  71. break;
  72. }
  73. case "gear": {
  74. mainState = "gear";
  75. break;
  76. }
  77. case "stage": {
  78. mainState = "stage";
  79. break;
  80. }
  81. }
  82. if (chosenItemContainer)
  83. subState = `${characterCreatorMenu[1]} - ${chosenItemName}`;
  84. else subState = characterCreatorMenu[1];
  85. break;
  86. }
  87. case "body": {
  88. mainState = "Body Features";
  89. if (characterCreatorMenu[1] === "measure")
  90. subState = "Measurements";
  91. else if (chosenItemContainer)
  92. subState = `${characterCreatorMenu[1]} - ${chosenItemName}`;
  93. else subState = characterCreatorMenu[1];
  94. break;
  95. }
  96. case "clothing": {
  97. mainState = "Clothing";
  98. if (characterCreatorMenu[1] === "outfit") subState = "Outfit";
  99. else if (chosenItemContainer)
  100. subState = `${characterCreatorMenu[1]} - ${chosenItemName}`;
  101. else subState = characterCreatorMenu[1];
  102. break;
  103. }
  104. case "pose": {
  105. mainState = "Pose";
  106. switch (characterCreatorMenu[1]) {
  107. case "body":
  108. case "face": {
  109. if (chosenItemContainer)
  110. subState = `${characterCreatorMenu[1]} - ${chosenItemName}`;
  111. else subState = characterCreatorMenu[1];
  112. break;
  113. }
  114. case "eyes": {
  115. subState = "eyes";
  116. break;
  117. }
  118. case "advanced": {
  119. subState = "Advanced";
  120. break;
  121. }
  122. }
  123. break;
  124. }
  125. case "color": {
  126. mainState = "Color";
  127. switch (characterCreatorMenu[1]) {
  128. case "body":
  129. case "theme": {
  130. subState = characterCreatorMenu[1];
  131. break;
  132. }
  133. case "decals": {
  134. if (chosenItemContainer)
  135. subState = `decals - ${chosenItemName}`;
  136. else subState = "decals";
  137. break;
  138. }
  139. case "paints":
  140. case "mix": {
  141. const selectedPaintIcon =
  142. document.querySelector<HTMLImageElement>(
  143. "[src*='/static/svg/tools/paint-selection.svg']"
  144. );
  145. if (selectedPaintIcon) {
  146. subState = `${characterCreatorMenu[1]} - ${
  147. (
  148. selectedPaintIcon.previousElementSibling as HTMLImageElement
  149. ).alt
  150. }`;
  151. } else subState = characterCreatorMenu[1];
  152. break;
  153. }
  154. }
  155. break;
  156. }
  157. case "booth": {
  158. mainState = "Booth";
  159. break;
  160. }
  161. case "buy": {
  162. mainState = "Buying Items";
  163. switch (characterCreatorMenu[1]) {
  164. case "mini": {
  165. const selectedMini = document.querySelector<HTMLDivElement>(
  166. "#view [class*=name]"
  167. );
  168. if (selectedMini)
  169. subState = `${characterCreatorMenu[1]} - ${selectedMini.textContent}`;
  170. else subState = characterCreatorMenu[1];
  171. break;
  172. }
  173. case "packs": {
  174. const selectedPack = document.querySelector<HTMLDivElement>(
  175. "#view [class*=displayLabel]"
  176. );
  177. if (selectedPack)
  178. subState = `${characterCreatorMenu[1]} - ${selectedPack.textContent}`;
  179. else subState = characterCreatorMenu[1];
  180. break;
  181. }
  182. case "dice": {
  183. subState = "dice";
  184. break;
  185. }
  186. case "gift cards": {
  187. subState = "gift cards";
  188. break;
  189. }
  190. case "digital credits": {
  191. subState = "digital credits";
  192. break;
  193. }
  194. }
  195. break;
  196. }
  197. }
  198. if (subState) {
  199. presenceData.state = `${mainState[0].toUpperCase()}${mainState.slice(
  200. 1
  201. )}: ${subState[0].toUpperCase()}${subState.slice(1)}`;
  202. } else {
  203. presenceData.state = `${mainState[0].toUpperCase()}${mainState.slice(
  204. 1
  205. )}`;
  206. }
  207. }
  208. break;
  209. }
  210. case "account": {
  211. presenceData.details = "Managing account settings";
  212. presenceData.state = document.querySelector<HTMLAnchorElement>(
  213. "[class*=sidenavContainer] [class*=itemActive]"
  214. ).textContent;
  215. break;
  216. }
  217. case "cart": {
  218. presenceData.details = "Viewing cart";
  219. break;
  220. }
  221. case "intro": {
  222. presenceData.details = "Browsing";
  223. presenceData.state = "Sample characters and introduction";
  224. break;
  225. }
  226. case "media-request": {
  227. presenceData.details = "Creating a media request";
  228. presenceData.state = document.querySelector<HTMLLabelElement>(
  229. "#issue_choices input:checked + label"
  230. ).textContent;
  231. break;
  232. }
  233. case "suggest": {
  234. presenceData.details = "Suggesting a feature";
  235. break;
  236. }
  237. default: {
  238. if (path.startsWith("load_config"))
  239. presenceData.details = "Loading character";
  240. else {
  241. presenceData.details = "Browsing";
  242. presenceData.state = document.title.match(
  243. /^(.*?)(?: \| Hero Forge®)?$/
  244. )[1];
  245. }
  246. }
  247. }
  248. if (presenceData.details) presence.setActivity(presenceData);
  249. else presence.setActivity();
  250. });