mirror of
https://codeberg.org/vlw/stadia-avatar.git
synced 2025-09-13 23:23:40 +02:00
Moved userscripts to repo root.
Added client userscript in a "proof of concept" state of readiness. The bot userscript is neat and tidy, it works very well too. Added additional comments.
This commit is contained in:
parent
b586850c26
commit
c90b64b671
5 changed files with 135 additions and 46 deletions
|
@ -6,7 +6,7 @@
|
||||||
"host" => "",
|
"host" => "",
|
||||||
"username" => "",
|
"username" => "",
|
||||||
"password" => "",
|
"password" => "",
|
||||||
"database" => "stadia_avatars"
|
"database" => "stadia_avatars" // 'setup-db.sql' contains the db structure
|
||||||
];
|
];
|
||||||
|
|
||||||
protected static $instance;
|
protected static $instance;
|
||||||
|
@ -44,6 +44,7 @@
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DB interface for manipulating Stadia Avatar
|
||||||
class StadiaAvatarDB extends DBConnector {
|
class StadiaAvatarDB extends DBConnector {
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
|
@ -64,6 +65,7 @@
|
||||||
return $this->sql->exec_query($SQL);
|
return $this->sql->exec_query($SQL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the value of column 'avatar'
|
||||||
public function get_avatar($user_id) {
|
public function get_avatar($user_id) {
|
||||||
$SQL = "SELECT `userid`, `avatar` FROM `avatars` WHERE `userid` = '${user_id}'";
|
$SQL = "SELECT `userid`, `avatar` FROM `avatars` WHERE `userid` = '${user_id}'";
|
||||||
$query = $this->sql->exec_query($SQL);
|
$query = $this->sql->exec_query($SQL);
|
||||||
|
@ -73,6 +75,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Insert or update user avatar
|
||||||
public function set_avatar($user_id,$avatar) {
|
public function set_avatar($user_id,$avatar) {
|
||||||
if(!$this->get_avatar($user_id)) {
|
if(!$this->get_avatar($user_id)) {
|
||||||
http_response_code("201");
|
http_response_code("201");
|
||||||
|
|
|
@ -1,10 +1,21 @@
|
||||||
|
// ==UserScript==
|
||||||
|
// @name Stadia Avatars - Bot
|
||||||
|
// @namespace https://victorwesterlund.com/
|
||||||
|
// @version 1.0
|
||||||
|
// @description https://github.com/VictorWesterlund/stadia-avatar
|
||||||
|
// @author VictorWesterlund
|
||||||
|
// @match https://stadia.google.com/*
|
||||||
|
// @grant none
|
||||||
|
// @noframes
|
||||||
|
// ==/UserScript==
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/* The Stadia Service Worker "mgsw.js" acts like a proxy and rejects requests to the StadiaAvatar endpoint.
|
/* The Stadia Service Worker "mgsw.js" acts like a proxy and rejects requests to the StadiaAvatar endpoint.
|
||||||
Enable the "Bypass for network" toggle in DevTools->Application->Service Workers to circumvent this issue. */
|
Enable the "Bypass for network" toggle in DevTools->Application->Service Workers to circumvent this issue. */
|
||||||
|
|
||||||
const endpoint = "";
|
const endpoint = "https://api.victorwesterlund.com/stadia-avatar/update";
|
||||||
const sharedSecret = ""; // Key to update the database
|
const sharedSecret = ""; // Key to update the database
|
||||||
|
|
||||||
const className = {
|
const className = {
|
||||||
|
@ -67,7 +78,7 @@
|
||||||
console.log("StadiaAvatar bot started.");
|
console.log("StadiaAvatar bot started.");
|
||||||
},
|
},
|
||||||
stop: () => {
|
stop: () => {
|
||||||
interval = null
|
interval = null;
|
||||||
console.log("StadiaAvatar bot stopped.");
|
console.log("StadiaAvatar bot stopped.");
|
||||||
}
|
}
|
||||||
}
|
}
|
118
userscript-client.js
Normal file
118
userscript-client.js
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
// ==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 ".ksZYgc, .rybUIf";
|
||||||
|
case "friends": return `.Y1rZWd[data-playerid="${id}"] .Fnd1Pd, .w2Sl7c[data-playerid="${id}"] .drvCDc`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
add(selectors,avatar) {
|
||||||
|
this.sheet.insertRule(`${selectors} { background-image: url(${avatar}) !important; }`);
|
||||||
|
console.log(`${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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 => {
|
||||||
|
gravatar.pathname = "/avatar/" + response.avatar; // Append Gravatar hash
|
||||||
|
avatars.add(avatars.selectors(group,playerID),gravatar); // Add style override by group
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----
|
||||||
|
|
||||||
|
replaceWithGravatar("me",getID(document.querySelector("[jsname='HiaYvf']")));
|
||||||
|
|
||||||
|
function updateFamily(group,wrapper) {
|
||||||
|
for(const element of wrapper) {
|
||||||
|
const id = getID(element);
|
||||||
|
if(!id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
replaceWithGravatar(group,id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let timeout = null;
|
||||||
|
|
||||||
|
const friendsList = (mutation,observer) => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
|
||||||
|
timeout = setTimeout(() => {
|
||||||
|
const friends = document.querySelector("[jsname='FhFdCc']").children;
|
||||||
|
const messages = document.querySelector("[jsname='FhFdCc']").children;
|
||||||
|
|
||||||
|
updateFamily("friends",messages);
|
||||||
|
},700);
|
||||||
|
}
|
||||||
|
|
||||||
|
const friendsMenu = document.querySelector("[jsname='TpfyL']");
|
||||||
|
const friends = new MutationObserver(friendsList);
|
||||||
|
friends.observe(friendsMenu,{
|
||||||
|
childList: true,
|
||||||
|
subtree: true
|
||||||
|
});
|
||||||
|
|
||||||
|
})();
|
|
@ -1,11 +0,0 @@
|
||||||
// ==UserScript==
|
|
||||||
// @name Stadia Avatars
|
|
||||||
// @namespace https://victorwesterlund.com/
|
|
||||||
// @version 0.1
|
|
||||||
// @description try to take over the world!
|
|
||||||
// @author VictorWesterlund
|
|
||||||
// @match https://stadia.google.com/*
|
|
||||||
// @grant none
|
|
||||||
// @require file://C:\path\to\userscript.user.js
|
|
||||||
// @noframes
|
|
||||||
// ==/UserScript==
|
|
|
@ -1,32 +0,0 @@
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
function getElementByJSname(name) {
|
|
||||||
return document.querySelector(`[jsname="${name}"]`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const myID = () => {
|
|
||||||
let element = getElementByJSname("HiaYvf");
|
|
||||||
return element.getAttribute("data-player-id");
|
|
||||||
}
|
|
||||||
|
|
||||||
function locationChanged() {
|
|
||||||
switch(window.location.pathname) {
|
|
||||||
case "/home": console.log("home"); break;
|
|
||||||
case "/settings": console.log("settings"); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let currentLocation = window.location.href;
|
|
||||||
|
|
||||||
// Poll window.location.href for changes
|
|
||||||
let poll = setInterval(() => {
|
|
||||||
if(window.location.href != currentLocation) {
|
|
||||||
currentLocation = window.location.href;
|
|
||||||
locationChanged();
|
|
||||||
}
|
|
||||||
},500);
|
|
||||||
|
|
||||||
locationChanged();
|
|
||||||
})();
|
|
Loading…
Add table
Reference in a new issue