presence.ts 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. import { ActivityType, Assets } from 'premid'
  2. const presence = new Presence({
  3. clientId: '1206601150607134780',
  4. })
  5. const browsingTimestamp = Math.floor(Date.now() / 1000)
  6. async function getStrings() {
  7. return presence.getStrings(
  8. {
  9. buttonWatchStream: 'general.buttonWatchStream',
  10. buttonWatchVideo: 'general.buttonWatchVideo',
  11. live: 'general.live',
  12. pause: 'general.paused',
  13. paused: 'general.paused',
  14. play: 'general.playing',
  15. playing: 'general.playing',
  16. readingArticle: 'general.readingArticle',
  17. search: 'general.search',
  18. searchFor: 'general.searchFor',
  19. searchSomething: 'general.searchSomething',
  20. upload: 'youtube.upload',
  21. viewHome: 'general.viewHome',
  22. viewList: 'general.viewList',
  23. viewSeries: 'general.viewSeries',
  24. waitingLive: 'general.waitingLive',
  25. waitingLiveThe: 'general.waitingLiveThe',
  26. watchingLive: 'general.watchingLive',
  27. watchingVid: 'general.watchingVid',
  28. },
  29. await presence.getSetting<string>('lang').catch(() => 'en'),
  30. )
  31. }
  32. let strings: Awaited<ReturnType<typeof getStrings>>
  33. let oldLang: string | null = null
  34. presence.on('UpdateData', async () => {
  35. const presenceData: PresenceData = {
  36. name: 'Tver',
  37. type: ActivityType.Watching,
  38. largeImageKey: 'https://cdn.rcd.gg/PreMiD/websites/T/TVer/assets/logo.png',
  39. startTimestamp: browsingTimestamp,
  40. }
  41. const [
  42. buttons,
  43. liveDetail,
  44. liveState,
  45. newLang,
  46. privacy,
  47. showTimestamps,
  48. vidDetail,
  49. vidState,
  50. videoPic,
  51. ] = await Promise.all([
  52. presence.getSetting<boolean>('buttons'),
  53. presence.getSetting<string>('liveDetail'),
  54. presence.getSetting<string>('liveState'),
  55. presence.getSetting<string>('lang').catch(() => 'en'),
  56. presence.getSetting<boolean>('privacy'),
  57. presence.getSetting<boolean>('timestamp'),
  58. presence.getSetting<string>('vidDetail'),
  59. presence.getSetting<string>('vidState'),
  60. presence.getSetting<boolean>('videoPic'),
  61. ])
  62. const { pathname, href } = document.location
  63. const title = document.querySelector(
  64. '[class^=\'titles_container\'] h1',
  65. )?.textContent
  66. const seriesTitle = document.querySelector(
  67. '[class^=\'titles_container\'] h2',
  68. )?.textContent
  69. if (oldLang !== newLang || !strings) {
  70. oldLang = newLang
  71. strings = await getStrings()
  72. }
  73. switch (pathname) {
  74. case '/': {
  75. presenceData.details = strings.viewHome
  76. break
  77. }
  78. case '/mypage/fav':
  79. case '/mypage/later':
  80. case '/mypage/resume': {
  81. presenceData.details = document.querySelector(
  82. '[class*=\'mypage-page-main_selectedTab\']',
  83. )?.textContent
  84. break
  85. }
  86. default:
  87. if (pathname.includes('/live')) {
  88. const isScheduled = document.querySelector(
  89. '[class^=\'live-scheduled_host\']',
  90. )
  91. const tvStation = document.querySelector(
  92. '[class^=\'description_metaDetail\'] > span',
  93. )?.textContent
  94. if (privacy) {
  95. if (isScheduled)
  96. presenceData.details = strings.waitingLive
  97. else presenceData.details = strings.watchingLive
  98. }
  99. else {
  100. if (videoPic) {
  101. presenceData.largeImageKey = document
  102. .querySelector<HTMLImageElement>(
  103. '[class*=\'live_active\'] > div > img',
  104. )
  105. ?.src
  106. .replace(/(thumbnail\/live\/)[^/]+/, '$1small')
  107. .replace(/\.jpg.*$/, '.jpg')
  108. }
  109. if (isScheduled) {
  110. presenceData.details = strings.waitingLiveThe
  111. }
  112. else {
  113. presenceData.details = liveDetail
  114. .replace('%tvStation%', tvStation ?? '')
  115. .replace('%seriesTitle%', seriesTitle ?? '')
  116. .replace('%title%', title ?? '')
  117. }
  118. presenceData.state = liveState
  119. .replace('%tvStation%', tvStation ?? '')
  120. .replace('%seriesTitle%', seriesTitle ?? '')
  121. .replace('%title%', title ?? '')
  122. presenceData.buttons = [
  123. { label: strings.buttonWatchStream, url: href },
  124. ]
  125. if (
  126. !document.querySelector('[class^=\'live-finished_host\']')
  127. && !isScheduled
  128. ) {
  129. presenceData.smallImageKey = Assets.Live
  130. presenceData.smallImageText = strings.live
  131. }
  132. }
  133. }
  134. else if (pathname.includes('/episodes')) {
  135. if (privacy) {
  136. presenceData.details = strings.watchingVid
  137. }
  138. else {
  139. if (videoPic) {
  140. presenceData.largeImageKey = `https://statics.tver.jp/images/content/thumbnail/episode/small/${
  141. pathname.split('/')[2]
  142. }.jpg`
  143. }
  144. const tvStation = document.querySelector(
  145. '[class^=\'description_meta\'] > div:nth-child(1)',
  146. )?.textContent
  147. presenceData.details = vidDetail
  148. .replace('%tvStation%', tvStation ?? '')
  149. .replace('%seriesTitle%', seriesTitle ?? '')
  150. .replace('%title%', title ?? '')
  151. presenceData.state = vidState
  152. .replace('%tvStation%', tvStation ?? '')
  153. .replace('%seriesTitle%', seriesTitle ?? '')
  154. .replace('%title%', title ?? '')
  155. const { paused } = document.querySelector<HTMLVideoElement>('video')!
  156. if (!paused) {
  157. [presenceData.startTimestamp, presenceData.endTimestamp] = presence.getTimestampsfromMedia(
  158. document.querySelector<HTMLVideoElement>('video')!,
  159. )
  160. }
  161. presenceData.smallImageKey = paused ? Assets.Pause : Assets.Play
  162. presenceData.smallImageText = paused
  163. ? strings.paused
  164. : strings.playing
  165. presenceData.buttons = [
  166. { label: strings.buttonWatchVideo, url: href },
  167. ]
  168. }
  169. }
  170. else if (pathname.includes('/series')) {
  171. presenceData.details = strings.viewSeries
  172. if (!privacy) {
  173. presenceData.state = document.querySelector(
  174. '[class^=\'series-main_title\']',
  175. )?.textContent
  176. }
  177. }
  178. else if (pathname.includes('/specials')) {
  179. presenceData.details = strings.readingArticle
  180. if (!privacy) {
  181. presenceData.state = document.querySelector(
  182. '[class^=\'special-feature-page-main_title\']',
  183. )?.textContent
  184. }
  185. }
  186. else if (pathname.includes('/rankings/episode')) {
  187. presenceData.details = strings.viewList
  188. if (!privacy) {
  189. presenceData.state = document.querySelector(
  190. '[class^=\'select-tabs-switch-list_container\']',
  191. )?.textContent
  192. }
  193. }
  194. else if (pathname.includes('/search')) {
  195. presenceData.details = strings.searchSomething
  196. }
  197. else {
  198. presenceData.details = strings.viewHome
  199. }
  200. }
  201. if (!showTimestamps) {
  202. delete presenceData.startTimestamp
  203. delete presenceData.endTimestamp
  204. }
  205. if (!buttons)
  206. delete presenceData.buttons
  207. presence.setActivity(presenceData)
  208. })