123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- const presence = new Presence({
- clientId: "809093093600133165",
- }),
- browsingTimestamp = Math.floor(Date.now() / 1000);
- let cached: {
- videoURL: string;
- video: HTMLVideoElement;
- };
- async function getStrings() {
- return presence.getStrings(
- {
- playing: "general.playing",
- paused: "general.paused",
- live: "general.live",
- browse: "general.browsing",
- forYou: "tiktok.forYou",
- following: "tiktok.following",
- buttonViewProfile: "general.buttonViewProfile",
- viewProfile: "general.viewProfile",
- viewAProfile: "general.viewAProfile",
- viewTikTok: "tiktok.viewing",
- buttonViewTikTok: "tiktok.buttonViewTikTok",
- browseThrough: "tiktok.browseThrough",
- watchingLive: "general.watchingLive",
- readingADM: "general.readingADM",
- exploringWithTag: "tiktok.exploringWithTag",
- viewAPlaylist: "general.viewAPlaylist",
- buttonWatchStream: "general.buttonWatchStream",
- },
- await presence.getSetting<string>("lang").catch(() => "en")
- );
- }
- function getVideo(video: HTMLVideoElement | null) {
- const videoURL = video?.src;
- if (
- videoURL &&
- (!cached?.videoURL || !cached?.video || cached?.videoURL !== videoURL)
- ) {
- cached = {
- videoURL,
- video,
- };
- return;
- } else if (!video && cached.video) return cached.video;
- }
- let strings: Awaited<ReturnType<typeof getStrings>>,
- oldLang: string = null;
- presence.on("UpdateData", async () => {
- const presenceData: PresenceData = {
- type: ActivityType.Watching,
- largeImageKey:
- "https://cdn.rcd.gg/PreMiD/websites/T/TikTok/assets/logo.png",
- startTimestamp: browsingTimestamp,
- },
- [newLang, privacy, buttons, showProfileUsernames] = await Promise.all([
- presence.getSetting<string>("lang").catch(() => "en"),
- presence.getSetting<boolean>("privacy"),
- presence.getSetting<boolean>("buttons"),
- presence.getSetting<boolean>("show-profile-usernames"),
- ]),
- { pathname, hostname, href } = document.location,
- lang = document.querySelector("html")?.getAttribute("lang"),
- username =
- document.querySelector('[data-e2e="user-profile-nickname"]')
- ?.textContent ??
- document.querySelector('[data-e2e="user-subtitle"]')?.textContent ??
- document
- .querySelector('[data-e2e="browser-nickname"]')
- ?.querySelector('[class*="SpanNickName"]')?.textContent ??
- document.querySelector('[data-e2e="browser-nickname"]')?.firstElementChild
- ?.textContent, // Username
- userid =
- document.querySelector('[data-e2e="user-profile-uid"]')?.textContent ??
- document.querySelector('[data-e2e="user-title"]')?.textContent ??
- document.querySelector('[data-e2e="browse-username"]')?.textContent, //Userid (so @userid)
- description =
- document.querySelector('[data-e2e="user-profile-live-title"]')
- ?.textContent ??
- document.querySelector('[data-e2e="browse-video-desc"]')?.textContent; // Video/livestream description
- if (oldLang !== newLang || !strings) {
- oldLang = newLang;
- strings = await getStrings();
- }
- switch (true) {
- case pathname === "/following":
- case pathname.includes("foryou"):
- case pathname === "/":
- case pathname === `/${lang}`:
- case pathname === `/${lang}/`: {
- if (!privacy) delete presenceData.startTimestamp;
- const videos = Array.from(document.querySelectorAll("video")).find(
- video => !video.paused
- );
- let video: HTMLVideoElement;
- if (videos) {
- video = videos;
- getVideo(videos);
- } else video = getVideo(null);
- const baseEl = video?.closest(
- '[data-e2e="recommend-list-item-container"]'
- ),
- userId = baseEl?.querySelector('h3[data-e2e="video-author-uniqueid"]'),
- tiktokURL = `https://www.tiktok.com/@${userId?.textContent}/video/${
- video
- ?.closest('[class="tiktok-web-player no-controls"]')
- ?.getAttribute("id")
- ?.split("-")?.[2]
- }`,
- creatorURL = `https://${hostname}${
- userId?.parentElement?.getAttribute("href") ?? ""
- }/`,
- tiktokURLMatch = tiktokURL.match(
- /https:\/\/www[.]tiktok[.]com\/@.*\/video\/[0-9]{19}/
- ),
- creatorURLMatch = creatorURL.match(
- /http(s)?:\/\/(www[.])?tiktok\.com\/@([\w.]{0,23}\w)(?:\/\S*)?\//
- )?.[0],
- paused =
- video
- ?.closest('div[data-e2e="feed-video"]')
- ?.querySelector('[data-e2e="video-play"]')
- ?.getAttribute("aria-label")
- ?.toLowerCase() === "pause";
- presenceData.details = privacy
- ? strings.browseThrough
- : userId &&
- baseEl?.querySelector('[data-e2e="video-author-nickname"]')
- ?.textContent
- ? `${
- baseEl?.querySelector('[data-e2e="video-author-nickname"]')
- ?.textContent
- } (@${userId?.textContent})`
- : strings.browseThrough;
- presenceData.state = baseEl?.querySelector(
- '[data-e2e="video-desc"]'
- )?.textContent;
- if (tiktokURLMatch && creatorURLMatch) {
- presenceData.buttons = [
- { label: strings.buttonViewTikTok, url: tiktokURL },
- {
- label: strings.buttonViewProfile,
- url: creatorURL,
- },
- ];
- } else if (creatorURLMatch) {
- presenceData.buttons = [
- {
- label: strings.buttonViewProfile,
- url: creatorURL,
- },
- ];
- } else if (tiktokURLMatch) {
- presenceData.buttons = [
- { label: strings.buttonViewTikTok, url: tiktokURL },
- ];
- }
- if (!paused && video?.duration && video?.currentTime) {
- [presenceData.startTimestamp, presenceData.endTimestamp] =
- presence.getTimestampsfromMedia(video);
- }
- presenceData.smallImageKey = paused ? Assets.Pause : Assets.Play;
- presenceData.smallImageText = paused ? strings.paused : strings.playing;
- break;
- }
- case pathname.includes("/video/"): {
- if (!privacy) delete presenceData.startTimestamp;
- const vidEl = document.querySelector("video");
- let video: {
- paused: boolean;
- currentTime: number;
- duration: number;
- };
- if (!vidEl) {
- video = {
- paused:
- !!document.querySelector('[aria-label="Pause"]') ||
- !!document.querySelector("[class*='DivPlayIconContainer']"),
- currentTime: presence.timestampFromFormat(
- document
- .querySelector("[class*='DivSeekBarTimeContainer']")
- ?.textContent?.split("/")[0]
- ),
- duration: presence.timestampFromFormat(
- document
- .querySelector("[class*='DivSeekBarTimeContainer']")
- ?.textContent?.split("/")[1]
- ),
- };
- } else {
- video = {
- paused: vidEl?.paused,
- currentTime: vidEl.currentTime,
- duration: vidEl.duration,
- };
- }
- presenceData.details = privacy
- ? strings.browseThrough
- : `${username} (@${userid})`;
- presenceData.state = description;
- presenceData.smallImageKey = video.paused ? Assets.Pause : Assets.Play;
- presenceData.smallImageText = video.paused
- ? strings.paused
- : strings.playing;
- if (!video.paused) {
- [presenceData.startTimestamp, presenceData.endTimestamp] =
- presence.getTimestamps(video.currentTime, video.duration);
- }
- presenceData.buttons = [
- { label: strings.buttonViewTikTok, url: href },
- {
- label: strings.buttonViewProfile,
- url: `https://www.tiktok.com/@${userid}`,
- },
- ];
- break;
- }
- case pathname === "/live": {
- const videos = Array.from(document.querySelectorAll("video")).find(
- video => !video.paused
- );
- let video: HTMLVideoElement;
- if (videos) {
- video = videos;
- getVideo(videos);
- } else video = getVideo(null);
- presenceData.details = privacy
- ? strings.watchingLive
- : `${strings.watchingLive} - ${
- video?.parentElement?.querySelector('[class*="SpanNickName"]')
- ?.textContent
- }`;
- presenceData.state = video?.parentElement?.querySelectorAll(
- '[class="css-1g1mtx-DivDetailsLine eawfp3g1"]'
- )?.[1]?.textContent;
- presenceData.smallImageKey = video?.paused ? Assets.Pause : Assets.Live;
- presenceData.smallImageText = video?.paused
- ? strings.paused
- : strings.live;
- presenceData.buttons = [
- {
- label: strings.buttonWatchStream,
- url: `https://www.tiktok.com/${
- video?.parentElement?.querySelector('[class*="SpanNickName"]')
- ?.textContent
- }/live`,
- },
- {
- label: strings.buttonViewProfile,
- url: `https://www.tiktok.com/${
- video?.parentElement?.querySelector('[class*="SpanNickName"]')
- ?.textContent
- }`,
- },
- ];
- break;
- }
- case pathname.includes("/live"): {
- const video = document.querySelector("video");
- presenceData.details = privacy
- ? strings.watchingLive
- : `${strings.watchingLive} - ${username} (@${userid})`;
- presenceData.state = description;
- presenceData.smallImageKey = video?.paused ? Assets.Pause : Assets.Live;
- presenceData.smallImageText = video?.paused
- ? strings.paused
- : strings.live;
- presenceData.buttons = [
- { label: strings.buttonWatchStream, url: href },
- {
- label: strings.buttonViewProfile,
- url: href?.split("/live")?.[0],
- },
- ];
- break;
- }
- case pathname.includes("/@"): {
- const playlistMenu = document
- .querySelector('[class*="DivModalContainer eo04fh215"]')
- ?.querySelector('[class*="Title"]');
- presenceData.details =
- privacy || !showProfileUsernames
- ? strings.viewAProfile
- : `${strings.viewProfile} ${username} (@${userid})`;
- if (showProfileUsernames) {
- presenceData.buttons = [
- { label: strings.buttonViewProfile, url: href },
- ];
- }
- presenceData.state = playlistMenu
- ? `${strings.viewAPlaylist} - ${playlistMenu?.textContent}`
- : document.querySelector('p[aria-selected="true"]')?.textContent;
- break;
- }
- case pathname.includes("/explore"): {
- presenceData.details = privacy
- ? strings.browseThrough
- : strings.exploringWithTag;
- presenceData.state = document.querySelector(
- ".css-1hs87dt-ButtonCategoryItemContainer"
- )?.textContent;
- break;
- }
- case pathname.includes("/messages"): {
- presenceData.details = privacy
- ? strings.browseThrough
- : strings.readingADM;
- break;
- }
- }
- if ((!buttons || privacy) && presenceData.buttons)
- delete presenceData.buttons;
- if (privacy && presenceData.state) delete presenceData.state;
- if (privacy && presenceData.endTimestamp) delete presenceData.endTimestamp;
- if (privacy && presenceData.smallImageKey) delete presenceData.smallImageKey;
- presence.setActivity(presenceData);
- });
|