presence.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. const presence = new Presence({
  2. clientId: "883446187099840562",
  3. });
  4. async function getStrings() {
  5. return presence.getStrings(
  6. {
  7. play: "general.playing",
  8. pause: "general.paused",
  9. live: "general.live",
  10. },
  11. await presence.getSetting<string>("lang").catch(() => "en")
  12. );
  13. }
  14. let channel: string,
  15. channelTimestamp: number,
  16. strings: Awaited<ReturnType<typeof getStrings>>,
  17. oldLang: string = null;
  18. presence.on("UpdateData", async () => {
  19. let presenceData: PresenceData = {
  20. largeImageKey:
  21. "https://cdn.rcd.gg/PreMiD/websites/C/Cosmote%20TV/assets/logo.png",
  22. };
  23. const pages: Record<string, PresenceData> = {
  24. "#!": {
  25. details: "Browsing",
  26. },
  27. search: {
  28. details: "Searching",
  29. state:
  30. document.querySelector<HTMLInputElement>("#searchFieldInput")?.value,
  31. smallImageKey: Assets.Search,
  32. smallImageText: "Searching",
  33. },
  34. loginSplash: {
  35. details: "Logging In",
  36. },
  37. channels: {
  38. details: "Browsing Channels",
  39. },
  40. watchlist: {
  41. details: "Viewing Watchlist",
  42. },
  43. settings: {
  44. details: "Viewing Settings",
  45. },
  46. privacy: {
  47. details: "Viewing Privacy Policy",
  48. },
  49. livetv: {
  50. details: "Browsing Live TV",
  51. },
  52. inbox: {
  53. details: "Viewing Inbox",
  54. },
  55. "livetv/replaytv": {
  56. details: "Browsing Replay TV",
  57. },
  58. "livetv/guide": {
  59. details: "Browsing Live TV Guide",
  60. },
  61. "onDemand/FILMS": {
  62. details: "Browsing Films",
  63. },
  64. "onDemand/SERIES": {
  65. details: "Browsing Series",
  66. },
  67. "onDemand/MOVIES_CLUB": {
  68. details: "Browsing Movies Club",
  69. },
  70. "onDemand/SPORTS": {
  71. details: "Browsing Sports",
  72. },
  73. "onDemand/DOCUMENTARIES": {
  74. details: "Browsing Documentaries",
  75. },
  76. "onDemand/KIDS": {
  77. details: "Browsing Kids Content",
  78. },
  79. },
  80. [newLang, logo, timestamps] = await Promise.all([
  81. presence.getSetting<string>("lang").catch(() => "en"),
  82. presence.getSetting<boolean>("logo"),
  83. presence.getSetting<boolean>("timestamps"),
  84. ]);
  85. for (const [path, data] of Object.entries(pages)) {
  86. if (document.location.hash.includes(path))
  87. presenceData = { ...presenceData, ...data };
  88. }
  89. if (oldLang !== newLang || !strings) {
  90. oldLang = newLang;
  91. strings = await getStrings();
  92. }
  93. if (document.querySelector<HTMLDivElement>("div[ng-if='showPlayer']")) {
  94. const { paused, currentTime, duration } =
  95. document.querySelector<HTMLVideoElement>("video#arxPlayer");
  96. // TV
  97. if (
  98. document.querySelector<HTMLImageElement>(
  99. "div[ng-if='details.channelLogoWide'] > .wide-logo"
  100. )
  101. ) {
  102. presenceData.details = document.querySelector<HTMLSpanElement>(
  103. ".meta-title[ng-bind~='details.title']"
  104. )?.textContent;
  105. presenceData.state = document.querySelector<HTMLSpanElement>(
  106. ".meta-title[ng-bind='details.channel.title']"
  107. )?.textContent;
  108. if (logo) {
  109. presenceData.largeImageKey = document
  110. .querySelector<HTMLImageElement>(
  111. "div[ng-if='details.channelLogoWide'] > .wide-logo"
  112. )
  113. ?.src.replace("-wide", "-normal");
  114. }
  115. // Live
  116. if (document.querySelector<HTMLSpanElement>(".meta-remain")) {
  117. if (channel !== presenceData.state || !channelTimestamp)
  118. channelTimestamp = Math.floor(Date.now() / 1000);
  119. presenceData.startTimestamp = channelTimestamp;
  120. presenceData.smallImageKey = paused ? Assets.Pause : Assets.Live;
  121. presenceData.smallImageText = paused ? strings.pause : strings.live;
  122. } else {
  123. // Replay / Timeshift
  124. [presenceData.startTimestamp, presenceData.endTimestamp] =
  125. presence.getTimestamps(
  126. presence.timestampFromFormat(
  127. document.querySelector<HTMLSpanElement>("#VcurrentTime")
  128. .textContent
  129. ),
  130. presence.timestampFromFormat(
  131. document.querySelector<HTMLSpanElement>("#Vduration").textContent
  132. )
  133. );
  134. presenceData.smallImageKey = paused ? Assets.Pause : Assets.Play;
  135. presenceData.smallImageText = paused ? strings.pause : strings.play;
  136. }
  137. channel = presenceData.state;
  138. } else {
  139. // On Demand
  140. presenceData.details = document.querySelector<HTMLSpanElement>(
  141. ".meta-title[ng-bind~='details.title']"
  142. ).textContent;
  143. // Series
  144. if (
  145. document.querySelector<HTMLSpanElement>(
  146. "span[ng-bind='details.seriesSubs']"
  147. )?.textContent.length > 0
  148. ) {
  149. const episode = document
  150. .querySelector<HTMLSpanElement>("span[ng-bind='details.seriesSubs']")
  151. .textContent.split(" / ", 3)
  152. .map(str => str.trim());
  153. switch (episode.length) {
  154. case 3:
  155. if (
  156. presenceData.details !== episode[2] &&
  157. !episode[2].endsWith(` ${episode[1]}`) &&
  158. !episode[2].endsWith(` ${episode[1].replace("Ε", "E")}`)
  159. )
  160. presenceData.state = `${episode[0]}:${episode[1]} ${episode[2]}`;
  161. else {
  162. presenceData.state = `${episode[0]
  163. .replace("S", "Season ")
  164. .replace("Κ", "Κύκλος ")} ${episode[1]
  165. .replace("E", "Episode ")
  166. .replace("Ε", "Επεισόδιο ")}`;
  167. }
  168. break;
  169. case 2:
  170. presenceData.state = episode[0]
  171. .replace("E", "Episode ")
  172. .replace("Ε", "Επεισόδιο ");
  173. if (
  174. presenceData.details !== episode[1] &&
  175. !episode[1].endsWith(` ${episode[0]}`)
  176. )
  177. presenceData.state += `: ${episode[1]}`;
  178. break;
  179. case 1:
  180. presenceData.state = episode[0];
  181. }
  182. }
  183. [presenceData.startTimestamp, presenceData.endTimestamp] =
  184. presence.getTimestamps(Math.floor(currentTime), Math.floor(duration));
  185. presenceData.smallImageKey = paused ? Assets.Pause : Assets.Play;
  186. presenceData.smallImageText = paused ? strings.pause : strings.play;
  187. }
  188. if (paused || !timestamps) {
  189. delete presenceData.startTimestamp;
  190. delete presenceData.endTimestamp;
  191. channelTimestamp = null;
  192. }
  193. }
  194. presence.setActivity(presenceData);
  195. });