Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
44 changes: 44 additions & 0 deletions websites/P/Primeshows/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"$schema": "https://schemas.premid.app/metadata/1.16",
"apiVersion": 1,
"author": {
"id": "1203605618745933880",
"name": "friday.su"
},
"service": "Primeshows",
"description": {
"en": "Enjoy unlimited streaming of movies, TV shows, and anime in HD & 4K, completely free! Primeshows offers a seamless experience with multi-language support and auto-next playback, ensuring you never miss a moment. Watch your favorite content anytime, anywhere!"
},
"url": "www.primeshows.live",
"regExp": "^https?[:][/][/]([a-z0-9-]+[.])*primeshows[.]live[/]",
"version": "1.0.0",
"logo": "https://i.ibb.co/fdn3gFWS/logo.png",
"thumbnail": "https://i.ibb.co/7NtK5cn6/image.png",
"color": "#121212",
"category": "videos",
"tags": [
"video",
"streaming",
"movies",
"anime",
"tv"
],
"settings": [
{
"id": "lang",
"multiLanguage": true
},
{
"id": "privacy",
"title": "Privacy Mode",
"icon": "fas fa-user-secret",
"value": false
},
{
"id": "showButtons",
"title": "Show Buttons",
"icon": "fas fa-compress-arrows-alt",
"value": true
}
]
}
297 changes: 297 additions & 0 deletions websites/P/Primeshows/presence.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,297 @@
import { ActivityType, Assets } from 'premid'

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

const browsingTimestamp = Math.floor(Date.now() / 1000)

enum ActivityAssets {
Logo = 'https://i.ibb.co/fdn3gFWS/logo.png',
}

/**
* Formats a slug into a readable name.
* e.g., "66732-stranger-things" -> "Stranger Things"
*/
const formatSlug = (slug: string | undefined): string => {

Check failure

Code scanning / ESLint

Enforce top-level functions to be declared with function keyword Error

Top-level functions should be declared with function keyword
if (!slug) return ''

Check failure

Code scanning / ESLint

Newline after if Error

Expect newline after if
return slug
.split('-')
.map(word => {

Check failure

Code scanning / ESLint

Require parentheses around arrow function arguments Error

Expected parentheses around arrow function argument having a body with curly braces.
if (/^\d+$/.test(word)) return '' // Skip IDs

Check failure

Code scanning / ESLint

Newline after if Error

Expect newline after if
return word.charAt(0).toUpperCase() + word.slice(1)
})
.filter(Boolean)
.join(' ')
}

/**
* Attempts to retrieve a name/title from the DOM if the URL slug is insufficient.
*/
const getNameFromDOM = (): string | null => {

Check failure

Code scanning / ESLint

Enforce top-level functions to be declared with function keyword Error

Top-level functions should be declared with function keyword
const selectors = [
'h1.text-white',
'.movie-title',
'.show-title',
'h1',
'header h1',
'#Movie\\ Name',
'#TV\\ Shows\\ Name'
]

Check failure

Code scanning / ESLint

Require or disallow trailing commas Error

Missing trailing comma.
for (const selector of selectors) {
const el = document.querySelector(selector)
if (el && el.textContent) return el.textContent.trim()

Check failure

Code scanning / ESLint

Newline after if Error

Expect newline after if
}
return null
}

/**
* Robustly fetches the rating from the page.
*/
const getRating = (): string => {

Check failure

Code scanning / ESLint

Enforce top-level functions to be declared with function keyword Error

Top-level functions should be declared with function keyword
const ratingEl = document.querySelector('.radial-progress span.text-white') ||

Check failure

Code scanning / ESLint

Enforce consistent linebreak style for operators Error

'||' should be placed at the beginning of the line.

Check failure

Code scanning / ESLint

Disallow trailing whitespace at the end of lines Error

Trailing spaces not allowed.
document.querySelector('[class*="radial-progress"] span') ||

Check failure

Code scanning / ESLint

Indentation for binary operators Error

Expected indentation of 4 spaces

Check failure

Code scanning / ESLint

Enforce consistent linebreak style for operators Error

'||' should be placed at the beginning of the line.
document.querySelector('.rating-value')
const rating = ratingEl?.textContent?.trim() || 'N/A'
return rating === '0' || rating === '0.0' ? 'N/A' : rating
}

