Geoguessr rating displayer

Adds the competitive rating to usernames

目前为 2023-08-26 提交的版本。查看 最新版本

// ==UserScript==
// @name         Geoguessr rating displayer
// @description  Adds the competitive rating to usernames
// @version      1.1.0
// @license      MIT
// @author       joniber
// @namespace
// @match        https://www.geoguessr.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=geoguessr.com
// @namespace https://gf.qytechs.cn/users/1072330
// ==/UserScript==

//=====================================================================================\\
//    change these values however you like (make sure to hit ctrl+s afterwards)        \\
//=====================================================================================\\



const RATING_IN_FRIENDS_TAB = true;
//                            ^^^^^ set this to 'false' if you don't want to display rating in the friends tab
const RATING_IN_LEADERBOARD = true;
//                            ^^^^  set this to 'false' if you don't want to display rating in leaderboards
const RATING_IN_MATCHMAKING = true;
//                            ^^^^  set this to 'false' if you don't want to display rating in matchmaking lobbies
const RATING_IN_INGAME_PAGE = true;
//                            ^^^^  set this to 'false' if you don't want to display rating ingame

const RATING_COLOR_CHANGE = true;
//                          ^^^^ set this to 'false' if you don't want to change the color based on the ranking

const RATING_IN_BREAKDOWN = true;
//                          ^^^^ set this to 'false' if you don't want to see rating in the breakdown menu

const RATING_IN_SUGGESTIONS = true;
//                           ^^^^ set this to 'false' if you don't want to see rating in the friend suggestion list

//=====================================================================================\\
//  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 = 'ur__';
const PROFIlE_RATING_ID = SCRIPT_PREFIX + 'profileRating';
const USER_RATING_CLASS = SCRIPT_PREFIX + 'userRating';

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 ratingText() {
    return `<p
        class="${USER_RATING_CLASS}"
        style="margin-left: .25rem; margin-right:.25rem; margin-top:0px; display: none;"
        onerror="this.style.display = 'none'"
    ></p>`;
}

let flag = true
let flag1 = false

async function fillRating(ratingNumber, userId) {
    const userData = await getUserData(userId);
    const rating = userData.competitive.rating;

    ratingNumber.innerHTML = rating;
    let color;
    if (RATING_COLOR_CHANGE) {
        if (rating < 450) {
            color = '#ba682e';
        } else if (rating < 650) {
            color = '#8e8e8e';
        } else if (rating < 850) {
            color = '#e8ac06';
        } else if (rating < 1100) {
            color = '#e04781';
        } else if (rating >= 1100) {
            color = '#a994e3';
        }

        ratingNumber.style.color = color;
    }
    ratingNumber.style.display = 'block';
}

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;
}

function addRatingToUsername(link) {
    if (!link.querySelector(`.${USER_RATING_CLASS}`)) {
        const destination = link.querySelector('.user-nick_nickWrapper__8Tnk4');
        destination.insertAdjacentHTML('beforeend', ratingText());
        const ratingNumber = destination.lastChild;
        if(destination.children[2]){
            destination.insertBefore(
                ratingNumber,
                destination.children[2]
            );

        }

        fillRating(ratingNumber, retrieveIdFromLink(link.href));
    }
}

function addRatingToIngameUsername(link) {
    if (!link.querySelector(`.${USER_RATING_CLASS}`)) {
        const destination = link.querySelector('span');
        destination.style.display = 'flex';
        destination.innerHTML += '&nbsp;';
        destination.insertAdjacentHTML('beforeend', ratingText());
        const ratingNumber = destination.lastChild;
        if (destination.childElementCount == 4) {
            destination.insertBefore(
                ratingNumber,
                ratingNumber.previousElementSibling.previousElementSibling
            );
        } else if (destination.childElementCount > 2) {
            destination.insertBefore(ratingNumber, ratingNumber.previousElementSibling);
        }

        fillRating(ratingNumber, retrieveIdFromLink(link.href));
    }
}

let inBattleRoyale = false;
let inDuels = false;
let lastOpenedMapHighscoreTab = 0;

function onMutationsBr(mutations, observer) {
    if (RATING_IN_INGAME_PAGE) {
        // battle royale distance
        for (const link of document.querySelectorAll('.distance-player-list_name__fPSwC a')) {
            addRatingToIngameUsername(link);
        }

        // battle royale countries
        for (const link of document.querySelectorAll(
            '.countries-player-list_playerName__g4tnM a'
        )) {
            addRatingToIngameUsername(link);
        }
    }
}

