diff --git a/source/plugins/community/16personalities/index.mjs b/source/plugins/community/16personalities/index.mjs index 92d8fb28a21..2cd5bd0182c 100644 --- a/source/plugins/community/16personalities/index.mjs +++ b/source/plugins/community/16personalities/index.mjs @@ -1,8 +1,7 @@ //Setup export default async function({login, q, imports, data, account}, {enabled = false, extras = false} = {}) { - //Plugin execution try { - //Check if plugin is enabled and requirements are met + //Check if the plugin is enabled and requirements are met if ((!q["16personalities"]) || (!imports.metadata.plugins["16personalities"].enabled(enabled, {extras}))) return null @@ -17,25 +16,95 @@ export default async function({login, q, imports, data, account}, {enabled = fal console.debug(`metrics/compute/${login}/plugins > 16personalities > started ${await browser.version()}`) const page = await browser.newPage() console.debug(`metrics/compute/${login}/plugins > 16personalities > loading ${url}`) - await page.goto(url, {waitUntil: imports.puppeteer.events}) + + //Capture console messages from the browser context + page.on("console", msg => { + if (msg.type() === "debug") { + console.debug(`BROWSER: ${msg.text()}`) + } + }) + + await page.goto(url, {waitUntil: "networkidle2"}) //Fetch raw data - const raw = await page.evaluate(() => ({ - color: getComputedStyle(document.querySelector(".card__bg")).backgroundColor, //eslint-disable-line no-undef - type: document.querySelector(".type__code").innerText, - personality: [...document.querySelectorAll(".personality-cards .sp-personality-card")].map(card => ({ - category: card.querySelector(".card__title").innerText, - value: card.querySelector(".card__subtitle").innerText, - image: card.querySelector(".card__image").src, - text: card.querySelector(".card__text").innerText, - })), - traits: [...document.querySelectorAll("#traits .card__body")].map(card => ({ - category: card.querySelector(".card__title").innerText, - value: card.querySelector(".card__subtitle").innerText, - score: card.querySelector(".center__num").innerText, - text: card.querySelector("p").innerText, - })), - })) + const raw = await page.evaluate(() => { + const getInnerText = selector => document.querySelector(selector)?.innerText || "" + + //Default map personality category to RGB colors + const defaultPersonalityColors = { + explorers: "rgb(228, 174, 58)", //Virtuoso, Adventurer, Entrepreneur, Entertainer + sentinels: "rgb(66, 152, 180)", //Logistician, Defender, Executive, Consul + diplomats: "rgb(51, 164, 116)", //Advocate, Mediator, Protagonist, Campaigner + analysts: "rgb(136, 97, 154)", //Architect, Logician, Commander, Debater + default: "rgb(0, 0, 0)" + } + let defaultColor = defaultPersonalityColors.default + + //Choose the default color based on the personality type + const personalityType = getInnerText(".link--inline") + if (personalityType.includes("Virtuoso") || personalityType.includes("Adventurer") || personalityType.includes("Entrepreneur") || personalityType.includes("Entertainer")) + defaultColor = defaultPersonalityColors.explorers + else if (personalityType.includes("Logistician") || personalityType.includes("Defender") || personalityType.includes("Executive") || personalityType.includes("Consul")) + defaultColor = defaultPersonalityColors.sentinels + else if (personalityType.includes("Advocate") || personalityType.includes("Mediator") || personalityType.includes("Protagonist") || personalityType.includes("Campaigner")) + defaultColor = defaultPersonalityColors.diplomats + else if (personalityType.includes("Architect") || personalityType.includes("Logician") || personalityType.includes("Commander") || personalityType.includes("Debater")) + defaultColor = defaultPersonalityColors.analysts + + console.debug(`Personality Type: ${personalityType}`) + + return { + //Type extraction + type: getInnerText(".type__code"), + + //Personality details extraction + personality: [...document.querySelectorAll(".slider__slides > div")].map(card => { + //Extract image data + let image = "" + const cardElement = card.querySelector(".card__image") + //Check if the card has an image as an url, e.g., the "His Role" image or the "His Strategy" image + if (cardElement.querySelector("img")) { + image = cardElement.querySelector("img").src + console.debug(`Image for ${card.querySelector(".card__title")?.innerText}: ${image}`) + } + //Check if the card has a image as a svg, e.g., the "His personality" image + else if (cardElement.querySelector("svg")) { + image = new XMLSerializer().serializeToString(cardElement.querySelector("svg")) + image = `data:image/svg+xml,${encodeURIComponent(image)}` + console.debug(`Image for ${card.querySelector(".card__title")?.innerText} is a svg`) + } + + return { + category: card.querySelector(".card__title")?.innerText || "", //Category, e.g., "His role" + value: card.querySelector(".card__subtitle")?.innerText || "", //Value of the category, e.g., "Sentinel" + image, //Image of the category + text: card.querySelector(".prevent--drag.card__p")?.innerText || "" //Description of the category + } + }), + + //Traits details extraction + traits: [...document.querySelectorAll(".traits__boxes > div")].map(card => { + const categoryText = card.querySelector(".traitbox__label")?.innerText + const scoreText = card.querySelector(".traitbox__value")?.innerText.trim() //Get the text like "75% Extraverted" + + console.debug(`Parsing Trait category ${categoryText} ${scoreText}`) + + //Split the score text into percentage and trait + const [percentage, ...traitArray] = scoreText.split(" ") + + //Return the traits details + return { + category: categoryText || "", //Trait category name, e.g., "Energy" + value: traitArray.join(" ") || "", //Extracted trait, e.g., "Extraverted" + score: percentage || "", //Extracted percentage, e.g., "75%" + text: card.querySelector("p").innerText || "" //Description of the trait + } + }), + + //Color + color: document.querySelector(".card__bg") ? getComputedStyle(document.querySelector(".card__bg")).backgroundColor : defaultColor //eslint-disable-line no-undef + } + }) //Format data const {color} = raw @@ -43,16 +112,19 @@ export default async function({login, q, imports, data, account}, {enabled = fal const personality = await Promise.all(raw.personality.map(async ({category, value, image, text}) => ({ category, value: value.replace(`(${type})`, "").trim(), - image: await imports.imgb64(image), + image: image.startsWith("data:image/svg+xml,") ? image : await imports.imgb64(image), text: text.replace(`${category}\n${value}\n`, "").trim(), }))) const traits = raw.traits.map(({category, value, score, text}) => ({ - category, + category: category.replace(":", "").trim(), value: `${value[0]}${value.substring(1).toLocaleLowerCase()}`, score: scores ? Number(score.replace("%", "")) / 100 : NaN, - text: text.split(".").slice(1).join("."), + text: text.trim() })) + //Close browser + await browser.close() + //Results return {sections, color, type, personality, traits} } diff --git a/source/templates/classic/partials/16personalities.ejs b/source/templates/classic/partials/16personalities.ejs index 48883f7959e..c8a8ba94684 100644 --- a/source/templates/classic/partials/16personalities.ejs +++ b/source/templates/classic/partials/16personalities.ejs @@ -14,14 +14,34 @@ <% } else { %> - <% if ((plugins["16personalities"].sections.includes("personality"))||(plugins["16personalities"].sections.includes("profile"))) { %> + + <% if (plugins["16personalities"].sections.includes("personality") || plugins["16personalities"].sections.includes("profile")) { %>