/**
* Robustly fetches the release date from the page.
*/
const getReleaseDate = (type: 'movie' | 'tv'): string => {

Check failure

Code scanning / ESLint

Enforce top-level functions to be declared with function keyword Error

Top-level functions should be declared with function keyword
const selector = type === 'movie' ? '#Movie\\ Release\\ Date time p' : '#TV\\ Shows\\ Air\\ Date time'
let date = document.querySelector(selector)?.textContent?.trim() ||

Check failure

Code scanning / ESLint

Enforce consistent linebreak style for operators Error

'||' should be placed at the beginning of the line.

Check failure

Code scanning / ESLint

Disallow trailing whitespace at the end of lines Error

Trailing spaces not allowed.
document.querySelector('time')?.textContent?.trim() ||

Check failure

Code scanning / ESLint

Indentation for binary operators Error

Expected indentation of 4 spaces

Check failure

Code scanning / ESLint

Enforce consistent linebreak style for operators Error

'||' should be placed at the beginning of the line.

Check failure

Code scanning / ESLint

Disallow trailing whitespace at the end of lines Error

Trailing spaces not allowed.
'N/A'

Check failure

Code scanning / ESLint

Disallow trailing whitespace at the end of lines Error

Trailing spaces not allowed.
// Format long dates like "Sunday, October 12, 2014" to "October 2014"
if (date !== 'N/A') {
const dateParts = date.split(', ')
const p0 = dateParts[0]
const p1 = dateParts[1]
const p2 = dateParts[2]

if (dateParts.length === 3 && p1 && p2) {
date = `${p1} ${p2}`
} else if (dateParts.length === 2 && type === 'tv' && p0 && p1) {

Check failure

Code scanning / ESLint

Enforce consistent brace style for blocks Error

Closing curly brace appears on the same line as the subsequent block.
const monthYear = p0.split(' ')[0]
if (monthYear) {
date = `${monthYear} ${p1}`
}
}
}
return date
}

