-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat(TOD): add presence * feat(TOD): add presence * Update presence.ts * Update metadata.json * Update metadata.json * Update presence.ts Signed-off-by: Wise <[email protected]> * Update metadata.json Signed-off-by: Wise <[email protected]> * Update presence.ts Signed-off-by: Wise <[email protected]> * Update presence.ts Signed-off-by: Wise <[email protected]> * Update metadata.json Signed-off-by: Wise <[email protected]> * Update websites/T/TOD/presence.ts Co-authored-by: Daniel Lau <[email protected]> Signed-off-by: Wise <[email protected]> * Update websites/T/TOD/presence.ts Co-authored-by: Daniel Lau <[email protected]> Signed-off-by: Wise <[email protected]> * feat(TOD): add presence * feat(TOD): add presence * feat(TOD): add presence * chore: restore package lock --------- Signed-off-by: Wise <[email protected]> Co-authored-by: Daniel Lau <[email protected]> Co-authored-by: theusaf <[email protected]>
- Loading branch information
1 parent
be1ec9f
commit 70d06a6
Showing
2 changed files
with
314 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{ | ||
"$schema": "https://schemas.premid.app/metadata/1.10", | ||
"author": { | ||
"id": "640526616350425100", | ||
"name": "itswise" | ||
}, | ||
"service": "TOD", | ||
"description": { | ||
"en": "TOD is a video-streaming platform which includes a lot of movies, TV shows and matches provided by BeIN." | ||
}, | ||
"url": [ | ||
"tod.tv", | ||
"www.tod.tv" | ||
], | ||
"matches": [ | ||
"https://www.tod.tv/*" | ||
], | ||
"version": "1.0.0", | ||
"logo": "https://i.imgur.com/2euETKm.png", | ||
"thumbnail": "https://i.imgur.com/4oCkPdW.jpeg", | ||
"color": "#FEBC11", | ||
"category": "videos", | ||
"tags": [ | ||
"tod", | ||
"video", | ||
"media", | ||
"sports", | ||
"matches" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,284 @@ | ||
const { href } = document.location; | ||
|
||
class TOD extends Presence { | ||
constructor(presenceOptions: PresenceOptions) { | ||
super(presenceOptions); | ||
} | ||
|
||
getVideo() { | ||
return document.querySelector<HTMLMediaElement>("video"); | ||
} | ||
|
||
getVideoType() { | ||
if ( | ||
this.getVideoTitle().match(/S\d+\s*\|\s*E\d+/i) || | ||
this.getVideoTitle().match(/EP\s*\d+/i) | ||
) | ||
return "show"; | ||
else return "movie"; | ||
} | ||
|
||
getTitle(eyebrow = false) { | ||
if (this.isWatching() && eyebrow) return this.getVideoTitle(); | ||
|
||
const title = document.querySelector( | ||
"div.bein-dh1-hero__head-container > h1.bein-dh1-hero__title.heading-shadow" | ||
)?.textContent; | ||
|
||
return ( | ||
title ?? this.getVideoTitle()?.replace(/\d+\s*-\s*\d+/, "vs") ?? "Unknown" | ||
); | ||
} | ||
|
||
getVideoTitle() { | ||
return document.querySelector("div.diva-standard-title")?.textContent; | ||
} | ||
|
||
isWatching() { | ||
return !!this.getVideoTitle(); | ||
} | ||
|
||
isLive() { | ||
return !!document.querySelector("span.diva-live-now"); | ||
} | ||
|
||
isTrailer() { | ||
return this.getVideoTitle().includes("Trailer"); | ||
} | ||
} | ||
|
||
const enum Assets { | ||
Logo = "https://i.imgur.com/2euETKm.png", | ||
} | ||
|
||
const presence = new TOD({ | ||
clientId: "1229087342787039334", | ||
}), | ||
data: { | ||
startedSince: number; | ||
settings?: { | ||
id: string; | ||
delete?: boolean; | ||
data: string[]; | ||
}[]; | ||
presence: { | ||
[key: string]: { | ||
setPresenceData?: () => void; | ||
}; | ||
}; | ||
} = { | ||
presence: {}, | ||
startedSince: Math.floor(Date.now() / 1000), | ||
}; | ||
|
||
presence.on("UpdateData", async () => { | ||
const presenceData: PresenceData = { | ||
type: ActivityType.Watching, | ||
smallImageKey: Assets.Search, | ||
smallImageText: "Browsing", | ||
largeImageKey: Assets.Logo, | ||
details: "Browsing...", | ||
startTimestamp: data.startedSince, | ||
}; | ||
|
||
data.presence = { | ||
"/movie/([a-zA-Z0-9-]+)": { | ||
setPresenceData() { | ||
if (presence.isWatching()) { | ||
const video = presence.getVideo(); | ||
|
||
[, presenceData.endTimestamp] = | ||
presence.getTimestampsfromMedia(video); | ||
|
||
if (presence.isTrailer()) { | ||
presenceData.details = "Watching a trailer"; | ||
presenceData.state = presence.getVideoTitle().replace(/- (.+)/, ""); | ||
|
||
presenceData.smallImageText = video.paused ? "Paused" : "Playing"; | ||
presenceData.smallImageKey = video.paused | ||
? Assets.Pause | ||
: Assets.Play; | ||
|
||
presenceData.buttons = [ | ||
{ | ||
label: "Watch Trailer", | ||
url: href, | ||
}, | ||
]; | ||
} else { | ||
presenceData.details = `Watching ${presence.getVideoType()}`; | ||
presenceData.state = presence.getVideoTitle(); | ||
|
||
presenceData.smallImageText = video.paused ? "Paused" : "Playing"; | ||
presenceData.smallImageKey = video.paused | ||
? Assets.Pause | ||
: Assets.Play; | ||
|
||
presenceData.buttons = [ | ||
{ | ||
label: `Watch ${ | ||
presence.getVideoType() === "show" ? "Show" : "Movie" | ||
}`, | ||
url: href, | ||
}, | ||
]; | ||
} | ||
|
||
if (video.paused) { | ||
delete presenceData.startTimestamp; | ||
delete presenceData.endTimestamp; | ||
} | ||
} else { | ||
(presenceData.details = `Viewing ${ | ||
presence.getVideoType() === "show" ? "Show" : "Movie" | ||
}:`), | ||
(presenceData.state = presence.getVideoTitle().replace(/(.+)/, "")); | ||
|
||
presenceData.buttons = [ | ||
{ | ||
label: `View ${ | ||
presence.getVideoType() === "show" ? "Show" : "Movie" | ||
}:`, | ||
url: href, | ||
}, | ||
]; | ||
} | ||
}, | ||
}, | ||
"/watch/(soccer|multisports)-([a-zA-Z0-9-]+)": { | ||
setPresenceData() { | ||
if (presence.isWatching()) { | ||
const video = presence.getVideo(); | ||
if (presence.isLive()) { | ||
presenceData.smallImageText = video.paused ? "Paused" : "Live"; | ||
presenceData.smallImageKey = video.paused | ||
? Assets.Pause | ||
: Assets.Live; | ||
} else { | ||
[, presenceData.endTimestamp] = | ||
presence.getTimestampsfromMedia(video); | ||
|
||
presenceData.smallImageText = video.paused ? "Paused" : "Playing"; | ||
presenceData.smallImageKey = video.paused | ||
? Assets.Pause | ||
: Assets.Play; | ||
} | ||
|
||
presenceData.details = presence.getTitle(); | ||
presenceData.state = "Match"; | ||
|
||
presenceData.buttons = [ | ||
{ | ||
label: "Watch Match", | ||
url: href, | ||
}, | ||
]; | ||
|
||
if (video.paused) { | ||
delete presenceData.startTimestamp; | ||
delete presenceData.endTimestamp; | ||
} | ||
} else { | ||
presenceData.details = "Watching match:"; | ||
presenceData.state = presence.getTitle(); | ||
|
||
presenceData.buttons = [ | ||
{ | ||
label: "Watch Match", | ||
url: href, | ||
}, | ||
]; | ||
} | ||
}, | ||
}, | ||
"/sports/event/soccer-([a-zA-Z0-9-]+)": { | ||
setPresenceData() { | ||
if (presence.isWatching()) { | ||
const video = presence.getVideo(); | ||
[, presenceData.endTimestamp] = | ||
presence.getTimestampsfromMedia(video); | ||
|
||
presenceData.details = presence.getTitle(); | ||
presenceData.state = "Match"; | ||
|
||
presenceData.smallImageText = video.paused ? "Paused" : "Playing"; | ||
presenceData.smallImageKey = video.paused | ||
? Assets.Pause | ||
: Assets.Play; | ||
|
||
presenceData.buttons = [ | ||
{ | ||
label: "Preview Match", | ||
url: href, | ||
}, | ||
]; | ||
|
||
if (video.paused) { | ||
delete presenceData.startTimestamp; | ||
delete presenceData.endTimestamp; | ||
} | ||
} else { | ||
presenceData.smallImageKey = Assets.Viewing; | ||
presenceData.smallImageText = "Viewing"; | ||
presenceData.details = "Previewing match:"; | ||
presenceData.state = presence.getTitle(); | ||
|
||
presenceData.buttons = [ | ||
{ | ||
label: "Preview Match", | ||
url: href, | ||
}, | ||
]; | ||
} | ||
}, | ||
}, | ||
"/account": { | ||
setPresenceData() { | ||
presenceData.details = "Viewing their settings"; | ||
}, | ||
}, | ||
}; | ||
|
||
data.settings = [ | ||
{ | ||
id: "timestamp", | ||
data: ["startTimestamp", "endTimestamp"], | ||
}, | ||
{ | ||
id: "buttons", | ||
data: ["buttons"], | ||
}, | ||
{ | ||
id: "smallImage", | ||
data: ["smallImageKey"], | ||
}, | ||
]; | ||
|
||
let presenceSelect; | ||
|
||
for (const [pathname, PData] of Object.entries(data.presence)) { | ||
if (new RegExp(pathname).test(document.location.pathname)) { | ||
presenceSelect = pathname; | ||
PData.setPresenceData(); | ||
} | ||
} | ||
|
||
if (!presenceSelect && presence.isWatching()) { | ||
const presenceKey = | ||
presence.getVideoType() === "movie" || presence.getVideoType() === "show" | ||
? "/movie/([a-zA-Z0-9-]+)" | ||
: "Unknown"; | ||
data.presence[presenceKey].setPresenceData(); | ||
} | ||
|
||
for (const setting of data.settings) { | ||
const settingValue = await presence.getSetting<boolean>(setting.id); | ||
|
||
if (!settingValue) { | ||
for (const PData of setting.data) | ||
delete presenceData[PData as keyof PresenceData]; | ||
} | ||
} | ||
|
||
presence.setActivity(presenceData); | ||
}); |