你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式
你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式
(我已經安裝了使用者樣式管理器,讓我安裝!)
// ==UserScript==
// @name Geoguessr change Avatar to Pin
// @description Adds the competitive rating to usernames
// @version 1.0.0
// @license MIT
// @author joniber#5011
// @namespace
// @match https://www.geoguessr.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=geoguessr.com
// @namespace https://greasyfork.org/users/1072330
// ==/UserScript==
//=====================================================================================\\
// change these values however you like (make sure to hit ctrl+s afterwards) \\
//=====================================================================================\\
const PIN_IN_OWN_PROFILE = true;
// ^^^^^ set this to 'false' if you don't want to display rating in the friends tab
const PIN_IN_OTHERS_PROFILE = true;
// ^^^^ set this to 'false' if you don't want to display rating in leaderboards
const PIN_IN_DUELS_MATCHMAKING = true;
// ^^^^ set this to 'false' if you don't want to display rating in matchmaking lobbies
const PIN_IN_BR_MATCHMAKING = true;
// ^^^^ set this to 'false' if you don't want to display rating ingame
const NO_AVATARS_END_OF_DUEL = true;
//=====================================================================================\\
// don't edit anything after this point unless you know what you're doing \\
//=====================================================================================\\
const GEOGUESSR_USER_ENDPOINT = 'https://geoguessr.com/api/v3/users';
const SCRIPT_PREFIX = 'up__';
const USER_PIN_CLASS = SCRIPT_PREFIX + 'userPin';
const USER_PIN_ID = SCRIPT_PREFIX + 'profilePin';
let player1 = null
let player2 = null
const OBSERVER_CONFIG = {
characterDataOldValue: false,
subtree: true,
childList: true,
characterData: false,
};
const ERROR_MESSAGE = (wrong) => '${wrong}';
function pathMatches(path) {
return location.pathname.match(new RegExp(`^/(?:[^/]+/)?${path}$`));
}
function wrapperDuels(){
return `<div class="profile-header_avatarWrapper__5_jDA up__"></div>`
}
function wrapper(){
return `<div class="profile-header_avatar__y6vsp"><div class="avatar_titleAvatar__0pdL9"><div class="styles_rectangle___6gqv up__" style="padding-top: 100%;"><div class="avatar_titleAvatarImage__A51Dx up__"></div></div></div></div>`
}
function profilePicture(){
return `<img class="styles_image__8M_kp ${USER_PIN_CLASS}" loading="auto" style="object-fit:cover;">`
}
function profilePicture1(){
return `<img class="styles_image__8M_kp" id="${USER_PIN_ID}" loading="auto" style="object-fit:cover;">`
}
function levelBorder(){
return `<picture class="avatar_titleAvatarFrame__AT57_ ${USER_PIN_CLASS}"><source type="image/avif"><source type="image/webp"><img class="avatar_titleAvatarFrame__AT57_"></picture>`
}
function levelBorder1(){
return `<picture class="avatar_titleAvatarFrame__AT57_" id="${USER_PIN_ID}"><source type="image/avif"><source type="image/webp"><img class="avatar_titleAvatarFrame__AT57_"></picture>`
}
async function fillPin(pin, userId) {
const userData = await getUserData(userId);
const pinURL = userData.pin.url;
pin.setAttribute('src', "/images/auto/144/144/ce/0/plain/" + pinURL)
}
async function fillLvl(lvl, userId){
const userData = await getUserData(userId);
const level = roundToNearest10(userData.progress.level)
lvl.firstChild.setAttribute('srcset', "/static/avatars/tiers/low-quality/tier-" + level + ".avif")
lvl.children[1].setAttribute('srcset', "/static/avatars/tiers/low-quality/tier-" + level + ".webp")
lvl.lastChild.setAttribute('src', "/static/avatars/tiers/low-quality/tier-" + level + ".png")
}
function changeAvatarToPin(link) {
if(!document.querySelector(`.${USER_PIN_CLASS}`)){
document.querySelector('.profile-header_fullBodyAvatar___LRnw').remove();
let destination = document.querySelector(".profile-header_avatarWrapper__5_jDA")
destination.insertAdjacentHTML("beforeend", wrapper());
destination = document.querySelector('.avatar_titleAvatarImage__A51Dx.up__')
destination.insertAdjacentHTML("beforeend", profilePicture())
const pin = destination.lastChild
fillPin(pin, retrieveIdFromLink(location.href))
destination = document.querySelector(".styles_rectangle___6gqv.up__")
destination.insertAdjacentHTML("beforeend", levelBorder())
const lvl = destination.lastChild
fillLvl(lvl, retrieveIdFromLink(location.href))
}
}
function changeAvatarInGame(link) {
if(!document.querySelector(`.${USER_PIN_CLASS}`)){
document.querySelector('.profile-header_fullBodyAvatar___LRnw').remove();
let destination = document.querySelector(".profile-header_avatarWrapper__5_jDA")
destination.insertAdjacentHTML("beforeend", wrapper());
destination = document.querySelector('.avatar_titleAvatarImage__A51Dx.up__')
destination.insertAdjacentHTML("beforeend", profilePicture())
const pin = destination.lastChild
fillPin(pin, retrieveIdFromLink(location.href))
destination = document.querySelector(".styles_rectangle___6gqv.up__")
destination.insertAdjacentHTML("beforeend", levelBorder())
const lvl = destination.lastChild
fillLvl(lvl, retrieveIdFromLink(location.href))
}
}
let inBattleRoyale = false;
let inDuels = false;
let lastOpenedMapHighscoreTab = 0;
function onMutationsBr(mutations, observer) {
for(let q in document.getElementsByTagName('canvas')){
q.remove();
}
if (PIN_IN_BR_MATCHMAKING) {
// battle royale distance
for (const link of document.querySelectorAll('.distance-player-list_name__fPSwC a')) {
changeAvatarInGame(link);
}
// battle royale countries
for (const link of document.querySelectorAll(
'.countries-player-list_playerName__g4tnM a'
)) {
changeAvatarInGame(link);
}
}
}
function onMutationsDuels(mutations, observer) {
// for(let i = 0; i<2; i++){
// let q = document.getElementsByTagName('canvas')[i];
// if(q!=null){
// q.remove();
// }
// }
if(NO_AVATARS_END_OF_DUEL){
let avatar_end_of_duel_wrapper = document.querySelector('.game-finished_avatarContainer__S63IS')
if (avatar_end_of_duel_wrapper != null){
avatar_end_of_duel_wrapper.style.display="none";
}
}
if (PIN_IN_DUELS_MATCHMAKING) {
if(player1 == null){
player1 = document.querySelectorAll('.lobby_avatarContainer__kN2RK')[0];
if(player1 != null){
console.log("--------------Player1------------")
player1.children[0].firstChild.remove()
player1.children[0].remove()
let destination1 = player1
destination1.insertAdjacentHTML('afterBegin', wrapperDuels())
destination1 = document.querySelector('.profile-header_avatarWrapper__5_jDA.up__')
destination1.insertAdjacentHTML('afterBegin', wrapper())
destination1 = document.querySelector('.avatar_titleAvatarImage__A51Dx.up__')
destination1.insertAdjacentHTML("beforeEnd", profilePicture())
const pin = destination1.lastChild
let id = player1.lastChild.firstChild.href
fillPin(pin, retrieveIdFromLink(id))
destination1 = document.querySelector(".styles_rectangle___6gqv.up__")
destination1.insertAdjacentHTML("beforeEnd", levelBorder())
const lvl = destination1.lastChild
console.log(player1)
console.log(id)
fillLvl(lvl, retrieveIdFromLink(id))
}
}
if(player2 == null){
player2 = document.querySelectorAll('.lobby_avatarContainer__kN2RK')[1];
if(player2 != null){
console.log("--------------Player2------------")
player2.children[0].firstChild.remove()
player2.children[0].remove()
let destination2 = player2
destination2.insertAdjacentHTML('afterBegin', wrapperDuels())
destination2 = document.querySelectorAll('.profile-header_avatarWrapper__5_jDA.up__')[1];
destination2.insertAdjacentHTML('afterBegin', wrapper())
destination2 = document.querySelectorAll('.avatar_titleAvatarImage__A51Dx.up__')[1];
destination2.insertAdjacentHTML("beforeEnd", profilePicture())
const pin1 = destination2.lastChild
let id1 = player2.lastChild.firstChild.href
fillPin(pin1, retrieveIdFromLink(id1))
destination2 = document.querySelectorAll(".styles_rectangle___6gqv.up__")[1]
destination2.insertAdjacentHTML("beforeEnd", levelBorder())
const lvl1 = destination2.lastChild
console.log(player2)
console.log(id1)
fillLvl(lvl1, retrieveIdFromLink(id1))
}
}
if(player1 != null && player2 != null){
player1 = null;
player2 = null;
}
}}
function onMutationsStandard(mutations, observer) {
if (isBattleRoyale() && document.querySelector('.game_hud__h3YxY ul') && !inBattleRoyale) {
inBattleRoyale = true;
const brObserver = new MutationObserver(onMutationsBr);
brObserver.observe(document.querySelector('.game_hud__h3YxY ul'), OBSERVER_CONFIG);
} else if (isDuels() && document.querySelector('.game_hud__fhdo5') && !inDuels) {
inDuels = true;
const duelsObserver = new MutationObserver(onMutationsDuels);
duelsObserver.observe(document.querySelector('.game_hud__fhdo5'), OBSERVER_CONFIG);
} else if (inBattleRoyale && !document.querySelector('.game_hud__h3YxY ul')) {
inBattleRoyale = false;
} else if (inDuels && !document.querySelector('.game_hud__fhdo5')) {
inDuels = false;
}
if (inBattleRoyale || inDuels) {
return;
}
if (isProfile() ) {
if(!PIN_IN_OWN_PROFILE && isOwnProfile()){
return
}
if(!PIN_IN_OTHERS_PROFILE && isOtherProfile()){
return
}
if(!document.querySelector(`#${USER_PIN_ID}`)){
document.querySelector('.profile-header_fullBodyAvatar___LRnw').remove();
let destination = document.querySelector(".profile-header_avatarWrapper__5_jDA")
destination.insertAdjacentHTML("beforeend", wrapper());
destination = document.querySelector('.avatar_titleAvatarImage__A51Dx.up__')
destination.insertAdjacentHTML("beforeend", profilePicture1())
const pin = destination.lastChild
fillPin(pin, retrieveIdFromLink(location.href))
destination = document.querySelector(".styles_rectangle___6gqv.up__")
destination.insertAdjacentHTML("beforeend", levelBorder1())
const lvl = destination.lastChild
fillLvl(lvl, retrieveIdFromLink(location.href))
}
}
if (PIN_IN_BR_MATCHMAKING) {
// battle royale matchmaking
for (const link of document.querySelectorAll('.player-card_root__NvK_s')) {
changeAvatarToPin(link);
}
}
}
//helpfunctions
function roundToNearest10(number) {
return Math.ceil(number / 10) * 10;
}
function retrieveIdFromLink(link) {
if (link.endsWith('/me/profile')) {
const data = document.querySelector('#__NEXT_DATA__').text;
const json = JSON.parse(data);
return json.props.middlewareResults[1].account.user.userId;
}
return link.split('/').at(-1);
}
function isOtherProfile() {
return pathMatches('user/.+');
}
function isOwnProfile() {
return pathMatches('me/profile');
}
function isProfile() {
return isOwnProfile() || isOtherProfile();
}
function isBattleRoyale() {
return pathMatches('battle-royale/.+');
}
function isDuels() {
return pathMatches('duels/.+');
}
async function getUserData(id) {
const response = await fetch(`${GEOGUESSR_USER_ENDPOINT}/${id}`);
const json = await response.json();
return json;
}
const observer = new MutationObserver(onMutationsStandard);
observer.observe(document.body, OBSERVER_CONFIG);