Skip to content

Commit 5900712

Browse files
authored
feat(Voxani): add Activity (#10362)
* Feat(Vix): Add Activity Signed-off-by: xDoritos <agusssd0@gmail.com> * Add files via upload Signed-off-by: xDoritos <agusssd0@gmail.com> * Delete websites/V/Vix/presence.ts Signed-off-by: xDoritos <agusssd0@gmail.com> * Delete websites/V/Vix/metadata.json Signed-off-by: xDoritos <agusssd0@gmail.com> --------- Signed-off-by: xDoritos <agusssd0@gmail.com>
1 parent 98b4741 commit 5900712

File tree

3 files changed

+185
-0
lines changed

3 files changed

+185
-0
lines changed

websites/V/Voxani/iframe.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const iframe = new iFrame()
2+
3+
iframe.on('UpdateData', () => {
4+
const video = document.querySelector<HTMLVideoElement>('video')
5+
if (!video || Number.isNaN(video.duration))
6+
return
7+
iframe.send({
8+
iFrameVideoData: {
9+
currTime: video.currentTime,
10+
dur: video.duration,
11+
paused: video.paused || video.ended,
12+
},
13+
})
14+
})

websites/V/Voxani/metadata.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"$schema": "https://schemas.premid.app/metadata/1.16",
3+
"apiVersion": 1,
4+
"author": {
5+
"id": "432215088686956565",
6+
"name": "_xdoritos"
7+
},
8+
"service": "Voxani",
9+
"description": {
10+
"en": "Voxani is a streaming platform for anime and other video content."
11+
},
12+
"url": "voxani.live",
13+
"regExp": "^https?[:][/][/]([a-z0-9-]+[.])*voxani[.]live[/]",
14+
"version": "1.0.0",
15+
"logo": "https://imgur.com/nkyTI9D.png",
16+
"thumbnail": "https://imgur.com/XoUqqZH.png",
17+
"color": "#000000",
18+
"category": "anime",
19+
"tags": [
20+
"anime",
21+
"video",
22+
"streaming"
23+
],
24+
"iframe": true,
25+
"iFrameRegExp": "(^|\\.)?(megaplay\\.buzz|rapid-cloud\\.co|vidwish\\.live)"
26+
}

