Last active
August 8, 2023 02:50
-
-
Save Maista6969/124d0ddfd5fc05ec8cce7cf21e46b9dd to your computer and use it in GitHub Desktop.
Shows the summarized O-counter and scene ratings for studio cards in Stash
This file contains 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 studios | |
// @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('.studio-card', showStats, script_name); | |
async function showStats(studioCard) { | |
const studioId = studioCard.querySelector('a[href*=studios]').href.split('/').pop(); | |
const name = studioCard.querySelector('h5').innerText; | |
let popoverRow = studioCard.querySelector('.card-popovers'); | |
// Some studios only have child studios and no scenes of their own but we summarize | |
// the stats for all children so we need to create the popover row for icons ourselves | |
if (popoverRow === null) { | |
studioCard.insertAdjacentHTML('beforeend', '<hr><div role="group" class="card-popovers btn-group"></div>'); | |
popoverRow = studioCard.querySelector('.card-popovers'); | |
}; | |
const newElems = await getStudioData(studioId).then(summarizeSceneData).then((data) => makeIcons({name, id: studioId, ...data})); | |
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:%22studios%22,%22value%22:(%22items%22:%5B(%22id%22:%22${id}%22,%22label%22:%22${name}%22)%5D,%22depth%22:-1),%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 getStudioData(id) { | |
let query = JSON.stringify( | |
{ | |
"query": "query FindScenes($scene_filter: SceneFilterType) { findScenes(scene_filter: $scene_filter, filter: { per_page: -1 }) { scenes { o_counter rating100 } } }", | |
"variables": { | |
"scene_filter": { | |
"studios": { | |
"modifier": "INCLUDES", | |
"value": [id], | |
"depth": -1, // Remove this if you do not want to summarize data for all child studios | |
} | |
} | |
} | |
}); | |
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'); | |
return reject(`Query for '${id}' failed: ${errors}`); | |
} | |
resolve(res.response.data.findScenes); | |
} catch (error) { | |
reject(error.message); | |
} | |
} | |
}); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I know you made this for your own use only, but now you've let the cat out of the bag. 😁
Would be neat if you modified the script and it's corresponding performers script in four ways
<span class="name-icons">
element with the other icon buttonsp.s. this really should be built in to stash. very elegant idea and presentation.