Last active
April 29, 2023 10:37
-
-
Save Maista6969/568826199a314adbc15abe7813c4ac55 to your computer and use it in GitHub Desktop.
Shows the summarized O-counter and scene ratings for performer cards in Stash
This file contains hidden or 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
// ==UserScript== | |
// @name Rating stats for performers | |
// @author Maista | |
// @namespace com.maista.userscripts | |
// @version 1.0 | |
// @require https://gist.githubusercontent.com/Maista6969/aaf8f04b1af7603ed27866e9e7f46a02/raw/53f00a1ccc3370e65af4735c46bcc0a71ac5ef77/onElementReady.js | |
// @include http://localhost:9999/* | |
// @grant GM_xmlhttpRequest | |
// @icon http://localhost:9999/favicon.ico | |
// ==/UserScript== | |
const script_name = GM_info.script.name.toLowerCase().split(' ').join('-'); | |
onElementReady('.performer-card', showStats, script_name); | |
async function showStats(performerCard) { | |
const performerId = performerCard.querySelector('a[href*=performers]').href.split('/').pop(); | |
const popoverRow = performerCard.querySelector('.card-popovers'); | |
if (popoverRow === null) return; | |
const newElems = await getPerformerData(performerId).then(summarizeSceneData).then(makeIcons); | |
newElems.forEach(el => popoverRow.appendChild(el)); | |
} | |
function makeIcons({id, name, o_total, avgRating, numScenes}) { | |
const elems = []; | |
const baseUrl = `http://localhost:9999/scenes?c=(%22type%22:%22performers%22,%22value%22:%5B(%22id%22:%22${id}%22,%22label%22:%22${name}%22)%5D,%22modifier%22:%22INCLUDES%22)`; | |
if (o_total > 0) { | |
const oEl = document.createElement('a'); | |
oEl.title = `${o_total} total Os`; | |
oEl.href = `${baseUrl}&sortby=o_counter&sortdir=desc`; | |
const oButton = document.createElement('button'); | |
oButton.classList.add("minimal", "btn", "btn-primary"); | |
oButton.innerHTML = `<svg class="svg-inline--fa fa-icon" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="currentColor" d="M22.855.758L7.875 7.024l12.537 9.733c2.633 2.224 6.377 2.937 9.77 1.518c4.826-2.018 7.096-7.576 5.072-12.413C33.232 1.024 27.68-1.261 22.855.758zm-9.962 17.924L2.05 10.284L.137 23.529a7.993 7.993 0 0 0 2.958 7.803a8.001 8.001 0 0 0 9.798-12.65zm15.339 7.015l-8.156-4.69l-.033 9.223c-.088 2 .904 3.98 2.75 5.041a5.462 5.462 0 0 0 7.479-2.051c1.499-2.644.589-6.013-2.04-7.523z"></path></svg><span>${o_total}</span>`; | |
oEl.appendChild(oButton); | |
elems.push(oEl); | |
} | |
if (!avgRating.includes("NaN")) { | |
const arEl = document.createElement('a'); | |
arEl.title = `${avgRating} average rating based on ${numScenes} rated scenes`; | |
arEl.href = `${baseUrl}&sortby=rating&sortdir=desc`; | |
let arButton = document.createElement('button'); | |
arButton.classList.add("minimal", "btn", "btn-primary"); | |
arButton.innerHTML = `<svg class="svg-inline--fa fa-star fa-icon unset" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M287.9 0C297.1 0 305.5 5.25 309.5 13.52L378.1 154.8L531.4 177.5C540.4 178.8 547.8 185.1 550.7 193.7C553.5 202.4 551.2 211.9 544.8 218.2L433.6 328.4L459.9 483.9C461.4 492.9 457.7 502.1 450.2 507.4C442.8 512.7 432.1 513.4 424.9 509.1L287.9 435.9L150.1 509.1C142.9 513.4 133.1 512.7 125.6 507.4C118.2 502.1 114.5 492.9 115.1 483.9L142.2 328.4L31.11 218.2C24.65 211.9 22.36 202.4 25.2 193.7C28.03 185.1 35.5 178.8 44.49 177.5L197.7 154.8L266.3 13.52C270.4 5.249 278.7 0 287.9 0L287.9 0zM287.9 78.95L235.4 187.2C231.9 194.3 225.1 199.3 217.3 200.5L98.98 217.9L184.9 303C190.4 308.5 192.9 316.4 191.6 324.1L171.4 443.7L276.6 387.5C283.7 383.7 292.2 383.7 299.2 387.5L404.4 443.7L384.2 324.1C382.9 316.4 385.5 308.5 391 303L476.9 217.9L358.6 200.5C350.7 199.3 343.9 194.3 340.5 187.2L287.9 78.95z"></path></svg><span>${avgRating}</span>`; | |
arEl.appendChild(arButton); | |
elems.push(arEl); | |
} | |
return elems; | |
} | |
function summarizeSceneData({scenes, ...rest}) { | |
const o_total = scenes.map(({o_counter}) => o_counter).reduce((a, b) => a+b, 0); | |
const ratings = scenes.map(({rating100}) => rating100).filter(rating => rating !== null); | |
const numScenes = ratings.length; | |
const avgRating = (ratings.reduce((a, b) => a+b, 0) / numScenes / 20).toPrecision(2); | |
return { o_total, avgRating, numScenes, ...rest }; | |
} | |
function getPerformerData(id) { | |
let query = JSON.stringify( | |
{ | |
"query": "query FindPerformer($id: ID!) { findPerformer(id: $id) { name id scenes { o_counter, rating100 } } }", | |
"variables": { | |
"id": id | |
} | |
}); | |
return new Promise((resolve, reject) => { | |
GM_xmlhttpRequest({ | |
method: "POST", | |
responseType: "json", | |
url: "http://localhost:9999/graphql", | |
headers: { "Content-Type": "application/json" }, | |
data: query, | |
onload: (res) => { | |
try { | |
if (res.status != 200) { | |
let errors = res.response.errors.map((e) => e.message).join('\n'); | |
reject(`Query for '${id}' failed: ${errors}`); | |
return; | |
} | |
resolve(res.response.data.findPerformer); | |
} catch (error) { | |
reject(error.message); | |
} | |
} | |
}); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment