NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Your Genshin Impact Characters // @namespace https://github.com/KTOOGER/Your-Genshin-Impact-Characters // @description A userscript that highlights your characters on Genshin Impact sites // @require https://openuserjs.org/src/libs/sizzle/GM_config.js // @version 1.2.5 // @license MIT // @author KTOOGER // @grant GM_getValue // @grant GM_setValue // @match https://genshin-center.com/* // @match https://genshin.gg/* // @match https://genshin.honeyhunterworld.com/* // ==/UserScript== (function () { 'use strict'; const CHARACTERS = { "Albedo": {}, "Alhaitham": {}, "Aloy": {}, "Amber": {}, "Ayaka": { "genshin-center.com": "kamisatoayaka", "genshin.honeyhunterworld.com": "Kamisato Ayaka" }, "Ayato": { "genshin-center.com": "kamisatoayato", "genshin.honeyhunterworld.com": "Kamisato Ayato" }, "Barbara": {}, "Beidou": {}, "Baizhu": {}, "Bennett": {}, "Candace": {}, "Chongyun": {}, "Collei": {}, "Cyno": {}, "Dehya": {}, "Diluc": {}, "Diona": {}, "Dori": {}, "Eula": {}, "Faruzan": {}, "Fischl": {}, "Ganyu": {}, "Gorou": {}, "Heizou": { "genshin-center.com": "shikanoinheizou", "genshin.honeyhunterworld.com": "Shikanoin Heizou" }, "HuTao": { "genshin.honeyhunterworld.com": "Hu Tao" }, "Itto": { "genshin-center.com": "aratakiitto", "genshin.honeyhunterworld.com": "Arataki Itto" }, "Jean": {}, "Kaeya": {}, "Kaveh": {}, "Kazuha": { "genshin-center.com": "kaedeharakazuha", "genshin.honeyhunterworld.com": "Kaedehara Kazuha" }, "Keqing": {}, "Klee": {}, "Kokomi": { "genshin-center.com": "sangonomiyakokomi", "genshin.honeyhunterworld.com": "Sangonomiya Kokomi" }, "Layla": {}, "Lisa": {}, "Mika": {}, "Mona": {}, "Nahida": {}, "Nilou": {}, "Ningguang": {}, "Noelle": {}, "Qiqi": {}, "Raiden": { "genshin.honeyhunterworld.com": "Raiden Shogun" }, "Razor": {}, "Rosaria": {}, "Sara": { "genshin-center.com": "kujousara", "genshin.honeyhunterworld.com": "Kujou Sara" }, "Sayu": {}, "Shenhe": {}, "Shinobu": { "genshin.gg": "kukishinobu", "genshin-center.com": "kukishinobu", "genshin.honeyhunterworld.com": "Kuki Shinobu" }, "Sucrose": {}, "Tartaglia": { "genshin.gg": "childe" }, "Thoma": {}, "Tighnari": {}, "Traveler(Anemo)": { "genshin-center.com": "traveler", "genshin.honeyhunterworld.com": "Traveler" }, "Traveler(Dendro)": { "genshin-center.com": "traveler", "genshin.honeyhunterworld.com": "Traveler" }, "Traveler(Geo)": { "genshin-center.com": "traveler", "genshin.honeyhunterworld.com": "Traveler" }, "Traveler(Electro)": { "genshin-center.com": "traveler", "genshin.honeyhunterworld.com": "Traveler" }, "Venti": {}, "Wanderer": {}, "Xiangling": {}, "Xiao": {}, "Xingqiu": {}, "Xinyan": {}, "YaeMiko": { "genshin.honeyhunterworld.com": "Yae Miko" }, "Yanfei": {}, "Yaoyao": {}, "Yelan": {}, "Yoimiya": {}, "YunJin": { "genshin.honeyhunterworld.com": "Yun Jin" }, "Zhongli": {} } const HASHES = { "#settings": () => gms.open(), "#import": () => importCharacters() } const charNameRules = { "genshin.gg": (text) => text.toLowerCase(), "genshin-center.com": (text) => text.toLowerCase() } const cssFor = { 'genshin-center.com': (chars) => { return ( `a .CharacterThumbnail_charBox__NsyIF .containedImage { opacity : 0.333 }` + chars.highlight.map((char) => `\na[href*="/characters/${char}"] .containedImage {opacity: 1}`).join('') ) }, 'genshin.gg': (chars) => { return ( chars.highlight.map((char) => `a.character-portrait[href^="/characters/${char}"]>img, a.tierlist-portrait[href^="/characters/${char}"] > .tierlist-icon-wrapper { opacity: 1 }\n`).join('') + `a.character-portrait>img, a.tierlist-portrait > .tierlist-icon-wrapper { opacity:0.3333 } iframe#Characters {z-index: 99999 !important}` ) }, 'genshin.honeyhunterworld.com': (chars) => { return ( `iframe#Characters {z-index: 99999 !important}` + chars.highlight.map((char) => `\na .itempic_cont img[alt="${char}"] { opacity: 1 }`).join('') + chars.other.map((char) => `\na .itempic_cont img[alt="${char}"] { opacity: 0.333 }`).join('') ) } } const addHtmlInterfaceFor = { 'genshin.gg'() { root.querySelector(".dropdown-menu").insertAdjacentHTML("beforeend", '<a class="nav-link" href="#settings">Settings</a>') }, 'genshin.honeyhunterworld.com'() { document.querySelector("body > div > div.wp-block-columns > div:nth-child(1) > .ad_sidebar_left").insertAdjacentHTML("beforebegin", `<a href="#settings"> <label class="menu_item_text"> <div class="menu_item_img_wrap"> <img alt="Settings" loading="lazy" class="widget_menu_icon" src="/img/icons/char_35.webp?x37636"> </div> Settings </label> </a>`) } } function getAllCharsFor(site) { let result = {} let rename = charNameRules[site] || (t => t) for (let char in CHARACTERS) { result[char] = CHARACTERS[char][site] || rename(char) } return result } function getUserCharsFor(site) { let result = { highlight: [], other: [] } let characters = getAllCharsFor(site) for (let char in characters) { let names = [] if (typeof characters[char] === "object") { for (let name in characters[char]) { names.push(characters[char][name]) } } else { names.push(characters[char]) } if (gms.get(char)) { result.highlight = result.highlight.concat(names) } else { result.other = result.other.concat(names) } } return result } function initGM(CHARACTERS) { let settings = {} for (let el in CHARACTERS) { settings[el] = { 'label': el, 'type': 'checkbox', 'default': false } } GM_config.init({ 'id': 'Characters', 'fields': settings, 'events': { 'save': function () { document.location.href = document.location.pathname }, 'close': function () { document.location.href = document.location.pathname } } }); return GM_config } function hashCheck() { for (let hash in HASHES) { if (document.location.hash === hash) { HASHES[hash]() break } } } function addHtml(site) { (addHtmlInterfaceFor[site] || (() => console.log('Interface not added')))() let style = document.createElement('style') style.innerHTML = cssFor[site](getUserCharsFor(site)) document.head.append(style) } function initScript() { hashCheck() window.onhashchange = hashCheck addHtml(site) } if (document.location.ancestorOrigins.length) return const site = document.location.host var gms = initGM(CHARACTERS) initScript() })();