Skip to content

Commit b1eb9b9

Browse files
authored
feat(MovieBoxPro): add activity (#10382)
* feat(MovieBoxPro): add activity * hotfix * fix(movieboxpro) Signed-off-by: sirschubert <100043392+sirschubert@users.noreply.github.com> --------- Signed-off-by: sirschubert <100043392+sirschubert@users.noreply.github.com>
1 parent b4ee2fb commit b1eb9b9

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"$schema": "https://schemas.premid.app/metadata/1.16",
3+
"apiVersion": 1,
4+
"author": {
5+
"id": "339316517558681610",
6+
"name": "firstoften"
7+
},
8+
"service": "MovieBoxPro",
9+
"description": {
10+
"en": "MovieBoxPro is for watching movies and TV shows, offering details like posters, cast info, trailers, and trending titles, sourced from The Movie Database"
11+
},
12+
"url": "movieboxpro.app",
13+
"regExp": "^https?[:][/][/]([a-z0-9-]+[.])*movieboxpro[.]app[/]",
14+
"version": "1.0.0",
15+
"logo": "https://cdn.aptoide.com/imgs/b/c/8/bc87071060372ad5bbd0ee5470c05dda_icon.jpg",
16+
"thumbnail": "https://raw.githubusercontent.com/sirschubert/assets/refs/heads/main/assets/movieboxpro.png",
17+
"color": "#fcba03",
18+
"category": "videos",
19+
"tags": [
20+
"movies",
21+
"series",
22+
"watch"
23+
]
24+
}

websites/M/MovieBoxPro/presence.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { ActivityType, Assets, getTimestamps, timestampFromFormat } from 'premid'
2+
3+
declare const Presence: any
4+
5+
const presence = new Presence({ clientId: '1453728381903306814' })
6+
7+
function extractSeasonEpisode(text: string | null | undefined): string | null {
8+
if (!text)
9+
return null
10+
const match = text.match(/S(\d+)\s*E(\d+)/i)
11+
return (match && match[1] && match[2]) ? `Season ${Number.parseInt(match[1])}, Episode ${Number.parseInt(match[2])}` : null
12+
}
13+
14+
presence.on('UpdateData', async () => {
15+
const video = document.querySelector('video')
16+
const rawTitle = document.querySelector('span.name')?.textContent ?? null
17+
18+
const presenceData: any = {
19+
type: ActivityType.Watching,
20+
largeImageKey: 'https://cdn.aptoide.com/imgs/b/c/8/bc87071060372ad5bbd0ee5470c05dda_icon.jpg',
21+
details: 'Browsing Library',
22+
state: 'Choosing a movie...',
23+
}
24+
25+
if (video && rawTitle) {
26+
presenceData.details = rawTitle
27+
28+
const coverImg = document.querySelector<HTMLImageElement>('img.cover')
29+
if (coverImg)
30+
presenceData.largeImageKey = coverImg.src
31+
32+
const params = new URLSearchParams(document.location.search)
33+
let episodeInfo = (params.get('season') && params.get('episode'))
34+
? `Season ${params.get('season')}, Episode ${params.get('episode')}`
35+
: null
36+
37+
if (!episodeInfo) {
38+
const jwTitle = document.querySelector('.jw-title-primary')?.textContent ?? document.querySelector('.jw-title-secondary')?.textContent
39+
episodeInfo = extractSeasonEpisode(jwTitle)
40+
}
41+
42+
if (!episodeInfo) {
43+
const videoContainer = document.querySelector('.video-js')
44+
if (videoContainer)
45+
episodeInfo = extractSeasonEpisode(videoContainer.textContent)
46+
}
47+
48+
if (!episodeInfo) {
49+
const metaDesc = document.querySelector('meta[name="description"]')?.getAttribute('content')
50+
episodeInfo = extractSeasonEpisode(metaDesc) || extractSeasonEpisode(document.title)
51+
}
52+
53+
presenceData.state = episodeInfo || (document.location.href.match(/tvshow|season/) ? 'Watching TV Show' : 'Watching Movie')
54+
55+
if (video.paused) {
56+
presenceData.smallImageKey = Assets.Pause
57+
presenceData.smallImageText = 'Paused'
58+
presenceData.state += ' (Paused)'
59+
delete presenceData.startTimestamp
60+
delete presenceData.endTimestamp
61+
}
62+
else {
63+
presenceData.smallImageKey = Assets.Play
64+
presenceData.smallImageText = 'Playing'
65+
66+
let rawCurrent = document.querySelector('.vjs-current-time-display')?.textContent ?? ''
67+
let rawDuration = document.querySelector('.vjs-duration-display')?.textContent ?? ''
68+
const rawRemaining = document.querySelector('.vjs-remaining-time-display')?.textContent ?? ''
69+
70+
if (!rawCurrent.trim()) {
71+
rawCurrent = document.querySelector('.jw-text-elapsed')?.textContent ?? ''
72+
rawDuration = document.querySelector('.jw-text-duration')?.textContent ?? ''
73+
}
74+
75+
const currentSeconds = timestampFromFormat(rawCurrent.replace(/[^\d:]/g, ''))
76+
const durationSeconds = timestampFromFormat(rawDuration.replace(/[^\d:]/g, ''))
77+
const remainingSeconds = timestampFromFormat(rawRemaining.replace(/[^\d:]/g, ''))
78+
79+
if (durationSeconds > 0) {
80+
[presenceData.startTimestamp, presenceData.endTimestamp] = getTimestamps(currentSeconds, durationSeconds)
81+
}
82+
else if (remainingSeconds > 0) {
83+
presenceData.startTimestamp = Date.now() - (currentSeconds * 1000)
84+
presenceData.endTimestamp = Date.now() + (remainingSeconds * 1000)
85+
}
86+
else {
87+
presenceData.startTimestamp = Date.now() - (currentSeconds * 1000)
88+
delete presenceData.endTimestamp
89+
}
90+
}
91+
}
92+
93+
presence.setActivity(presenceData)
94+
})

0 commit comments

Comments
 (0)