您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
My attempt to improve the search function in geoguessr.
当前为
// ==UserScript== // @name A Better Search // @namespace http://tampermonkey.net/ // @version 0.0.1 // @description My attempt to improve the search function in geoguessr. // @author Lemson // @match https://www.geoguessr.com/ // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @license MIT // @grant GM_addStyle // ==/UserScript== const CSS = ` .top-search-bar{ width: 30%; margin-left: 34%; position: absolute; border-radius: 2rem; padding-left: 1rem; font-size: 1rem; background-color: rgba(0,0,0,.8); color: white; border: 1px solid white; } .modal { width: 70%; height: 70%; background-color: #d9d9d9; border-radius: 2.5rem; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); scale: 0; transition: 0.1s; box-shadow: 0 0 5rem 1rem rgb(0, 0, 0); display: flex; z-index:5; } .active { transition: 0.1s; scale: 1; } .sidebar { height: 100%; width: 4rem; background-color: #545454; border-top-left-radius: 2.5rem; border-bottom-left-radius: 2.5rem; border-right: 1px solid black; } .maincontent { display: flex; flex-direction: column; width: 100%; } .search { height: 2.5rem; margin: 2rem; display: flex; justify-content: space-between; } .searchbar { width: 50%; border-radius: 1.1rem; border: 0.1rem solid black; padding-left: 1rem; box-shadow: 0 0 7rem black; font-size: 1rem; } .filter-btn { height: 100%; width: 2.5rem; border-radius: 0.4rem; border: 1px solid black; background-color: rgb(192, 192, 192); } .filter-btn:active { background-color: rgb(145, 145, 145); } .close { margin-left: 5rem; font-size: 2rem; cursor: pointer; } .close:hover{ transition: .2s; scale: 1.1; } .windows { width: 95%; height: 80%; margin-left: 2rem; border: 1px solid black; display: flex; flex-direction: row; justify-content: space-evenly; } .results { background-color: rgba(0, 0, 0, 0.112); width: 100%; height: 100%; overflow: auto; overflow-x: hidden; } .selection-info { background-color: rgba(0, 0, 0, 0.112); border-left: 0.1rem solid black; width: 100%; height: 100%; display: flex; flex-direction: column; overflow: auto; overflow-x: hidden; } .result-container { width: 99%; border: 1px solid rgb(0, 0, 0); margin: 0.2rem; display: flex; } .result-container:hover { background-color: rgba(0, 0, 0, 0.107); } .result-container:active { background-color: rgba(0, 0, 0, 0.25); } .result-title-author { width: 90%; } .result-title { font-size: 1.6rem; } .result-creator { font-size: 1rem; } .author-space { text-decoration: underline; color: rgb(15, 0, 88); } .likesdisplay { width: 10%; display: flex; flex-direction: column; align-items: center; justify-content: center; color: red; font-size: 1.2rem; -webkit-text-stroke: .5px black; } .selected { background-color: rgba(0, 0, 255, 0.1); } .selected-header { display: flex; flex-direction: row; padding-left: 1rem; border-bottom: .1rem solid black; justify-content: space-between; padding-right: 1rem; } .header-likes { display: flex; flex-direction: column; align-items: center; justify-content: center; } .selected-title { font-size: 1.4rem; } .selected-creator { font-size: .8rem; font-weight: bold; color: black; } .selected-creator:hover{ color: blue; } .selected-desc { margin: .5rem; border: 1px solid black; padding: .3rem; border-radius: .5rem; height: auto; min-height: 2rem; } .tags { display: flex; flex-direction: row; gap: .7rem; margin-left: .5rem; flex-wrap: wrap; row-gap: 0.5rem; } .searchAndFilter{ width: 100%; } .tag{ border: 1px solid black; padding: .2rem; padding-left: .5rem; padding-right: .5rem; border-radius: 2rem; height: .9rem; font-size: .8rem; } .game { position: relative; width: 100%; height: 100%; margin: 0.5rem; margin-top: 1.5rem; border-radius: 1rem; border: 1px solid black; overflow: hidden; display: flex; /* Use flexbox layout */ } .game:before { content: ""; background-image: url('https://img.freepik.com/free-photo/planet-earth-background_23-2150564685.jpg'); background-size: cover; background-position: center; position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: -10; overflow: hidden; } .game-settings { width: 50%; height: 100%; display: flex; flex-direction: column; align-items: center; } .ol-selected-leaderboard{ width: 50%; height: 100%; } ::-webkit-scrollbar { width: 0.1rem; } ::-webkit-scrollbar-thumb { background-color: rgb(0, 0, 0); } .game-mode-select{ color: white; display: flex; align-items: center; flex-direction: column; margin-top: .6rem; width: 100%; justify-content: center; margin-top: .7vh; } .game-mode-select>h1{ font-weight: 500; letter-spacing: .06vw; margin-bottom: .4vh; font-size: 1.6vh; } .gamemode-buttons{ display: flex; flex-direction: row; justify-content: space-evenly; background-color: rgba(255, 255, 255, 0.06); border: .1rem solid white; border-radius: .4rem; width: 95%; text-wrap: nowrap; } .gamemode-buttons>*{ font-size: 1.2rem; color: white; padding-left: 1rem; padding-right: 1rem; border-radius: .5rem; margin: .2rem; font-style: italic; } .selected-mode { background-color: #7950E5; } .round-select{ color: white; display: flex; align-items: center; justify-content: center; flex-direction: column; margin-top: 1.2rem; width: 100%; } .round-select>h1{ font-size: 1.3rem; font-weight: 500; letter-spacing: .1rem; margin-bottom: .3rem; } .round-numbers{ display: flex; flex-direction: row; justify-content: space-evenly; background-color: rgba(255, 255, 255, 0.06); border: .1rem solid white; border-radius: .4rem; width: 95%; height: 3rem; } .round-numbers>*{ color: white; width: 3.5rem; margin-top: .2rem; margin-bottom: .2rem; display: flex; align-items: center; justify-content: center; border-radius: .5rem; } .round-time{ color: white; display: flex; align-items: center; justify-content: center; flex-direction: column; margin-top: 1.2rem; width: 95%; background-color: rgba(0,0,0,0.7);; border: .1rem solid white; border-radius: .5rem; padding-top: 1rem; padding-bottom: 1rem; } .round-time>h1, .round-time>h2{ font-size: 1.3rem; font-weight: 500; letter-spacing: .1rem; margin-bottom: .3rem; } .time-slider{ width: 90%; padding:0; } .start-game-btn{ width: 95%; height: 4rem; background-color: #97E851; border-radius: 2rem; box-shadow: inset 0 1px 10px white; font-size: 2rem; font-weight: bold; font-style: italic; color: white; -webkit-text-stroke: 1px black; margin-top: 1rem; border: .1rem solid white; } `; GM_addStyle(CSS); const HTML = ` <div id="overlay-main" class="modal"> <div class="sidebar"></div> <div class="maincontent"> <div class="search"> <div class="searchAndFilter"> <input type="text" placeholder="Search..." class="searchbar" /> <button class="filter-btn">Filter</button> </div> <button class="close">✖</button> </div> <div class="windows"> <div class="results"> <!-- <div class="result-container"> <div class="result-title-author"> <h1 class="result-title">A Community Turkey</h1> <h2 class="result-creator">created by: <a href="google.com">John Harvey Kellogg</a></h2> </div> <div class="likesdisplay"> <div class="heartSVG">♥</div> <h3 class="like-ount"></h3> </div> </div> --> </div> <div class="selection-info"> <!-- <header class="selected-header"> <div class="header-title-container"> <h1 class="selected-title">A Balanced Turkey</h1> <a class="selected-creator ">John Harvey Kellogg</a> </div> <div class="header-likes"> <h3 class="header-likes-num">69</h3> <div>♥</div> </div> </header> --> </div> </div> </div> </div> `; let div = document.createElement("div"); div.innerHTML = HTML; document.body.append(div); //******************************************************************* */ //******************************************************************* */ //******************************************************************* */ //******************************************************************* */ //Creates searchbar on the top. //header_logoWrapper__ let searchBarParent = document.querySelector("[class^='header_logoWrapper__']"); searchBarParent.style = "justify-content: space-between;"; let topSearchBar = document.createElement("input"); topSearchBar.placeholder = "Search for a map..."; topSearchBar.classList.add("top-search-bar"); searchBarParent.appendChild(topSearchBar); const everything = document.querySelector(".modal"); document.addEventListener("keydown", function (event) { if (document.activeElement == topSearchBar && event.key === "Enter") { let searchTerm = topSearchBar.value; everything.classList.add("active"); search(searchTerm); } }); // const resultsBox = document.querySelector(".results"); const infoBox = document.querySelector(".selection-info"); const overlay = document.querySelector(".modal"); const closeButton = document.querySelector(".close"); const searchBar = document.querySelector(".searchbar"); let chosenMode = "no move"; let roundAmount = 5; let roundTimeSeconds = 300; const startGameBaseUrl = "https://www.geoguessr.com/api/v3/games"; closeButton.addEventListener("click", function () { overlay.classList.remove("active"); }); const search = async (searchTerm) => { //let searchTerm = document.querySelector(".searchbar").value; let resp = await fetch(`https://www.geoguessr.com/api/v3/search/map?page=0&count=20&q=${searchTerm}`); //let resp = await fetch(`https://www.geoguessr.com/api/v3/search/map?page=0&count=1&q=a%balanced%turkey`); if (!resp) { console.error("fetch error"); } const data = await resp.json(); console.log("Search results:", data); createResults(data); }; const createResults = (searchData) => { //removes any HTML, if there is any. So that new HTML can be added. resultsBox.innerHTML = null; searchData.forEach((item) => { //Create and add the HTML for result let resultContainerHTML = ` <div class="result-container"> <div class="result-title-author"> <h1 class="result-title">${item.name}</h1> <h2 class="result-creator">created by: <a target="_blank" id="author-link" href="user/${item.creatorId}">${item.creator}</a></h2> </div> <div class="likesdisplay"> <div class="heartSVG">♥</div> <h3 class="like-ount">${item.likes}</h3> </div> </div>`; //Create element to append the created HTML onto let resultContainerParent = document.createElement("div"); resultContainerParent.innerHTML = resultContainerHTML; resultsBox.appendChild(resultContainerParent); //click on result resultContainerParent.addEventListener("click", function () { let resultContainer = resultContainerParent.querySelector(".result-container"); let clearSelections = document.querySelectorAll(".result-container"); clearSelections.forEach((thing) => { //Remove selections thing.classList.remove("selected"); }); displaySelectedMap(item, resultContainer); }); }); }; const startGame = (map) => { console.log("start game"); console.log(chosenMode); let gameSettings; if (chosenMode == "move") { gameSettings = { forbidMoving: false, forbidRotating: false, forbidZooming: false, map: map, rounds: roundAmount, timeLimit: roundTimeSeconds, }; } if (chosenMode == "no move") { gameSettings = { forbidMoving: true, forbidRotating: false, forbidZooming: false, map: map, rounds: roundAmount, timeLimit: roundTimeSeconds, }; } if (chosenMode == "nmpz") { gameSettings = { forbidMoving: true, forbidRotating: true, forbidZooming: true, map: map, rounds: roundAmount, timeLimit: roundTimeSeconds, }; } fetch(startGameBaseUrl, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(gameSettings), }) .then((response) => response.json()) .then((data) => { console.log(`https://www.geoguessr.com/game/${data.token}`); return data; // Pass the data object to the next then block }) .then((data) => { window.location.href = `https://www.geoguessr.com/game/${data.token}`; }) .catch((error) => console.error("error", error)); }; const setMode = (mode, buttons, button) => { buttons.forEach((a) => { a.classList.remove("selected-mode"); }); switch (mode) { case "MOVE": chosenMode = "move"; button.classList.add("selected-mode"); break; case "NO MOVE": chosenMode = "no move"; button.classList.add("selected-mode"); break; case "NMPZ": chosenMode = "nmpz"; button.classList.add("selected-mode"); break; } console.log(mode); }; const setRounds = (roundNum, nums, selectedNum) => { nums.forEach((a) => { a.classList.remove("selected-mode"); }); switch (roundNum) { case "1": roundAmount = 1; selectedNum.classList.add("selected-mode"); break; case "2": roundAmount = 2; selectedNum.classList.add("selected-mode"); break; case "3": roundAmount = 3; selectedNum.classList.add("selected-mode"); break; case "4": roundAmount = 4; selectedNum.classList.add("selected-mode"); break; case "5": roundAmount = 5; selectedNum.classList.add("selected-mode"); break; } console.log(roundNum); }; const displaySelectedMap = (item, resultContainer) => { resultContainer.classList.add("selected"); //clear the infobox infoBox.innerHTML = null; if (item.description == "" || item.description == null) { item.description = "The creator of this map has not added a description"; } item.created = item.created.slice(0, 10); let officialState; if (!item.isUserMap) { officialState = "Official Map"; } else { officialState = "Usermade Map"; } let selectedItemHTML = ` <header class="selected-header"> <div class="header-title-container"> <h1 class="selected-title">${item.name}</h1> <a class="selected-creator" href="user/${item.creatorId}" target="_blank">${item.creator}</a> </div> <div class="header-likes"> <h3 class="header-likes-num">${item.likes}</h3> <div>♥</div> </div> </header> <div class="selected-info-container"> <div class="selected-desc">${item.description}</div> <div class="tags"> <div class="tag"> <b>${item.coordinateCount} locations</b> </div> <div class="tag"> <b>Created: ${item.created}</b> </div> <div class="tag"> <b>${item.numberOfGamesPlayed} games played</b> </div> <div class="tag"> <b>${officialState}</b> </div> </div> </div> <div class="game"> <div class="game-settings"> <div class="game-mode-select"> <h1>Game settings</h1> <div class="gamemode-buttons"> <button class="mode-button selected-mode">MOVE</button> <button class="mode-button">NO MOVE</button> <button class="mode-button">NMPZ</button> </div> </div> <div class="round-select"> <h1>ROUNDS</h1> <div class="round-numbers"> <button class="round-number ">1</button> <button class="round-number">2</button> <button class="round-number">3</button> <button class="round-number">4</button> <button class="round-number selected-mode">5</button> </div> </div> <div class="round-time"> <h1>ROUND TIME</h1> <input type="range" min="1" max="600" step="1" class="time-slider" value="30"/> <h2 class="time-display">30 seconds</h2> </div> <button class="start-game-btn">START GAME!</button> </div> <div class="ol-selected-leaderboard"></div> </div> `; infoBox.innerHTML = selectedItemHTML; const slider = document.querySelector(".time-slider"); const timeDisplay = document.querySelector(".time-display"); slider.addEventListener("input", function () { if (slider.value < 60) { timeDisplay.textContent = `${slider.value} seconds`; } else if (slider.value >= 60) { let timeMin = Math.floor(slider.value / 60); let timeSec = slider.value % 60; if (timeSec == "0") timeDisplay.textContent = `${timeMin} minutes`; else timeDisplay.textContent = `${timeMin} minutes, ${timeSec} seconds`; } roundTimeSeconds = slider.value; }); const startButton = document.querySelector(".start-game-btn"); const modeButtons = document.querySelectorAll(".mode-button"); const roundNumbers = document.querySelectorAll(".round-number"); modeButtons.forEach((button) => { button.addEventListener("click", () => setMode(button.textContent, modeButtons, button)); }); roundNumbers.forEach((number) => { number.addEventListener("click", () => setRounds(number.textContent, roundNumbers, number)); }); //start button, get every piece of data that's needed to start a game on the currently selected settings. startButton.addEventListener("click", () => { //item.id is map startGame(item.id); }); }; document.addEventListener("keydown", function (event) { if (document.activeElement == searchBar && event.key === "Enter") { let searchTerm = searchBar.value; search(searchTerm); } });
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址