presence.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. const presence = new Presence({
  2. clientId: "1256196660657393714",
  3. });
  4. let isFetching = false;
  5. const enum Assets {
  6. Logo = "https://cdn.rcd.gg/PreMiD/websites/M/Max/assets/logo.png",
  7. }
  8. let fetchedInfo: {
  9. included: {
  10. attributes: {
  11. alternateId: string;
  12. src?: string;
  13. name?: string;
  14. episodeNumber?: number;
  15. seasonNumber?: number;
  16. videoType?: string;
  17. };
  18. id: string;
  19. relationships?: {
  20. images: {
  21. data: {
  22. id: string;
  23. }[];
  24. };
  25. show: {
  26. data: {
  27. id: string;
  28. };
  29. };
  30. };
  31. }[];
  32. path: string;
  33. };
  34. function findAlternateId(id: string) {
  35. return fetchedInfo.included?.find(x => x.attributes?.alternateId === id);
  36. }
  37. function findId(id: string) {
  38. return fetchedInfo.included?.find(x => x.id === id);
  39. }
  40. async function fetchPageInfo() {
  41. const { pathname } = location;
  42. if (isFetching || fetchedInfo?.path === pathname) return;
  43. isFetching = true;
  44. try {
  45. fetchedInfo = await fetch(
  46. `https://default.any-amer.prd.api.max.com/cms/routes${pathname}?include=default&page[items.size]=10`,
  47. {
  48. method: "GET",
  49. credentials: "include",
  50. }
  51. ).then(res => res.json());
  52. } catch {
  53. isFetching = false;
  54. return false;
  55. }
  56. fetchedInfo.path = pathname;
  57. isFetching = false;
  58. return true;
  59. }
  60. function getTitleInfo(usePresenceName?: boolean) {
  61. if (!fetchedInfo) return;
  62. if (location.pathname.includes("/video/")) {
  63. const episodeInfo = findAlternateId(location.pathname.split("/")[3]),
  64. showInfo = findAlternateId(episodeInfo?.relationships.show.data.id);
  65. if (!episodeInfo || !showInfo) return;
  66. return {
  67. name: usePresenceName ? showInfo.attributes.name : "Max",
  68. details: usePresenceName
  69. ? episodeInfo.attributes.name
  70. : showInfo.attributes.name,
  71. state:
  72. episodeInfo.attributes.videoType === "MOVIE"
  73. ? "Movie"
  74. : usePresenceName
  75. ? `Season ${episodeInfo.attributes.seasonNumber}, Episode ${episodeInfo.attributes.episodeNumber}`
  76. : `S${episodeInfo.attributes.seasonNumber}:E${episodeInfo.attributes.episodeNumber} ${episodeInfo.attributes.name}`,
  77. largeImageKey: findId(showInfo.relationships.images.data[5].id).attributes
  78. .src,
  79. };
  80. }
  81. const info = findAlternateId(location.pathname.split("/")[2]);
  82. return {
  83. state: info?.attributes.name,
  84. largeImageKey: findId(info?.relationships.images.data[5].id)?.attributes
  85. .src,
  86. };
  87. }
  88. presence.on("UpdateData", async () => {
  89. const presenceData: PresenceData = {
  90. type: ActivityType.Watching,
  91. largeImageKey: Assets.Logo,
  92. },
  93. [usePresenceName, showCoverArt] = await Promise.all([
  94. presence.getSetting<boolean>("usePresenceName"),
  95. presence.getSetting<boolean>("cover"),
  96. ]);
  97. await fetchPageInfo();
  98. switch (document.location.pathname.split("/")[1]) {
  99. case "show": {
  100. Object.assign(presenceData, getTitleInfo());
  101. presenceData.details = "Viewing a show:";
  102. break;
  103. }
  104. case "movie": {
  105. Object.assign(presenceData, getTitleInfo());
  106. presenceData.details = "Viewing a movie:";
  107. break;
  108. }
  109. case "video": {
  110. const video = document.querySelector("video");
  111. Object.assign(presenceData, getTitleInfo(usePresenceName));
  112. if (video) {
  113. if (!video.paused) {
  114. [presenceData.startTimestamp, presenceData.endTimestamp] =
  115. presence.getTimestampsfromMedia(video);
  116. }
  117. presenceData.smallImageKey = video.paused ? Assets.Pause : Assets.Play;
  118. presenceData.smallImageText = video.paused ? "Paused" : "Playing";
  119. }
  120. break;
  121. }
  122. default: {
  123. presenceData.details = "Browsing...";
  124. break;
  125. }
  126. }
  127. if (!showCoverArt) presenceData.largeImageKey = Assets.Logo;
  128. if (presenceData.details) presence.setActivity(presenceData);
  129. else presence.setActivity();
  130. });