websites/V/Voxani/presence.ts

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import { ActivityType, Assets, getTimestamps } from 'premid'
2+
3+
const presence = new Presence({
4+
clientId: '1459797444278620384',
5+
})
6+
const browsingTimestamp = Math.floor(Date.now() / 1000)
7+
8+
let iframePlayback = false
9+
let currTime = 0
10+
let durTime = 0
11+
let isPaused = true
12+
13+
enum ActivityAssets {
14+
Logo = 'https://imgur.com/nkyTI9D.png',
15+
Gif = 'https://i.imgur.com/0X67ZB7.gif',
16+
}
17+
18+
let cache: {
19+
text: string
20+
nombreAnime: string
21+
episodioAnime: string
22+
seasonAnime: string
23+
bannerImg: string | null | undefined
24+
} = {
25+
text: '',
26+
nombreAnime: '',
27+
episodioAnime: '',
28+
seasonAnime: '',
29+
bannerImg: '',
30+
}
31+
32+
async function getAnimeData(text: string) {
33+
if (text === cache.text && cache.nombreAnime !== '' && cache.bannerImg !== ActivityAssets.Logo) {
34+
return {
35+
nombreAnime: cache.nombreAnime,
36+
episodioAnime: cache.episodioAnime,
37+
seasonAnime: cache.seasonAnime,
38+
bannerImg: cache.bannerImg,
39+
}
40+
}
41+
42+
const nombreAnime = document.querySelector('h1')?.textContent?.trim() || ''
43+
const episodioAnime = document.querySelector('p')?.textContent?.trim() || ''
44+
const seasonAnime = 'Season 1'
45+
const bannerImg = ActivityAssets.Logo
46+
47+
cache = {
48+
text,
49+
nombreAnime,
50+
episodioAnime,
51+
seasonAnime,
52+
bannerImg,
53+
}
54+
55+
return {
56+
nombreAnime,
57+
episodioAnime,
58+
seasonAnime,
59+
bannerImg,
60+
}
61+
}
62+
63+
presence.on('iFrameData', (data: any) => {
64+
if (data.iFrameVideoData) {
65+
iframePlayback = true
66+
currTime = data.iFrameVideoData.currTime
67+
durTime = data.iFrameVideoData.dur
68+
isPaused = data.iFrameVideoData.paused
69+
}
70+
})
71+
72+
presence.on('UpdateData', async () => {
73+
const { pathname } = document.location
74+
75+
const presenceData: PresenceData = {
76+
name: 'Voxani',
77+
details: 'Browsing Voxani',
78+
state: 'Browsing anime content',
79+
largeImageKey: ActivityAssets.Logo,
80+
startTimestamp: browsingTimestamp,
81+
smallImageKey: Assets.Reading,
82+
type: ActivityType.Watching,
83+
}
84+
85+
if (pathname.includes('/watch/')) {
86+
const animeData = await getAnimeData(pathname)
87+
if (animeData) {
88+
presenceData.name = animeData.nombreAnime || 'Voxani'
89+
presenceData.details = animeData.nombreAnime || ''
90+
presenceData.state = 'Watching on Voxani'
91+
presenceData.largeImageKey = animeData.bannerImg
92+
presenceData.largeImageText = `${animeData.seasonAnime}, ${animeData.episodioAnime}`
93+
94+
if (iframePlayback) {
95+
presenceData.smallImageKey = isPaused ? Assets.Pause : Assets.Play
96+
presenceData.smallImageText = isPaused ? 'Pausado' : 'Reproduciendo'
97+
}
98+
99+
if (!isPaused) {
100+
const [startTs, endTs] = getTimestamps(
101+
Math.floor(currTime),
102+
Math.floor(durTime),
103+
)
104+
presenceData.startTimestamp = startTs
105+
presenceData.endTimestamp = endTs
106+
}
107+
else {
108+
delete presenceData.startTimestamp
109+
delete presenceData.endTimestamp
110+
}
111+
}
112+
}
113+
else if (pathname.includes('/anime')) {
114+
const animeName = document.querySelector('h1')?.textContent?.trim() || 'Voxani'
115+
presenceData.details = 'Browsing Anime'
116+
presenceData.state = `Looking: ${animeName}`
117+
presenceData.smallImageText = 'Browsing Anime'
118+
}
119+
else if (pathname.includes('/home')) {
120+
presenceData.details = 'Browsing Home'
121+
presenceData.state = 'Viewing the home page'
122+
presenceData.smallImageText = 'Browsing Home'
123+
}
124+
else if (pathname.includes('/discover')) {
125+
presenceData.details = 'Browsing Discover'
126+
presenceData.state = 'Exploring new anime'
127+
presenceData.smallImageText = 'Browsing Discover'
128+
}
129+
else if (pathname.includes('/browse')) {
130+
presenceData.details = 'Browsing Anime'
131+
presenceData.state = 'Looking through anime titles'
132+
presenceData.smallImageText = 'Browsing Anime'
133+
}
134+
else if (pathname.includes('/schedule')) {
135+
presenceData.details = 'Viewing Schedule'
136+
presenceData.state = 'Checking upcoming releases'
137+
presenceData.smallImageText = 'Viewing Schedule'
138+
}
139+
else if (pathname.includes('/my-list')) {
140+
presenceData.details = 'Viewing My List'
141+
presenceData.state = 'Managing personal anime list'
142+
presenceData.smallImageText = 'Viewing My List'
143+
}
144+
presence.setActivity(presenceData)
145+
})

0 commit comments

Comments
 (0)