presence.on('UpdateData', async () => {
let presenceData: PresenceData = {
largeImageKey: ActivityAssets.Logo,
startTimestamp: browsingTimestamp,
details: 'Unsupported Page',
}

const { pathname, search, href } = document.location
const urlParams = new URLSearchParams(search)

const privacy = await presence.getSetting<boolean>('privacy')
const showButtons = await presence.getSetting<boolean>('showButtons')

if (privacy) {
presenceData.details = 'Watching Primeshows 🔒'
presence.setActivity(presenceData)
return
}

// Static Pages
const pages: Record<string, PresenceData> = {
'/': {
details: 'Viewing HomePage 🏠',
smallImageKey: Assets.Viewing,
},
'/profile': {
details: 'Viewing Profile 👤',
smallImageKey: Assets.Viewing,
},
'/tv': {
details: 'Browsing TV Shows 📺',
smallImageKey: Assets.Viewing,
},
'/movies': {
details: 'Browsing Movies 🎬',
smallImageKey: Assets.Viewing,
},
'/trending': {
details: 'Browsing Trending 🔥',
smallImageKey: Assets.Viewing,
},
'/search': {
details: 'Browsing Search 🔎',
smallImageKey: Assets.Viewing,
},
'/livetv': {
details: 'Browsing Live TV 📶',
smallImageKey: Assets.Viewing,
},
'/sports': {
details: 'Live Sports ⚽',
smallImageKey: Assets.Viewing,
},
}

if (pages[pathname]) {
presenceData = {
...presenceData,
...pages[pathname],
type: ActivityType.Watching,
}
}

// Handle Dynamic Routes

Check failure

Code scanning / ESLint

Disallow trailing whitespace at the end of lines Error

Trailing spaces not allowed.
// 1. TV Info Page: /tv/{id}-{slug}
if (pathname.startsWith('/tv/') && pathname !== '/tv') {
const match = pathname.match(/\/tv\/(\d+)(?:-([^/]+))?/)

Check failure

Code scanning / ESLint

disallow unused capturing group Error

Capturing group number 1 is defined but never used.
if (match) {
const showName = formatSlug(match[2]) || getNameFromDOM() || 'Unknown Show'
presenceData.details = `Viewing ${showName} 📺`
presenceData.type = ActivityType.Watching
presenceData.smallImageKey = Assets.Viewing

Check failure

Code scanning / ESLint

Disallow trailing whitespace at the end of lines Error

Trailing spaces not allowed.
const rating = getRating()
const releaseDate = getReleaseDate('tv')

Check failure

Code scanning / ESLint

Disallow trailing whitespace at the end of lines Error

Trailing spaces not allowed.
const stateParts = []
if (rating !== 'N/A') stateParts.push(`⭐ ${rating}`)

Check failure

Code scanning / ESLint

Newline after if Error

Expect newline after if
if (releaseDate !== 'N/A') stateParts.push(`🗓️ ${releaseDate}`)

Check failure

Code scanning / ESLint

Newline after if Error

Expect newline after if
presenceData.state = stateParts.length > 0 ? stateParts.join(' • ') : 'Viewing Details'
presenceData.largeImageKey = document.querySelector<HTMLImageElement>('section.md\\:col-\\[1\\/4\\] img')?.src ||

Check failure

Code scanning / ESLint

Enforce consistent linebreak style for operators Error

'||' should be placed at the beginning of the line.

Check failure

Code scanning / ESLint

Disallow trailing whitespace at the end of lines Error

Trailing spaces not allowed.
document.querySelector<HTMLImageElement>('img[alt*="Poster"]')?.src ||

Check failure

Code scanning / ESLint

Indentation for binary operators Error

Expected indentation of 8 spaces

Check failure

Code scanning / ESLint

Enforce consistent linebreak style for operators Error

'||' should be placed at the beginning of the line.
ActivityAssets.Logo

if (showButtons) {
presenceData.buttons = [
{ label: 'View Show 📺', url: href }
]

Check failure

Code scanning / ESLint

Require or disallow trailing commas Error

Missing trailing comma.
}
}
}

// 2. Movie Info Page: /movies/{id}-{slug}
if (pathname.startsWith('/movies/') && pathname !== '/movies') {
const match = pathname.match(/\/movies\/(\d+)(?:-([^/]+))?/)

Check failure

Code scanning / ESLint

disallow unused capturing group Error

Capturing group number 1 is defined but never used.
if (match) {
const movieName = formatSlug(match[2]) || getNameFromDOM() || 'Unknown Movie'
presenceData.details = `Viewing ${movieName} 🎬`
presenceData.type = ActivityType.Watching
presenceData.smallImageKey = Assets.Viewing

const rating = getRating()
const runtime = document.querySelector('#Movie\\ Runtime time p')?.textContent?.match(/\d+/)?.[0] || 'N/A'
const releaseDate = getReleaseDate('movie')

const stateParts = []
if (rating !== 'N/A') stateParts.push(`⭐ ${rating}`)

Check failure

Code scanning / ESLint

Newline after if Error

Expect newline after if
if (runtime !== 'N/A') stateParts.push(`🕒 ${runtime}m`)

Check failure

Code scanning / ESLint

Newline after if Error

Expect newline after if
if (releaseDate !== 'N/A') stateParts.push(`🗓️ ${releaseDate}`)

Check failure

Code scanning / ESLint

Newline after if Error

Expect newline after if
presenceData.state = stateParts.length > 0 ? stateParts.join(' • ') : 'Viewing Details'
presenceData.largeImageKey = document.querySelector<HTMLImageElement>('figure img.object-cover')?.src ||

Check failure

Code scanning / ESLint

Enforce consistent linebreak style for operators Error

'||' should be placed at the beginning of the line.

Check failure

Code scanning / ESLint

Disallow trailing whitespace at the end of lines Error

Trailing spaces not allowed.
document.querySelector<HTMLImageElement>('img[alt*="Poster"]')?.src ||

Check failure

Code scanning / ESLint

Indentation for binary operators Error

Expected indentation of 8 spaces

Check failure

Code scanning / ESLint

Enforce consistent linebreak style for operators Error

'||' should be placed at the beginning of the line.
ActivityAssets.Logo

if (showButtons) {
presenceData.buttons = [
{ label: 'View Movie 🎬', url: href }
]

Check failure

Code scanning / ESLint

Require or disallow trailing commas Error

Missing trailing comma.
}
}
}

// 3. Watch TV: /watch/tv/{id}
if (pathname.startsWith('/watch/tv/')) {
const match = pathname.match(/\/watch\/tv\/(\d+)/)
if (match) {
const tmdbId = match[1]
const showName = getNameFromDOM() || 'Unknown Show'

const season = urlParams.get('season')
const episode = urlParams.get('episode')

Check failure

Code scanning / ESLint

Disallow trailing whitespace at the end of lines Error

Trailing spaces not allowed.
let seasonNo = '1'
let episodeNo = '1'

if (season && episode) {
seasonNo = season
episodeNo = episode
} else {

Check failure

Code scanning / ESLint

Enforce consistent brace style for blocks Error

Closing curly brace appears on the same line as the subsequent block.
const watchHistory = JSON.parse(localStorage.getItem('watch-history') || '{}')
const showData = (tmdbId ? watchHistory[tmdbId] : null) || { last_season_watched: '1', last_episode_watched: '1' }
seasonNo = showData.last_season_watched
episodeNo = showData.last_episode_watched
}

Check failure

Code scanning / ESLint

Disallow trailing whitespace at the end of lines Error

Trailing spaces not allowed.
presenceData.details = `Watching ${showName} 🍿`
presenceData.state = `S${seasonNo} E${episodeNo} • Streaming 📺`
presenceData.type = ActivityType.Watching
presenceData.smallImageKey = Assets.Play

Check failure

Code scanning / ESLint

Disallow trailing whitespace at the end of lines Error

Trailing spaces not allowed.
presenceData.largeImageKey = document.querySelector<HTMLImageElement>('img.poster')?.src || ActivityAssets.Logo

if (showButtons) {
presenceData.buttons = [
{ label: 'Watch Now 🍿', url: href }
]

Check failure

Code scanning / ESLint

Require or disallow trailing commas Error

Missing trailing comma.
}
}
}

// 4. Watch Movie: /watch/movie/{id}
if (pathname.startsWith('/watch/movie/')) {
const movieName = getNameFromDOM() || 'Unknown Movie'
presenceData.details = `Watching ${movieName} 🎬`
presenceData.state = `Enjoying Movie 🍿`
presenceData.type = ActivityType.Watching
presenceData.smallImageKey = Assets.Play
presenceData.largeImageKey = document.querySelector<HTMLImageElement>('img.poster')?.src || ActivityAssets.Logo

if (showButtons) {
presenceData.buttons = [
{ label: 'Watch Now 🍿', url: href }
]

Check failure

Code scanning / ESLint

Require or disallow trailing commas Error

Missing trailing comma.
}
}

// 5. Watch Sports: /watch/sports/{details}
if (pathname.startsWith('/watch/sports/')) {
const sportsSlug = pathname.split('/').pop() || ''
const sportsName = formatSlug(sportsSlug) || 'Live Sports'

Check failure

Code scanning / ESLint

Disallow trailing whitespace at the end of lines Error

Trailing spaces not allowed.
presenceData.details = `Watching ${sportsName} 🏆`
presenceData.type = ActivityType.Watching
presenceData.smallImageKey = Assets.Play
presenceData.state = 'Live Sports Event 📶'

if (showButtons) {
presenceData.buttons = [
{ label: 'Watch Live 📶', url: href }
]

Check failure

Code scanning / ESLint

Require or disallow trailing commas Error

Missing trailing comma.
}
}

// 6. Search Page
if (pathname.includes('/search')) {
const query = urlParams.get('q') || document.querySelector('input')?.getAttribute('value')

Check failure

Code scanning / ESLint

Disallow trailing whitespace at the end of lines Error

Trailing spaces not allowed.
presenceData.details = 'Searching Primeshows 🔎'
if (query) {
presenceData.state = `Looking for: ${query} ✨`
}
presenceData.smallImageKey = Assets.Search
}

if (presenceData.details !== 'Unsupported Page')
presence.setActivity(presenceData)
else

Check failure

Code scanning / ESLint

Disallow trailing whitespace at the end of lines Error

Trailing spaces not allowed.
presence.setActivity()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use clearActivity instead to hide the Activity.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed

})
Loading