|
1 | | -import { Assets } from 'premid' |
| 1 | +import { ActivityType, Assets, getTimestamps } from 'premid' |
2 | 2 |
|
3 | 3 | const presence = new Presence({ |
4 | 4 | clientId: '503557087041683458', |
@@ -135,110 +135,173 @@ export async function getThumbnail( |
135 | 135 | }) |
136 | 136 | } |
137 | 137 |
|
| 138 | +// Data we need is deleted when player controls disappear |
| 139 | +let cachedTitleTvShows: [string | null, string | null] = [null, null] |
| 140 | +let cachedEpisodeTitle: string | null = null |
| 141 | +let cachedSynopsis: string | null = null |
| 142 | +let cachedChannelName: string | null = null |
| 143 | +let cachedThumbnailUrl: string | null = null |
| 144 | +let lastImgSrc: string | null = null |
| 145 | + |
| 146 | +const navigationRoutes: Record<string, string> = { |
| 147 | + '/mes-videos/': 'Mes Vidéos', |
| 148 | + '/chaines/': 'Chaînes', |
| 149 | + '/programme-tv/': 'Programme TV', |
| 150 | + '/cinema/': 'Films', |
| 151 | + '/series/': 'Séries', |
| 152 | + '/jeunesse/': 'Jeunesse', |
| 153 | + '/live/': 'Chaînes en direct', |
| 154 | + '/documentaires/': 'Documentaires', |
| 155 | + '/divertissement/': 'Divertissements', |
| 156 | + '/info/': 'Infos', |
| 157 | + '/musique/': 'Musique', |
| 158 | + '/sport/': 'Sport', |
| 159 | +} |
| 160 | + |
138 | 161 | presence.on('UpdateData', async () => { |
139 | 162 | const presenceData: PresenceData = { |
140 | 163 | largeImageKey: myCANALAssets.Logo, |
| 164 | + largeImageText: 'myCANAL', |
141 | 165 | name: 'myCANAL', |
| 166 | + type: ActivityType.Watching, |
142 | 167 | } |
143 | 168 | const video = document.querySelector<HTMLVideoElement>('.iIZX3IGkM2eBzzWle1QQ') |
144 | 169 | const showCover = await presence.getSetting<boolean>('cover') |
145 | | - const mainTitle = document.querySelector('.bodyTitle___HwRP2') |
146 | | - |
147 | | - switch (document.location.pathname) { |
148 | | - case '/mes-videos/': |
149 | | - presenceData.state = 'Mes Vidéos' |
150 | | - break |
151 | | - case '/chaines/': |
152 | | - presenceData.state = 'Chaînes' |
153 | | - break |
154 | | - case '/programme-tv/': |
155 | | - presenceData.state = 'Programme TV' |
156 | | - break |
157 | | - case '/cinema/': |
158 | | - presenceData.state = 'Films' |
159 | | - break |
160 | | - case '/series/': |
161 | | - presenceData.state = 'Séries' |
162 | | - break |
163 | | - case '/jeunesse/': |
164 | | - presenceData.state = 'Jeunesse' |
165 | | - break |
166 | | - case '/live/': |
167 | | - presenceData.state = 'Chaînes en direct' |
168 | | - break |
| 170 | + const mainTitle = document.querySelector('.stickyTitle___HRELo') |
| 171 | + const currentPathName = document.location.pathname |
| 172 | + |
| 173 | + if (navigationRoutes[currentPathName]) { |
| 174 | + presenceData.state = navigationRoutes[currentPathName] |
169 | 175 | } |
170 | 176 |
|
171 | 177 | if (video && !Number.isNaN(video.duration)) { |
172 | | - const titleTvShows = document.querySelectorAll('.MGrm26svmXpUhj6dfbGN') |
173 | | - let channelID = new URLSearchParams(window.location.search).get('channel') |
174 | | - switch (true) { |
175 | | - case containsTerm('live'): |
176 | | - channelID = `${channelID?.charAt(0)} ${channelID?.substring(1)}` |
177 | | - presenceData.details = document.querySelector( |
178 | | - '.A6AH2oNkXUuOKJN5IYrL', |
179 | | - )?.textContent |
180 | | - presenceData.state = `sur ${ |
181 | | - document.querySelector<HTMLImageElement>( |
182 | | - `#\\3${channelID}_onclick > div > div.card__content_0dae1b.cardContent___DuNAN.ratio--169 > div[class*="cardLogoChannel"] > div > img`, |
183 | | - )?.alt |
184 | | - }`; |
185 | | - [presenceData.startTimestamp, presenceData.endTimestamp] = presence.getTimestamps(video.currentTime, video.duration) |
186 | | - presenceData.largeImageKey = showCover |
187 | | - ? document.querySelector<HTMLImageElement>( |
188 | | - `#\\3${channelID}_onclick > div > div.card__content_0dae1b.cardContent___DuNAN.ratio--169 > div[class*="cardLogoChannel"] > div > img`, |
189 | | - )?.src |
190 | | - : myCANALAssets.Logo |
191 | | - presenceData.smallImageKey = Assets.Live |
192 | | - presenceData.smallImageText = 'En direct' |
193 | | - delete presenceData.startTimestamp |
194 | | - delete presenceData.endTimestamp |
195 | | - presenceData.startTimestamp = browsingTimestamp |
196 | | - break |
197 | | - case containsTerm('cinema'): |
198 | | - presenceData.details = document.querySelector( |
199 | | - '.A6AH2oNkXUuOKJN5IYrL', |
200 | | - )?.textContent; |
201 | | - [presenceData.startTimestamp, presenceData.endTimestamp] = presence.getTimestamps(video.currentTime, video.duration) |
202 | | - presenceData.largeImageKey = showCover |
203 | | - ? (presenceData.largeImageKey = await getThumbnail( |
204 | | - document.querySelector<HTMLMetaElement>('[property=\'og:image\']') |
205 | | - ?.content, |
206 | | - )) |
207 | | - : myCANALAssets.Logo |
208 | | - presenceData.smallImageKey = video.paused ? Assets.Pause : Assets.Play |
209 | | - presenceData.smallImageText = video.paused |
210 | | - ? (await strings).pause |
211 | | - : (await strings).play |
212 | | - break |
213 | | - case containsTerm('series'): |
214 | | - case containsTerm('jeunesse'): |
215 | | - presenceData.details = titleTvShows[0]?.textContent?.trim() |
216 | | - presenceData.state = titleTvShows[1]?.textContent?.trim(); |
217 | | - [presenceData.startTimestamp, presenceData.endTimestamp] = presence.getTimestamps(video.currentTime, video.duration) |
218 | | - presenceData.largeImageKey = showCover |
219 | | - ? (presenceData.largeImageKey = await getThumbnail( |
220 | | - document.querySelector<HTMLMetaElement>('[property=\'og:image\']') |
221 | | - ?.content, |
222 | | - )) |
223 | | - : myCANALAssets.Logo |
224 | | - presenceData.smallImageKey = video.paused ? Assets.Pause : Assets.Play |
225 | | - presenceData.smallImageText = video.paused |
226 | | - ? (await strings).pause |
227 | | - : (await strings).play |
228 | | - break |
| 178 | + updateTitleForTvShowsCache() |
| 179 | + |
| 180 | + const showTitleAsActivity = await presence.getSetting<boolean>('useTitleAsName') |
| 181 | + |
| 182 | + if (containsTerm('live')) { |
| 183 | + await handleLiveContent(presenceData, showCover) |
229 | 184 | } |
| 185 | + else if (containsTerm('cinema')) { |
| 186 | + await handleCinemaContent(presenceData, video, showCover) |
| 187 | + } |
| 188 | + else if (containsTerm('series') || containsTerm('jeunesse')) { |
| 189 | + await handleSeriesContent(presenceData, video, showCover, showTitleAsActivity, mainTitle) |
| 190 | + } |
| 191 | + |
230 | 192 | if (video.paused) { |
231 | 193 | delete presenceData.startTimestamp |
232 | 194 | delete presenceData.endTimestamp |
233 | 195 | } |
| 196 | + |
| 197 | + if (showTitleAsActivity && mainTitle) { |
| 198 | + presenceData.name = mainTitle.textContent?.trim() |
| 199 | + } |
234 | 200 | } |
235 | 201 | else if (mainTitle) { |
236 | 202 | presenceData.details = 'Regarde...' |
237 | 203 | presenceData.state = mainTitle.textContent |
238 | 204 | } |
239 | 205 | else { |
240 | 206 | presenceData.details = 'Navigue...' |
| 207 | + resetCaches() |
241 | 208 | } |
242 | 209 |
|
243 | | - presence.setActivity(presenceData) |
| 210 | + await presence.setActivity(presenceData) |
244 | 211 | }) |
| 212 | + |
| 213 | +function resetCaches() { |
| 214 | + cachedTitleTvShows = [null, null] |
| 215 | + cachedEpisodeTitle = null |
| 216 | + cachedSynopsis = null |
| 217 | + cachedChannelName = null |
| 218 | +} |
| 219 | + |
| 220 | +function updateTitleForTvShowsCache() { |
| 221 | + const titleTvShows = document.querySelectorAll('.RbcMSl3qdUyV2kb3rAEg') |
| 222 | + if (titleTvShows.length >= 2) { |
| 223 | + cachedTitleTvShows = [ |
| 224 | + titleTvShows[0]?.textContent?.trim() || null, |
| 225 | + titleTvShows[1]?.textContent?.trim() || null, |
| 226 | + ] |
| 227 | + } |
| 228 | +} |
| 229 | + |
| 230 | +async function handleLiveContent(presenceData: MediaPresenceData | NonMediaPresenceData, showCover: boolean) { |
| 231 | + presenceData.details = document.querySelector('.A6AH2oNkXUuOKJN5IYrL')?.textContent |
| 232 | + |
| 233 | + if (showCover) { |
| 234 | + const channelImg = document.querySelector<HTMLImageElement>('.w4vxo5X8LLEAi6TxyFxu') |
| 235 | + if (channelImg) { |
| 236 | + if (channelImg.src !== lastImgSrc) { |
| 237 | + lastImgSrc = channelImg.src |
| 238 | + cachedThumbnailUrl = await getThumbnail(channelImg.src) |
| 239 | + } |
| 240 | + cachedChannelName = channelImg.alt.split('Logo de la chaîne ')[1] || 'une chaîne' |
| 241 | + } |
| 242 | + |
| 243 | + presenceData.largeImageKey = cachedThumbnailUrl || myCANALAssets.Logo |
| 244 | + } |
| 245 | + |
| 246 | + presenceData.state = `sur ${cachedChannelName || 'une chaîne'}` |
| 247 | + presenceData.startTimestamp = browsingTimestamp |
| 248 | + |
| 249 | + presenceData.smallImageKey = Assets.Live |
| 250 | + presenceData.smallImageText = 'En direct' |
| 251 | +} |
| 252 | + |
| 253 | +async function handleCinemaContent(presenceData: MediaPresenceData | NonMediaPresenceData, video: HTMLVideoElement, showCover: boolean) { |
| 254 | + presenceData.details = document.querySelector('.A6AH2oNkXUuOKJN5IYrL')?.textContent |
| 255 | + presenceData.state = document.head.querySelector('[name="description"]')?.getAttribute('content')?.trim(); |
| 256 | + |
| 257 | + [presenceData.startTimestamp, presenceData.endTimestamp] = getTimestamps(video.currentTime, video.duration) |
| 258 | + |
| 259 | + if (showCover) { |
| 260 | + presenceData.largeImageKey = await getThumbnail( |
| 261 | + document.querySelector<HTMLMetaElement>('[property=\'og:image\']')?.content, |
| 262 | + ) |
| 263 | + } |
| 264 | + |
| 265 | + presenceData.smallImageKey = video.paused ? Assets.Pause : Assets.Play |
| 266 | + presenceData.smallImageText = video.paused ? (await strings).pause : (await strings).play |
| 267 | +} |
| 268 | + |
| 269 | +async function handleSeriesContent(presenceData: PresenceData, video: HTMLVideoElement, showCover: boolean, showTitleAsActivity: boolean, mainTitle: Element | null) { |
| 270 | + const episodeTitle = cachedTitleTvShows[1]?.substring(cachedTitleTvShows[1]?.indexOf(':') + 1)?.trim() |
| 271 | + |
| 272 | + if (showTitleAsActivity && mainTitle) { |
| 273 | + presenceData.details = episodeTitle |
| 274 | + if (episodeTitle && episodeTitle !== cachedEpisodeTitle) { |
| 275 | + cachedEpisodeTitle = episodeTitle |
| 276 | + cachedSynopsis = null |
| 277 | + for (const el of document.querySelectorAll('[class*="episode-editorial__editorial-title"]')) { |
| 278 | + if (el.textContent === episodeTitle) { |
| 279 | + cachedSynopsis = el.nextSibling?.textContent?.trim() || null |
| 280 | + break |
| 281 | + } |
| 282 | + } |
| 283 | + } |
| 284 | + if (cachedSynopsis) { |
| 285 | + presenceData.state = cachedSynopsis |
| 286 | + } |
| 287 | + } |
| 288 | + else { |
| 289 | + presenceData.details = mainTitle?.textContent?.trim() |
| 290 | + presenceData.state = episodeTitle |
| 291 | + } |
| 292 | + |
| 293 | + [presenceData.startTimestamp, presenceData.endTimestamp] = getTimestamps(video.currentTime, video.duration) |
| 294 | + |
| 295 | + if (showCover) { |
| 296 | + presenceData.largeImageKey = await getThumbnail( |
| 297 | + document.querySelector<HTMLMetaElement>('[property=\'og:image\']')?.content, |
| 298 | + ) |
| 299 | + } |
| 300 | + |
| 301 | + const showSeason = `${cachedTitleTvShows[0]?.split('-').at(-1)?.trim()}` |
| 302 | + const showEpisode = `${cachedTitleTvShows[1]?.split(':')[0]?.trim()}` |
| 303 | + presenceData.largeImageText = `${showSeason}, ${showEpisode}` |
| 304 | + |
| 305 | + presenceData.smallImageKey = video.paused ? Assets.Pause : Assets.Play |
| 306 | + presenceData.smallImageText = video.paused ? (await strings).pause : (await strings).play |
| 307 | +} |
0 commit comments