presence.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. const presence = new Presence({
  2. clientId: "681116862930747520",
  3. });
  4. let oldLang: string,
  5. newLang: string,
  6. strings: Awaited<ReturnType<typeof getStrings>>,
  7. timestamp = 0,
  8. previous: Location,
  9. current: Location;
  10. presence.on("UpdateData", async () => {
  11. const path = current.pathname.split("/").slice(1),
  12. presenceData: PresenceData = {
  13. largeImageKey:
  14. "https://cdn.rcd.gg/PreMiD/websites/K/Keep%20Talking%20and%20Nobody%20Explodes/assets/logo.png",
  15. };
  16. oldLang = newLang;
  17. newLang = await presence.getSetting<string>("lang").catch(() => "en");
  18. if (!strings || oldLang !== newLang) strings = await getStrings(newLang);
  19. current = window.location;
  20. if (current.hostname.split(".")[0] === "bombmanual") {
  21. // Bomb manual page
  22. switch (isLanguageCode(path[0]) ? path[1] : path[0]) {
  23. // Web manual, PDF manual
  24. case "web":
  25. case "print": {
  26. if (timestamp === 0 || isNewLocation(previous, current))
  27. timestamp = Date.now();
  28. const pages = [...document.querySelectorAll<HTMLDivElement>(".page")],
  29. page = Math.round(
  30. (window.scrollY / getDocumentHeight()) * (pages.length - 1)
  31. );
  32. presenceData.details = document
  33. .querySelector<HTMLTitleElement>(".title")
  34. .textContent.replace(/\n|\t/g, "");
  35. presenceData.smallImageText = strings.reading;
  36. presenceData.smallImageKey = Assets.Reading;
  37. presenceData.startTimestamp = timestamp;
  38. if (page === 0) {
  39. presenceData.state =
  40. document.querySelector<HTMLHeadingElement>(
  41. ".versioning"
  42. ).firstChild.textContent;
  43. } else {
  44. presenceData.state = `${strings.page} ${page + 1} / ${
  45. pages.length
  46. }: ${pages[page].children[0].children[1].textContent}`;
  47. }
  48. break;
  49. }
  50. // How to play, Language select
  51. case "how-to-play-pc.html":
  52. case "how-to-play-mobile.html":
  53. case "how-to-play-switch.html":
  54. case "how-to-play-xbox.html":
  55. case "how-to-play-playstation.html":
  56. case "how-to-play-vr.html":
  57. case "how-to-play-psvr.html":
  58. case "how-to-play-gear-vr.html":
  59. case "how-to-play-oculus-go.html":
  60. case "how-to-play-oculus-quest.html":
  61. case "how-to-play-daydream.html":
  62. case "language":
  63. presenceData.details = document.title;
  64. break;
  65. // Startpage, Unknown
  66. default:
  67. return presence.setActivity();
  68. }
  69. } else {
  70. // Main page
  71. switch (path[0]) {
  72. // Contact Us, Privacy Policy
  73. case "contact-us":
  74. case "privacy-policy":
  75. presenceData.details =
  76. document.querySelector<HTMLHeadingElement>("h1")?.textContent ??
  77. document.title;
  78. break;
  79. // Presskit
  80. case "presskit":
  81. presenceData.details = "Presskit";
  82. break;
  83. // How To Play Remotely
  84. case "how-to-play-remotely":
  85. presenceData.details = "How To Play Remotely";
  86. break;
  87. // Mobile app
  88. case "mobile":
  89. presenceData.details = "Mobile App";
  90. break;
  91. // Translation FAQ
  92. case "translation-faq":
  93. presenceData.details = "Translation FAQ";
  94. break;
  95. case "faq":
  96. presenceData.details = "FAQ";
  97. if (window.location.hash?.length > 0) {
  98. presenceData.state = document.querySelector(
  99. window.location.hash
  100. ).children[0].children[0].children[0].children[0].children[0].textContent;
  101. }
  102. break;
  103. // Commercial Licensing
  104. case "commercial-license":
  105. presenceData.details = "Commercial Licensing";
  106. break;
  107. // Non-Commercial Use
  108. case "non-commercial-use":
  109. presenceData.details = "Non-Commercial Use";
  110. break;
  111. // Startpage, Unknown
  112. default:
  113. return presence.setActivity();
  114. }
  115. }
  116. presence.setActivity(presenceData);
  117. previous = current;
  118. });
  119. async function getStrings(lang: string) {
  120. return presence.getStrings(
  121. {
  122. reading: "general.reading",
  123. page: "general.page",
  124. },
  125. lang
  126. );
  127. }
  128. function getDocumentHeight() {
  129. const { body } = document,
  130. { documentElement: html } = document;
  131. return Math.max(
  132. body.scrollHeight,
  133. body.offsetHeight,
  134. html.clientHeight,
  135. html.scrollHeight,
  136. html.offsetHeight
  137. );
  138. }
  139. function isLanguageCode(text: string) {
  140. return /^(?<lang>[a-z]{2})(-(?<region>[A-Z]{2}))?$/.test(text);
  141. }
  142. function isNewLocation(previous: Location, current: Location) {
  143. return (
  144. !previous ||
  145. !current ||
  146. previous.hostname !== current.hostname ||
  147. previous.pathname !== current.pathname ||
  148. previous.protocol !== current.protocol ||
  149. previous.port !== current.port
  150. );
  151. }