mirror of
https://codeberg.org/vlw/stadia-avatar.git
synced 2025-09-13 15:23:40 +02:00
Custom avatars now appear on `/profile/` pages. Thanks to u/ChristopherKlay on Reddit for suggesting querySelector wildcards. Added some comments.
140 lines
No EOL
4.4 KiB
JavaScript
140 lines
No EOL
4.4 KiB
JavaScript
// ==UserScript==
|
|
// @name Stadia Avatars
|
|
// @namespace https://victorwesterlund.com/
|
|
// @version 1.0
|
|
// @description victorWesterlund/stadia-avatar
|
|
// @author VictorWesterlund
|
|
// @match https://stadia.google.com/*
|
|
// @grant none
|
|
// @noframes
|
|
// ==/UserScript==
|
|
|
|
(function() {
|
|
'use strict';
|
|
|
|
const stadiaAvatar = new URL("https://api.victorwesterlund.com/stadia-avatar/get");
|
|
const gravatar = new URL("https://www.gravatar.com/");
|
|
|
|
/*
|
|
G: Suitable for display on all websites with any audience type.
|
|
PG: May contain rude gestures, provocatively dressed individuals, the lesser swear words, or mild violence.
|
|
R: May contain such things as harsh profanity, intense violence, nudity, or hard drug use.
|
|
X: May contain hardcore sexual imagery or extremely disturbing violence.
|
|
*/
|
|
gravatar.searchParams.set("rating","G");
|
|
|
|
// Stylesheet for Stadia Avatars
|
|
class StadiaAvatarCSS {
|
|
|
|
constructor() {
|
|
this.sheet = null;
|
|
this.createStylesheet();
|
|
}
|
|
|
|
createStylesheet() {
|
|
const style = document.createElement("style");
|
|
style.setAttribute("data-stadia-avatars","");
|
|
style.setAttribute("data-late-css","");
|
|
|
|
document.head.appendChild(style);
|
|
this.sheet = style.sheet;
|
|
}
|
|
|
|
// Serialized group of selectors based on context
|
|
selectors(group,id = false) {
|
|
switch(group) {
|
|
case "me": return `
|
|
c-wiz[data-p*="${id}"] .XZRzG,
|
|
.OGtUWe .dOyvbe,
|
|
.ksZYgc,
|
|
.rybUIf
|
|
`;
|
|
case "friends": return `
|
|
div[jsdata*="${id}"] .PwtJse,
|
|
c-wiz[data-p*="${id}"] .XZRzG,
|
|
c-wiz[data-p*="${id}"] .drvCDc,
|
|
c-wiz[data-p*="${id}"] .vLPc0c,
|
|
.Y1rZWd[data-player-id="${id}"] .Fnd1Pd,
|
|
.Y1rZWd[data-playerid="${id}"] .Fnd1Pd,
|
|
.w2Sl7c[data-playerid="${id}"] .drvCDc
|
|
`;
|
|
}
|
|
}
|
|
|
|
add(selectors,avatar) {
|
|
this.sheet.insertRule(`${selectors} { background-image: url(${avatar}) !important; }`);
|
|
}
|
|
|
|
}
|
|
|
|
const avatars = new StadiaAvatarCSS();
|
|
|
|
// ----
|
|
|
|
// Return the player ID attribute of an element
|
|
const getID = (target) => {
|
|
const id = target.getAttribute("data-player-id") ?? target.getAttribute("data-playerid");
|
|
return id;
|
|
}
|
|
|
|
// Fetch Gravatar hash from endpoint
|
|
async function getStadiaAvatar(playerID) {
|
|
stadiaAvatar.searchParams.set("userID",playerID);
|
|
|
|
const response = await fetch(stadiaAvatar);
|
|
return response.json();
|
|
}
|
|
|
|
// Fetch avatar and append to stylesheet
|
|
function replaceWithGravatar(group,playerID) {
|
|
getStadiaAvatar(playerID).then(response => {
|
|
if(response.status !== "OK") {
|
|
return false;
|
|
}
|
|
|
|
gravatar.pathname = "/avatar/" + response.avatar; // Append Gravatar hash
|
|
avatars.add(avatars.selectors(group,playerID),gravatar); // Add style override by group
|
|
}).catch(
|
|
// Ignore missing avatars
|
|
);
|
|
}
|
|
|
|
// ----
|
|
|
|
replaceWithGravatar("me",getID(document.querySelector("[jsname='HiaYvf']"))); // Append styles for my avatar
|
|
|
|
function updateFamily(group,wrapper) {
|
|
for(const element of wrapper) {
|
|
const id = getID(element);
|
|
if(!id) {
|
|
continue;
|
|
}
|
|
|
|
replaceWithGravatar(group,id);
|
|
}
|
|
}
|
|
|
|
let timeout = null;
|
|
|
|
// Fetch friend avatars
|
|
const friendsList = (mutation,observer) => {
|
|
clearTimeout(timeout);
|
|
|
|
// Wait until subtree stops mutating (on initial load)
|
|
timeout = setTimeout(() => {
|
|
let elements = [];
|
|
elements = Array.prototype.concat.apply(elements,document.querySelector("[jsaction='JIbuQc:mbLu7b']").children); // Friends list
|
|
elements = Array.prototype.concat.apply(elements,document.querySelector("[jsname='FhFdCc']").children); // Messages list
|
|
|
|
updateFamily("friends",elements);
|
|
},700);
|
|
}
|
|
|
|
const friendsMenu = document.querySelector("[jsname='TpfyL']");
|
|
const friends = new MutationObserver(friendsList);
|
|
friends.observe(friendsMenu,{
|
|
childList: true,
|
|
subtree: true
|
|
});
|
|
|
|
})(); |