123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- const presence = new Presence({
- clientId: "612793327510749210",
- });
- function findRanking(rankingSelector: Element) {
- return (
- rankingSelector.textContent === strings.stString ||
- rankingSelector.textContent === strings.ndString ||
- rankingSelector.textContent === strings.rdString ||
- rankingSelector.textContent.replace(/\d+/, "{0}") === strings.topX
- );
- }
- async function getStrings() {
- return presence.getStrings(
- {
- buttonJoinGame: "kahoot.buttonJoinGame",
- joiningGame: "kahoot.joiningGame",
- waiting: "kahoot.waiting",
- gameStarting: "kahoot.gameStarting",
- playing: "kahoot.playing",
- questionLoading: "kahoot.questionLoading",
- incorrectAnswer: "kahoot.incorrectAnswer",
- correctAnswer: "kahoot.correctAnswer",
- resultsQuestion: "kahoot.resultsQuestion",
- slideViewing: "kahoot.slideViewing",
- gameOver: "kahoot.gameOver",
- gameCreate: "kahoot.gameCreate",
- loadingPage: "kahoot.loadingPage",
- firstPlace: "kahoot.firstPlace",
- points: "kahoot.points",
- questionsCorrect: "kahoot.questionsCorrect",
- slideShowing: "kahoot.slideShowing",
- questionShowing: "kahoot.questionShowing",
- stString: "kahoot.stString",
- ndString: "kahoot.ndString",
- rdString: "kahoot.rdString",
- topX: "kahoot.topX",
- onPodium: "kahoot.onPodium",
- of: "kahoot.of",
- questionNumber: "kahoot.questionNumber",
- feedback: "kahoot.feedback",
- waitingAnswer: "kahoot.waitingAnswer",
- drumRoll: "kahoot.drumRoll",
- position: "kahoot.position",
- teamTalk: "kahoot.teamTalk",
- gameSummary: "kahoot.gameSummary",
- login: "kahoot.login",
- createHome: "kahoot.createHome",
- discover: "kahoot.discover",
- searchKahoots: "kahoot.searchKahoots",
- kahootDetails: "kahoot.kahootDetails",
- kahootProfile: "kahoot.kahootProfile",
- myKahoots: "kahoot.myKahoots",
- userReports: "kahoot.userReports",
- myCourses: "kahoot.myCourses",
- editingCourse: "kahoot.editingCourse",
- viewingCourse: "kahoot.viewingCourse",
- editingKahoot: "kahoot.editingKahoot",
- previewingKahoot: "kahoot.previewingKahoot",
- liveCourse: "kahoot.liveCourse",
- liveCourseActivity: "kahoot.liveCourseActivity",
- },
- await presence.getSetting<string>("lang").catch(() => "en")
- );
- }
- let strings: Awaited<ReturnType<typeof getStrings>>,
- oldLang: string = null,
- browsingTimestamp = Math.floor(Date.now() / 1000),
- // 0 - ready to be updated if needed
- // 1 - updated, ready to be reset to 0
- timestampUpdateState = 0,
- iframeKahootName: string;
- presence.on("UpdateData", async () => {
- const presenceData: PresenceData = {
- largeImageKey:
- "https://cdn.rcd.gg/PreMiD/websites/K/Kahoot/assets/logo.png",
- startTimestamp: browsingTimestamp,
- },
- [buttons, newLang] = await Promise.all([
- await presence.getSetting<boolean>("buttons"),
- await presence.getSetting<string>("lang").catch(() => "en"),
- ]);
- oldLang ??= newLang;
- strings ??= await getStrings();
- if (oldLang !== newLang) {
- oldLang = newLang;
- strings = await getStrings();
- }
- const { host, pathname } = document.location;
- switch (host) {
- case "kahoot.it": {
- if (
- pathname === "/" ||
- pathname.includes("/join") ||
- pathname === "/v2/"
- ) {
- // Home/Join screen
- presenceData.details = strings.joiningGame;
- } else if (pathname.includes("/instructions")) {
- // Waiting for game to start
- presenceData.details = strings.waiting;
- // Set start timestamp after joining game
- if (timestampUpdateState === 0) {
- browsingTimestamp = Math.floor(Date.now() / 1000);
- timestampUpdateState = 1;
- }
- } else if (pathname.includes("/start")) {
- // Game is starting
- presenceData.details = strings.gameStarting;
- // Allow timestamp to be reset upon a potential replay
- if (timestampUpdateState === 1) timestampUpdateState = 0;
- } else if (pathname.includes("/gameblock")) {
- // Playing/Answering a question
- const [currentQuestion, totalQuestions] = document
- .querySelector('[data-functional-selector="question-index-counter"]')
- .textContent.match(/\d+/g);
- presenceData.details = strings.playing;
- presenceData.state = `${strings.questionNumber.replace(
- "{0}",
- strings.of
- .replace("{0}", currentQuestion)
- .replace("{1}", totalQuestions)
- )} | ${strings.points.replace(
- "{0}",
- document.querySelector(
- '[data-functional-selector="bottom-bar-score"]'
- ).textContent
- )}`;
- } else if (pathname.includes("/getready")) {
- // Next question is loading
- const [currentQuestion, totalQuestions] = document
- .querySelector('[data-functional-selector="question-index-counter"]')
- .textContent.match(/\d+/g);
- presenceData.details = strings.questionLoading;
- presenceData.state = `${strings.questionNumber.replace(
- "{0}",
- strings.of
- .replace("{0}", currentQuestion)
- .replace("{1}", totalQuestions)
- )}`;
- } else if (pathname.includes("/teamtalk")) {
- // Team discussion time
- presenceData.details = strings.teamTalk;
- } else if (
- pathname.includes("/answer") &&
- !pathname.includes("/result")
- ) {
- // Waiting for question to end
- presenceData.details = strings.waitingAnswer;
- } else if (pathname.includes("/result")) {
- // Answer result screen
- const rankingSelector = document.querySelector(
- '[data-functional-selector="player-rank"]'
- );
- if (!rankingSelector) presenceData.details = strings.resultsQuestion;
- else {
- presenceData.details = strings.resultsQuestion;
- presenceData.state = `${
- document.querySelector(
- '[data-functional-selector="correct-answer"]'
- )
- ? strings.correctAnswer
- : strings.incorrectAnswer
- } | ${
- /\d+/.test(rankingSelector.textContent)
- ? strings.position.replace(
- "{0}",
- rankingSelector.textContent.match(/\d+/)[0]
- )
- : strings.onPodium
- } | ${strings.points.replace(
- "{0}",
- document.querySelector(
- '[data-functional-selector="bottom-bar-score"]'
- ).textContent
- )}`;
- }
- } else if (pathname.includes("/contentblock")) {
- // Viewing a slide with content
- presenceData.details = strings.slideViewing;
- } else if (pathname.includes("/ranking")) {
- // Viewing the final ranking
- const rankingSelector = document.querySelector(
- '[data-functional-selector="ranking-header"],[data-functional-selector="ranking-header-winners"]'
- );
- if (!rankingSelector) presenceData.details = strings.drumRoll;
- else {
- const score = document.querySelector(
- '[data-functional-selector="bottom-bar-score"]'
- ).textContent;
- presenceData.details = findRanking(rankingSelector)
- ? `${strings.gameOver} | ${
- rankingSelector.textContent
- } | ${strings.points.replace("{0}", score)}`
- : `${strings.gameOver} | ${strings.points.replace("{0}", score)}`;
- }
- } else if (pathname.includes("/feedback")) {
- // Providing feedback
- presenceData.details = strings.feedback;
- } else presenceData.details = strings.loadingPage;
- presence.setActivity(presenceData);
- break;
- }
- case "play.kahoot.it": {
- switch (pathname) {
- case "/v2/": {
- // Settings/game creation
- presenceData.details = strings.gameCreate;
- break;
- }
- case "/v2/lobby": {
- // Lobby screen
- presenceData.details = strings.waiting;
- // Set start timestamp after game has been created
- if (timestampUpdateState === 0) {
- browsingTimestamp = Math.floor(Date.now() / 1000);
- presenceData.startTimestamp = browsingTimestamp;
- timestampUpdateState = 1;
- }
- if (buttons) {
- const pin = document.querySelector(
- '[data-functional-selector="game-pin"]'
- )?.textContent;
- if (pin) {
- presenceData.buttons = [
- {
- label: `${strings.buttonJoinGame.replace("{0}", pin)}`,
- url: `https://kahoot.it/?pin=${pin}`,
- },
- ];
- }
- }
- break;
- }
- case "/v2/start": {
- // Game start
- presenceData.details = strings.gameStarting;
- // Allow timestamp to be reset upon a potential replay
- if (timestampUpdateState === 1) timestampUpdateState = 0;
- break;
- }
- case "/v2/gameover": {
- presenceData.details = `${strings.firstPlace.replace(
- "{0}",
- document.querySelector('[data-functional-selector="winner"]')
- .textContent
- )} | ${strings.points.replace(
- "{0}",
- document.querySelector(
- '[data-functional-selector="place-1"] > [data-functional-selector="total-score"]'
- ).textContent
- )}`;
- const correctCount = document.querySelector(
- '[data-functional-selector="correct-count-gold"]'
- );
- if (correctCount) {
- const [correct, total] = correctCount.textContent.match(/\d+/g);
- presenceData.state = strings.questionsCorrect.replace(
- "{0}",
- strings.of.replace("{0}", correct).replace("{1}", total)
- );
- } else
- presenceData.state = strings.questionsCorrect.replace("{0}", "0");
- break;
- }
- case "/v2/gameblock": {
- if (
- document.querySelector(
- '[data-functional-selector="content-block-page"]'
- )
- ) {
- // Showing a Slide with Content
- presenceData.details = strings.slideShowing;
- } else {
- // Question in progress
- const questionCounter = document.querySelector(
- '[data-functional-selector="bottom-bar-question-counter"]'
- );
- if (!questionCounter) {
- // Question is starting
- presenceData.details = strings.questionLoading;
- } else {
- // Question is in progress
- const [currentQuestion, totalQuestions] =
- questionCounter.textContent.split("/");
- presenceData.details = strings.questionShowing;
- presenceData.state = `${strings.questionNumber.replace(
- "{0}",
- `${strings.of
- .replace("{0}", currentQuestion)
- .replace("{1}", totalQuestions)}`
- )}`;
- }
- }
- break;
- }
- case "/v2/game-summary": {
- // Game summary
- presenceData.details = strings.gameSummary;
- break;
- }
- default:
- presenceData.details = strings.loadingPage;
- }
- presence.setActivity(presenceData);
- break;
- }
- case "create.kahoot.it": {
- switch (pathname) {
- case "/": {
- // Kahoot! Create home page
- presenceData.details = strings.createHome;
- presenceData.state = "create.kahoot.it";
- break;
- }
- case "/after/login":
- case "/auth/login": {
- // Login
- presenceData.details = strings.login;
- break;
- }
- case "/discover": {
- // Discover
- presenceData.details = strings.discover;
- break;
- }
- case "/search": {
- // Search
- presenceData.details = strings.searchKahoots;
- presenceData.state = document.querySelector<HTMLInputElement>(
- '[data-functional-selector="search-box__input-field"]'
- ).value;
- break;
- }
- default:
- if (pathname.startsWith("/details/")) {
- // Kahoot details
- presenceData.details = strings.kahootDetails;
- presenceData.state = document.querySelector(
- '[data-functional-selector="kahoot-detail__title"]'
- ).textContent;
- } else if (pathname.startsWith("/profiles/")) {
- // Kahoot profile
- presenceData.details = strings.kahootProfile;
- presenceData.state = (
- document.querySelector(
- '[data-functional-selector="verified-user-profile-information"] > div > div'
- ) ??
- document.querySelector(
- '[data-functional-selector="default-user-profile"] > div > div > div:nth-of-type(2) > div'
- )
- ).firstChild.textContent.replace(/\n/g, " ");
- } else if (pathname.startsWith("/my-library/kahoots/")) {
- // My Kahoots
- presenceData.details = strings.myKahoots;
- } else if (pathname === "/user-reports") {
- // Game Reports
- presenceData.details = strings.userReports;
- } else if (pathname === "/my-library/courses") {
- // My Courses
- presenceData.details = strings.myCourses;
- } else if (pathname.startsWith("/course/")) {
- if (pathname.endsWith("/edit")) {
- // Editing a course
- presenceData.details = strings.editingCourse;
- presenceData.state = document.querySelector<HTMLInputElement>(
- '[data-functional-selector="course-title-input__course_title_input"]'
- ).value;
- } else {
- // Viewing a course
- presenceData.details = strings.viewingCourse;
- presenceData.state = document.querySelector(
- '[data-functional-selector="course-details"] h2'
- ).textContent;
- }
- } else if (pathname.startsWith("/creator/")) {
- // Editing a Kahoot!
- presenceData.details = strings.editingKahoot;
- presenceData.state = document.querySelector(
- '[data-functional-selector="top-bar__kahoot-summary-button"] > span'
- ).textContent;
- } else if (pathname.startsWith("/preview/")) {
- // Previewing a Kahoot!
- presenceData.details = strings.previewingKahoot;
- presenceData.state = iframeKahootName;
- } else if (pathname.startsWith("/v2/live-course/")) {
- // Live course
- presenceData.details = strings.liveCourse;
- const preview = document.querySelector(
- '[data-functional-selector="mega-menu__session-title"]'
- );
- if (preview) presenceData.state = preview.textContent;
- else {
- const course = document.querySelector(
- '[data-functional-selector="live-course-menu__toggle-mega-menu"] > span:nth-of-type(2)'
- ),
- [number] = course.textContent.match(/^\d+/);
- presenceData.state = strings.liveCourseActivity
- .replace("{0}", number)
- .replace(
- "{1}",
- course.textContent.substring(number.length + 2)
- );
- }
- } else presenceData.details = strings.loadingPage;
- }
- presence.setActivity(presenceData);
- break;
- }
- }
- });
- presence.on("iFrameData", (data: string) => {
- iframeKahootName = data;
- });
|