Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions websites/C/Cinejoy/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$schema": "https://schemas.premid.app/metadata/1.17",
"apiVersion": 1,
"author": {
"id": "1233363061440512011",
"name": "lxzy"
},
"service": "Cinejoy",
"description": {
"en": "Watch free movies and TV shows on Cinejoy."
},
"url": "cinejoy.to",
"regExp": "^https?[:][/][/]([a-z0-9-]+[.])*cinejoy[.]to[/]",
"version": "1.0.0",
"logo": "https://i.imgur.com/3wpcyto.png",
"thumbnail": "https://i.imgur.com/S4XjEAo.jpeg",
"color": "#95FF50",
"category": "videos",
"tags": [
"movie",
"tv",
"series",
"streaming"
]
}
95 changes: 95 additions & 0 deletions websites/C/Cinejoy/presence.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { Assets, getTimestampsFromMedia } from 'premid'

const presence = new Presence({
clientId: '1534742028368347156',
})

const TMDB_KEY = '8476a7ab80ad76f0936744df0430e67c'
const TMDB_IMG = 'https://image.tmdb.org/t/p/w500'

enum ActivityAssets {
Logo = 'https://cinejoy.to/favicon.ico',
}

function parsePath() {
const path = document.location.pathname
const parts = path.split('/').filter(Boolean)

const type = parts.find(p => p === 'tv' || p === 'movie')
if (!type)
return null

const typeIndex = parts.indexOf(type)
const idPart = parts[typeIndex + 1]
const idMatch = idPart?.match(/^\d+/)
const tmdbId = idMatch?.[0]
if (!tmdbId)
return null

const seasonPart = parts[typeIndex + 2]
const episodePart = parts[typeIndex + 3]
const season = seasonPart?.match(/\d+/)?.[0]
const episode = episodePart?.match(/\d+/)?.[0]

return { type, tmdbId, season, episode }
}

let cache: { key: string, details: any } | null = null

async function getTmdbDetails(type: string, tmdbId: string) {
const key = `${type}-${tmdbId}`
if (cache?.key === key)
return cache.details

const res = await fetch(
`https://api.themoviedb.org/3/${type}/${tmdbId}?api_key=${TMDB_KEY}&language=en-US`,
)
const data = await res.json()
cache = { key, details: data }
return data
}

presence.on('UpdateData', async () => {
const presenceData: PresenceData = {
largeImageKey: ActivityAssets.Logo,
details: 'Browsing Cinejoy',
}

const parsed = parsePath()
const video = document.querySelector('video')

if (parsed) {
try {
const data = await getTmdbDetails(parsed.type, parsed.tmdbId)
const title = data.title ?? data.name ?? 'Unknown'
const posterPath = data.poster_path

presenceData.details = title

if (parsed.type === 'tv' && parsed.season && parsed.episode) {
presenceData.state = `S${parsed.season}:E${parsed.episode}`
}
else if (parsed.type === 'movie' && data.release_date) {
presenceData.state = data.release_date.split('-')[0]
}

if (posterPath) {
presenceData.largeImageKey = `${TMDB_IMG}${posterPath}`
}
}
catch {
presenceData.details = 'Watching Cinejoy'
}
}

if (video && video.readyState > 0) {
presenceData.smallImageKey = video.paused ? Assets.Pause : Assets.Play
presenceData.smallImageText = video.paused ? 'Paused' : 'Playing'

if (!video.paused && Number.isFinite(video.duration)) {
[presenceData.startTimestamp, presenceData.endTimestamp] = getTimestampsFromMedia(video)
}
}

presence.setActivity(presenceData)
})
Loading