Skip to content

Commit 0de50ff

Browse files
feat(FlickyStream): add Activity (#10409)
1 parent 48a6057 commit 0de50ff

File tree

2 files changed

+169
-0
lines changed

2 files changed

+169
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"$schema": "https://schemas.premid.app/metadata/1.16",
3+
"apiVersion": 1,
4+
"author": {
5+
"id": "1428056065840255027",
6+
"name": "ahmanitsucks"
7+
},
8+
"service": "FlickyStream",
9+
"description": {
10+
"en": "A streaming platform for movies, TV shows, and anime."
11+
},
12+
"url": "flickystream.ru",
13+
"regExp": "^https?[:][/][/](www[.])?flickystream[.]ru[/]",
14+
"version": "1.0.0",
15+
"logo": "https://i.imgur.com/M4LL1F8.png",
16+
"thumbnail": "https://i.imgur.com/87Bezq3.png",
17+
"color": "#E53935",
18+
"category": "videos",
19+
"tags": [
20+
"movies",
21+
"anime",
22+
"tv"
23+
],
24+
"settings": [
25+
{
26+
"id": "privacy",
27+
"title": "Privacy Mode",
28+
"icon": "fas fa-user-secret",
29+
"value": false
30+
}
31+
]
32+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import { ActivityType, Assets } from 'premid'
2+
3+
const presence = new Presence({
4+
clientId: '1453062828033577203',
5+
})
6+
7+
const browsingTimestamp = Math.floor(Date.now() / 1000)
8+
9+
enum ActivityAssets {
10+
Logo = 'https://i.imgur.com/M4LL1F8.png',
11+
}
12+
13+
presence.on('UpdateData', async () => {
14+
let presenceData: PresenceData = {
15+
largeImageKey: ActivityAssets.Logo,
16+
startTimestamp: browsingTimestamp,
17+
details: 'Unsupported Page',
18+
}
19+
20+
const { pathname, search } = document.location
21+
22+
const privacy = await presence.getSetting<boolean>('privacy')
23+
24+
if (privacy) {
25+
presenceData.details = 'Watching FlickyStream'
26+
presence.setActivity(presenceData)
27+
return
28+
}
29+
30+
const pages: Record<string, PresenceData> = {
31+
'/': {
32+
details: 'Viewing HomePage',
33+
smallImageKey: Assets.Viewing,
34+
},
35+
'/tv': {
36+
details: 'Browsing TV Shows',
37+
smallImageKey: Assets.Viewing,
38+
},
39+
'/movie': {
40+
details: 'Browsing Movies',
41+
smallImageKey: Assets.Viewing,
42+
},
43+
'/sports': {
44+
details: 'Watching Live Sports',
45+
smallImageKey: Assets.Viewing,
46+
},
47+
'/watch-history': {
48+
details: 'Browsing Watch History',
49+
smallImageKey: Assets.Viewing,
50+
},
51+
'/trending': {
52+
details: 'Browsing Trending Content',
53+
smallImageKey: Assets.Viewing,
54+
},
55+
'/profile': {
56+
details: 'Browsing Profile',
57+
smallImageKey: Assets.Viewing,
58+
},
59+
'/login': {
60+
details: 'Signing In',
61+
smallImageKey: Assets.Viewing,
62+
},
63+
'/signup': {
64+
details: 'Signing Up',
65+
smallImageKey: Assets.Viewing,
66+
},
67+
}
68+
69+
for (const [path, data] of Object.entries(pages)) {
70+
if (pathname === path) {
71+
presenceData = {
72+
...presenceData,
73+
...data,
74+
type: ActivityType.Watching,
75+
}
76+
}
77+
}
78+
79+
if (pathname.startsWith('/movie/') || pathname.startsWith('/tv/')) {
80+
const title = document.querySelector('img[alt][src*="tmdb.org"]')?.getAttribute('alt') || document.title.replace(' | FlickyStream', '') || 'Viewing Movie'
81+
const image = document.querySelector('div.hidden.md\\:block img')?.getAttribute('src') || document.querySelector('img[src*="tmdb.org"]')?.getAttribute('src')
82+
const rating = (() => {
83+
const el = document.querySelector('div.text-amber-400')
84+
return el?.childNodes[el.childNodes.length - 1]?.textContent?.trim()
85+
})()
86+
presenceData.details = 'FlickyStream'
87+
presenceData.state = [
88+
title,
89+
rating && `⭐ ${rating}`,
90+
]
91+
.filter(Boolean)
92+
.join(' • ')
93+
if (image) {
94+
presenceData.type = ActivityType.Watching
95+
presenceData.name = title
96+
presenceData.largeImageKey = image
97+
presenceData.largeImageText = title
98+
presenceData.smallImageKey = ActivityAssets.Logo
99+
}
100+
}
101+
102+
if (pathname.startsWith('/player/movie/')) {
103+
const title = document.querySelector('h1.text-xl.md\\:text-2xl.font-semibold')?.textContent?.trim() || document.title.replace(' | FlickyStream', '') || 'Viewing Movie'
104+
presenceData.details = 'FlickyStream'
105+
if (title) {
106+
presenceData.type = ActivityType.Watching
107+
presenceData.name = title
108+
presenceData.largeImageKey = ActivityAssets.Logo
109+
presenceData.largeImageText = title
110+
}
111+
}
112+
113+
if (pathname.startsWith('/player/tv/')) {
114+
const title = document.querySelector('h1.text-xl.md\\:text-2xl.font-semibold')?.textContent?.trim() || document.title.replace(' | FlickyStream', '') || 'Viewing Movie'
115+
const rawTitle = document.querySelector('h1.text-xl.md\\:text-2xl.font-semibold')?.textContent?.trim() || ''
116+
const [showPart, episodePart] = rawTitle.split(' - ')
117+
const showTitle = showPart || 'Unknown Show'
118+
const [, seasonNo, episodeNo] = episodePart?.match(/Season\s+(\d+)\s+Episode\s+(\d+)/) || []
119+
presenceData.details = 'FlickyStream'
120+
if (title) {
121+
presenceData.type = ActivityType.Watching
122+
presenceData.name = `${showTitle} S${seasonNo}E${episodeNo}`
123+
presenceData.largeImageKey = ActivityAssets.Logo
124+
presenceData.largeImageText = showTitle
125+
}
126+
}
127+
if (pathname.includes('/search')) {
128+
presenceData.type = ActivityType.Watching
129+
presenceData.details = `Searching...`
130+
presenceData.state = `Query: ${decodeURIComponent(new URLSearchParams(search).get('q') || '').replace(/\b\w/g, c => c.toUpperCase())}`
131+
presenceData.smallImageKey = Assets.Search
132+
}
133+
134+
if (presenceData.details)
135+
presence.setActivity(presenceData)
136+
else presence.clearActivity()
137+
})

0 commit comments

Comments
 (0)