presence.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. class Weverse extends Presence {
  2. constructor(options: PresenceOptions) {
  3. super(options);
  4. }
  5. getArtistName(): string {
  6. return (
  7. document
  8. .querySelector("[class*=LiveArtistProfileView_name_item]")
  9. ?.textContent?.trim() ?? "Unknown Artist"
  10. );
  11. }
  12. getStreamTitle(): string {
  13. const titleElement = document.querySelector("h2[class*=TitleView_title]");
  14. if (titleElement) {
  15. const titleTextNodes = Array.from(titleElement.childNodes).filter(
  16. node =>
  17. !(
  18. node instanceof HTMLElement &&
  19. node.matches("[class*=LiveBadgeView_badge]")
  20. )
  21. );
  22. return (
  23. titleTextNodes
  24. .map(node => node.textContent)
  25. .join("")
  26. .trim() || "Unknown Title"
  27. );
  28. }
  29. return "Unknown Title";
  30. }
  31. getThumbnailUrl(): string | undefined {
  32. return document.querySelector<HTMLImageElement>(
  33. "[class*=ProfileThumbnailView_thumbnail_wrap] img"
  34. )?.src;
  35. }
  36. getCommunityName(): string {
  37. return (
  38. document
  39. .querySelector("[class*=HeaderCommunityDropdownWrapperView_name]")
  40. ?.textContent?.trim() ?? "Unknown Community"
  41. );
  42. }
  43. getCommunityImageUrl(): string | undefined {
  44. return document.querySelector<HTMLImageElement>(
  45. "[class*=CommunityAsideWelcomeView_thumbnail] img"
  46. )?.src;
  47. }
  48. getArtistPageName(): string {
  49. return (
  50. document
  51. .querySelector("[class*=HeaderCommunityDropdownWrapperView_name]")
  52. ?.textContent?.trim() ?? "Unknown Artist"
  53. );
  54. }
  55. getMomentThumbnailUrl(): string | undefined {
  56. return document.querySelector<HTMLImageElement>(
  57. "a[class*=PostHeaderView_thumbnail_wrap] img"
  58. )?.src;
  59. }
  60. getMomentNickname(): string {
  61. return (
  62. document
  63. .querySelector("[class*=PostHeaderView_nickname]")
  64. ?.textContent?.trim() ?? "Unknown User"
  65. );
  66. }
  67. getProfileName(): string {
  68. return (
  69. document
  70. .querySelector("h3[class*=CommunityProfileInfoView_profile_name]")
  71. ?.textContent?.trim() ?? "Unknown User"
  72. );
  73. }
  74. getProfileThumbnailUrl(): string | undefined {
  75. return document.querySelector<HTMLImageElement>(
  76. "a[class*=CommunityProfileInfoView_link_thumbnail] img"
  77. )?.src;
  78. }
  79. getFanPostNickname(): string {
  80. const nicknameElement = document.querySelector(
  81. "#modal [class*=PostHeaderView_nickname]"
  82. );
  83. if (nicknameElement) {
  84. const tempDiv = document.createElement("div");
  85. tempDiv.innerHTML = nicknameElement.innerHTML;
  86. for (const el of Array.from(tempDiv.querySelectorAll("em, span")))
  87. el.remove();
  88. return tempDiv.textContent?.trim() ?? "Unknown User";
  89. }
  90. return "Unknown User";
  91. }
  92. getFanPostThumbnailUrl(): string | undefined {
  93. return document.querySelector<HTMLImageElement>(
  94. "#modal [class*=ProfileThumbnailView_thumbnail] img"
  95. )?.src;
  96. }
  97. }
  98. const presence = new Weverse({
  99. clientId: "1284048129414402109",
  100. }),
  101. browsingTimestamp = Math.floor(Date.now() / 1000);
  102. presence.on("UpdateData", async () => {
  103. const privacy = await presence.getSetting<boolean>("privacy"),
  104. showButtons = await presence.getSetting<boolean>("buttons"),
  105. presenceData: PresenceData = {
  106. largeImageKey:
  107. "https://cdn.rcd.gg/PreMiD/websites/W/Weverse/assets/logo.png",
  108. startTimestamp: browsingTimestamp,
  109. };
  110. if (privacy) {
  111. presence.setActivity(presenceData);
  112. return;
  113. }
  114. if (document.location.pathname.includes("/live/")) {
  115. const thumbnailUrl = presence.getThumbnailUrl();
  116. presenceData.details = presence.getStreamTitle();
  117. presenceData.state = presence.getArtistName();
  118. const video = document.querySelector("video");
  119. if (document.querySelector("[class*=LiveBadgeView_-replay]") !== null) {
  120. presenceData.smallImageKey = Assets.Play;
  121. presenceData.smallImageText = "Replay";
  122. if (showButtons) {
  123. presenceData.buttons = [
  124. {
  125. label: `Watch ${presence.getArtistName()} Replay`,
  126. url: document.location.href,
  127. },
  128. ];
  129. }
  130. } else if (video) {
  131. presenceData.smallImageKey = video.paused ? Assets.Pause : Assets.Live;
  132. presenceData.smallImageText = video.paused ? "Paused" : "Live";
  133. if (showButtons) {
  134. presenceData.buttons = [
  135. {
  136. label: `Visit ${presence.getArtistName()} Live`,
  137. url: document.location.href,
  138. },
  139. ];
  140. }
  141. } else {
  142. presenceData.smallImageKey = Assets.Play;
  143. presenceData.smallImageText = "Playing";
  144. if (showButtons) {
  145. presenceData.buttons = [
  146. {
  147. label: `Watch ${presence.getArtistName()} Replay`,
  148. url: document.location.href,
  149. },
  150. ];
  151. }
  152. }
  153. if (thumbnailUrl) presenceData.largeImageKey = thumbnailUrl;
  154. } else if (document.location.pathname === "/")
  155. presenceData.details = "Browsing Weverse";
  156. else if (document.location.pathname.includes("/feed")) {
  157. presenceData.details = "Viewing Community Feed";
  158. presenceData.state = presence.getCommunityName();
  159. const communityImageUrl = presence.getCommunityImageUrl();
  160. if (communityImageUrl) presenceData.largeImageKey = communityImageUrl;
  161. } else if (document.location.pathname.includes("/artist")) {
  162. presenceData.details = "Viewing Artist";
  163. presenceData.state = presence.getArtistPageName();
  164. } else if (document.location.pathname.includes("/moment")) {
  165. presenceData.details = "Viewing Moment";
  166. presenceData.state = presence.getMomentNickname();
  167. const momentThumbnailUrl = presence.getMomentThumbnailUrl();
  168. if (momentThumbnailUrl) presenceData.largeImageKey = momentThumbnailUrl;
  169. } else if (document.location.pathname.includes("/media")) {
  170. presenceData.details = "Viewing Media";
  171. presenceData.state = presence.getCommunityName();
  172. } else if (document.location.pathname.includes("/profile")) {
  173. presenceData.details = `Viewing Profile of ${presence.getProfileName()}`;
  174. presenceData.state = `Community: ${presence.getCommunityName()}`;
  175. const profileThumbnailUrl = presence.getProfileThumbnailUrl();
  176. if (profileThumbnailUrl) presenceData.largeImageKey = profileThumbnailUrl;
  177. } else if (document.location.pathname.includes("/fanpost/")) {
  178. presenceData.details = "Viewing Fan Post";
  179. presenceData.state = presence.getFanPostNickname();
  180. const fanPostThumbnailUrl = presence.getFanPostThumbnailUrl();
  181. if (fanPostThumbnailUrl) presenceData.largeImageKey = fanPostThumbnailUrl;
  182. }
  183. if (presenceData.details) presence.setActivity(presenceData);
  184. else presence.setActivity();
  185. });