function onMutationsDuels(mutations, observer) {
    if (RATING_IN_INGAME_PAGE) {
        // duels
        const hud = document.querySelector('.hud_root__RY5pu');

        const firstPlayerLink = hud.firstChild?.querySelector('.health-bar_player__9j0Vu a');
        if (firstPlayerLink) {
            addRatingToUsername(firstPlayerLink);
        }

        const secondPlayerLink = hud.lastChild?.querySelector('.health-bar_player__9j0Vu a');
        if (secondPlayerLink) {
            if (addRatingToUsername(secondPlayerLink, 'afterbegin')) {
                const name = secondPlayerLink.querySelector('.user-nick_nick__y4VIt');
                name.innerHTML = '&nbsp;' + name.innerHTML;
            }
        }

        if (document.querySelector('.round-score_container__s6qNg')) {
            const leftLink = document.querySelector(
                '.round-score_healthLeft__TT8Kk .health-bar_player__9j0Vu a'
            );
            addRatingToUsername(leftLink);
            const rightLink = document.querySelector(
                '.round-score_healthRight__qgBbv .health-bar_player__9j0Vu a'
            );
            if (addRatingToUsername(rightLink, 'afterbegin')) {
                const name = rightLink.querySelector('.user-nick_nick__y4VIt');
                name.innerHTML = '&nbsp;' + name.innerHTML;
            }
        }
    }
}

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 (RATING_IN_FRIENDS_TAB) {
        // friends tab
        for (const link of document.querySelectorAll('.chat-friend_name__6GRE_ a')) {
            addRatingToUsername(link);
        }
    }

    if (RATING_IN_LEADERBOARD) {
        // generic leaderboard

        for (let link of document.querySelectorAll('.leaderboard_row___vctV')) {
            if(link.classList.contains('leaderboard_rowColumnCount3__C_mSL')){
                return;
            }
            else{
                if(link.querySelector('.leaderboard_columnContent__yA6b_.leaderboard_alignStart__KChAa a')){
                    addRatingToUsername(link.querySelector('.leaderboard_columnContent__yA6b_.leaderboard_alignStart__KChAa a'));
                }
            }
        }

        // map highscore leaderboard
        let tabSwitch = document.querySelector('.map-highscore_switchContainer__wCDRH div');
        if (tabSwitch) {
            const openedMapHighscoreTab =
                  +tabSwitch.firstChild.firstChild.classList.contains('switch_hide__OuYfZ');
            if (openedMapHighscoreTab != lastOpenedMapHighscoreTab) {
                lastOpenedMapHighscoreTab = openedMapHighscoreTab;
                for (const link of document.querySelectorAll(
                    '.map-highscore_userWrapper__aHpCF a'
                )) {
                    const rating = link.querySelector(`.${USER_RATING_CLASS}`);
                    if (rating) {
                        rating.remove();
                    }
                }
            }
            let tabSwitch1 = document.querySelector('.map-highscore_switchContainer__wCDRH');
            const openFriendHighscoreTab = tabSwitch1.lastChild.lastChild
            if(openFriendHighscoreTab){
                if(openFriendHighscoreTab.firstChild.classList.contains('switch_show__OGOFd') && flag){
                    flag = false
                    flag1 = true
                    for (const link of document.querySelectorAll(
                        '.map-highscore_userWrapper__aHpCF a'
                    )) {
                        const rating = link.querySelector(`.${USER_RATING_CLASS}`);
                        if (rating) {
                            rating.remove();
                        }
                    }
                }
            }

            const openFriendHighscoreTab1 = tabSwitch1.lastChild.firstChild
            if(openFriendHighscoreTab1){
                if(openFriendHighscoreTab1.firstChild.classList.contains('switch_show__OGOFd') && flag1){
                    flag = true
                    flag1 = false
                    for (const link of document.querySelectorAll(
                        '.map-highscore_userWrapper__aHpCF a'
                    )) {
                        const rating = link.querySelector(`.${USER_RATING_CLASS}`);
                        if (rating) {
                            rating.remove();
                        }
                    }
                }
            }

        }

        for (const link of document.querySelectorAll('.map-highscore_userWrapper__aHpCF a')) {
            addRatingToUsername(link);
        }
    }

    if (RATING_IN_BREAKDOWN) {
        for (const link of document.querySelectorAll('.results_userLink__V6cBI a')) {
            addRatingToUsername(link);
        }
    }

    if (RATING_IN_SUGGESTIONS) {
        for (const link of document.querySelectorAll('.friend_name__U2HoN a')) {
            addRatingToUsername(link);
        }
    }

    if (RATING_IN_MATCHMAKING) {
        // battle royale matchmaking
        for (const link of document.querySelectorAll('.player-card_userLink__HhoDo')) {
            addRatingToUsername(link);
        }
    }
}

const observer = new MutationObserver(onMutationsStandard);

observer.observe(document.body, OBSERVER_CONFIG);

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址