Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix color, personality, traits raw data extraction #1661

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
116 changes: 94 additions & 22 deletions source/plugins/community/16personalities/index.mjs
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -17,42 +16,115 @@ 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
const type = raw.type.replace("(", "").replace(")", "").trim()
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}
}
Expand Down
29 changes: 25 additions & 4 deletions source/templates/classic/partials/16personalities.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,42 @@
</section>
</div>
<% } else { %>
<% if ((plugins["16personalities"].sections.includes("personality"))||(plugins["16personalities"].sections.includes("profile"))) { %>
<!-- Render Personality if the 'personality' section is enabled -->
<% if (plugins["16personalities"].sections.includes("personality") || plugins["16personalities"].sections.includes("profile")) { %>
<div class="row fill-width">
<section class="personality-traits categories">
<% for (const {category, value, image, text} of plugins["16personalities"].personality) { if (((!plugins["16personalities"].sections.includes("personality"))&&(/personality/i.test(category)))||((!plugins["16personalities"].sections.includes("profile"))&&(!/personality/i.test(category)))) continue %>
<% for (const {category, value, image, text} of plugins["16personalities"].personality) { %>
<%
// Conditional check to filter categories if needed
if (
(!plugins["16personalities"].sections.includes("personality") && /personality/i.test(category)) ||
(!plugins["16personalities"].sections.includes("profile") && !/personality/i.test(category))
) continue;
%>
<div class="category">
<img src="<%= image %>" alt="" />
<!-- Render SVG or Image based on content -->
<% if (image.startsWith('<svg')) { %>
<!-- SVG handling -->
<div class="svg-container" style="width: 50px; height: 50px;">
<img src="<%= image %>" alt="<%= category %>" />
</div>
<% } else { %>
<!-- Fallback for other images -->
<img src="<%= image %>" alt="<%= category %>" />
<% } %>

<div class="explanation">
<span class="title" style="color: <%= plugins["16personalities"].color %>;"><span class="subtitle"><%= value %></span> <%= category.toLocaleLowerCase() %></span>
<span class="title" style="color: <%= plugins["16personalities"].color %>;">
<span class="subtitle"><%= value %></span> <%= category.toLowerCase() %>
</span>
<span class="text"><%= text %></span>
</div>
</div>
<% } %>
</section>
</div>
<% } %>
<!-- Render Traits if the 'traits' section is enabled -->
<% if (plugins["16personalities"].sections.includes("traits")) { %>
<div class="row fill-width">
<section class="personality-traits categories">
Expand Down
Loading