// ==UserScript==
// @name Geoguessr change Avatar to Pin (beta)
// @description Adds the competitive rating to usernames
// @version 1.0.1
// @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) \\
// PIN = PROFILE PICTURE \\
//=====================================================================================\\
const PIN_IN_OWN_PROFILE = true;
const PIN_IN_OTHERS_PROFILE = true;
const PIN_IN_DUELS_MATCHMAKING = true;
const PIN_IN_BR_MATCHMAKING = true;
const NO_AVATARS_END_OF_DUEL = true;
const PIN_IN_TEAM_DUEL_PRIVATE_LOBBY = true;
//Beta: still working on it, any questons or feedback -> Discord joniber#5011
//=====================================================================================\\
// 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;
let av = null;
let index = 0;
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 wrapperEndOfDuels() {
return `<div class="profile-header_avatar__y6vsp 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 logCode(event) {
if (event.key === 'o' || event.key === 'O') {
var htmlCode = document.getElementById('preroll');
var htmlCode1 = document.getElementById('overlay-portal-destination');
console.log(htmlCode);
console.log(htmlCode1);
}
}
// Eventlistener hinzufügen, um auf Tastendruck zu reagieren
document.addEventListener('keydown', logCode);
function changeAvatarToPin(link, avatarToRemove) {
if (!link.querySelector(`.${USER_PIN_CLASS}`)) {
if (link != null || link != '') {
let destination = null
if (avatarToRemove == link){
link.querySelector('.styles_image__8M_kp').style="display: none"
destination = link
}
else{
link.querySelector('.player-card_lobbyCardInner__G_xzy').firstChild.remove()
destination = link.querySelector('.player-card_lobbyCardInner__G_xzy')
}
destination.insertAdjacentHTML('afterbegin', wrapperDuels());
destination = link.querySelector('.profile-header_avatarWrapper__5_jDA.up__');
destination.insertAdjacentHTML('afterbegin', wrapper());
destination = link.querySelector('.avatar_titleAvatarImage__A51Dx.up__')
destination.insertAdjacentHTML('beforeend', profilePicture());
const pin = destination.lastChild
let id = '/me/profile'
if(link.querySelector('.player-card_userLink__HhoDo') != null){
id = link.querySelector('.player-card_userLink__HhoDo').href
}
fillPin(pin, retrieveIdFromLink(id));
destination = link.querySelector('.styles_rectangle___6gqv.up__');
destination.insertAdjacentHTML('beforeend',levelBorder());
const lvl = destination.lastChild
fillLvl(lvl, retrieveIdFromLink(id));
}
}
}
// function changeAvatarInGame(link) {
// if(!document.querySelector(`.${USER_PIN_CLASS}`)){
// let destination = link
// destination.insertAdjacentHTML("beforeEnd", wrapperDuels());
// 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.firstChild.remove();
let destination = avatar_end_of_duel_wrapper
destination.style = "height: fit-content";
destination.insertAdjacentHTML('afterbegin', wrapperDuels())
destination = document.querySelector('.profile-header_avatarWrapper__5_jDA.up__')
destination.insertAdjacentHTML('afterbegin', wrapper());
document.querySelector('.profile-header_avatar__y6vsp').style = "display:flex; justify-content:center; align-items:center"
document.querySelector('.avatar_titleAvatar__0pdL9').style="width:20rem"
destination = document.querySelector('.avatar_titleAvatarImage__A51Dx.up__')
destination.insertAdjacentHTML('beforeend', profilePicture());
const pin = destination.lastChild
let id = '/me/profile'
if(document.querySelectorAll('.anchor_variantUnderline__8wlJr')[0] != null){
id = document.querySelectorAll('.anchor_variantUnderline__8wlJr')[0].href
}
fillPin(pin, retrieveIdFromLink(id));
destination = document.querySelector('.styles_rectangle___6gqv.up__');
destination.insertAdjacentHTML('beforeend',levelBorder());
const lvl = destination.lastChild
fillLvl(lvl, retrieveIdFromLink(id));
}
}
if (PIN_IN_DUELS_MATCHMAKING) {
if (player1 == null) {
player1 = document.querySelectorAll('.lobby_avatarContainer__kN2RK')[0];
if (player1 != null) {
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;
fillLvl(lvl, retrieveIdFromLink(id));
}
}
if (player2 == null) {
player2 = document.querySelectorAll('.lobby_avatarContainer__kN2RK')[1];
if (player2 != null) {
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;
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;
console.log('br mode')
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;
console.log('duels mode');
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;
console.log('normal mode');
} else if (inDuels && !document.querySelector('.game_hud__fhdo5')) {
inDuels = false;
console.log('normal mode');
}
if (inBattleRoyale || inDuels) {
return;
console.log('normal mode');
}
if (isProfile()) {
if (!PIN_IN_OWN_PROFILE && isOwnProfile()) {
return;
console.log('normal mode');
}
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_TEAM_DUEL_PRIVATE_LOBBY){
for (const link of document.querySelectorAll('.team-player-card_lobbyCardInner__fT8A_')){
changeAvatarToPin(link, link);
}
}
if (PIN_IN_BR_MATCHMAKING) {
// battle royale matchmaking
//.player-card_lobbyCard___OpUa
//.player-card_lobbyCardInner__G_xzy
for (const link of document.querySelectorAll('.player-card_root__NvK_s')) {
changeAvatarToPin(link, 'player-card_lobbyCardInner__G_xzy');
}
}
if (isDuels() && PIN_IN_DUELS_MATCHMAKING) {
if (!document.querySelector(`#${USER_PIN_ID}`)) {
if (av == null) {
av = document.querySelector('.lobby_avatarContainer__kN2RK');
}
if (av != null) {
av.children[0].remove();
let destination_dw = av;
destination_dw.insertAdjacentHTML('afterBegin', wrapperDuels());
destination_dw = document.querySelector(
'.profile-header_avatarWrapper__5_jDA.up__'
);
destination_dw.insertAdjacentHTML('afterBegin', wrapper());
destination_dw = document.querySelector('.avatar_titleAvatarImage__A51Dx.up__');
destination_dw.insertAdjacentHTML('beforeEnd', profilePicture1());
const pin = destination_dw.lastChild;
let id = 'https://www.geoguessr.com/me/profile';
fillPin(pin, retrieveIdFromLink(id));
destination_dw = document.querySelector('.styles_rectangle___6gqv.up__');
destination_dw.insertAdjacentHTML('beforeEnd', levelBorder1());
const lvl = destination_dw.lastChild;
fillLvl(lvl, retrieveIdFromLink(id));
}
if (av != null) {
av = null;
}
}
}
}
//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);