A userscript dedicated to making the Korone site better and easier to use.
// ==UserScript==
// @name BTRKORONE
// @description A userscript dedicated to making the Korone site better and easier to use.
// @namespace https://www.pekora.zip/
// @version 1.0
// @license MIT
// @match https://www.pekora.zip/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_xmlhttpRequest
// @connect www.pekora.zip
// @connect i.redd.it
// @connect cdn.regnum.ru
// @connect upload.wikimedia.org
// @connect static.wikia.nocookie.net
// ==/UserScript==
(function () {
'use strict';
if (!GM_getValue('onboardingShown', false)) {
GM_setValue('onboardingShown', true);
function showOnboarding() {
const ov = document.createElement('div');
ov.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.75);z-index:99999;display:flex;align-items:center;justify-content:center;font-family:inherit;';
const box = document.createElement('div');
box.style.cssText = 'background:var(--white-color);border:1px solid var(--text-color-quinary);border-radius:8px;padding:32px 36px;max-width:400px;width:90%;text-align:center;color:var(--text-color-primary);box-shadow:0 8px 32px rgba(0,0,0,0.6);';
box.innerHTML = `
<h2 style="margin:0 0 12px;font-size:22px;font-weight:700;color:var(--text-color-primary);">Thanks for installing BTRKORONE</h2>
<p style="margin:0 0 20px;font-size:15px;color:var(--text-color-tertiary);line-height:1.6;">To access your settings, go to<br><strong style="color:var(--text-color-primary);">Settings → Account Info → Customize Your Korone</strong><br>and scroll to the bottom.</p>
<button id="pek-ob-ok" style="background:var(--primary-color);color:#fff;border:none;border-radius:4px;padding:10px 28px;font-size:16px;font-weight:600;cursor:pointer;">Got it!</button>
`;
ov.appendChild(box);
document.body.appendChild(ov);
ov.querySelector('#pek-ob-ok').addEventListener('click', () => ov.remove());
ov.addEventListener('click', e => { if (e.target === ov) ov.remove(); });
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', showOnboarding);
else showOnboarding();
}
if (location.pathname === '/catalog') {
const keyword = new URLSearchParams(location.search).get('keyword');
if (keyword) {
let injected = false;
const injectSearch = () => {
if (injected) return;
const inp = document.querySelector('input[placeholder="Search"][type="text"]');
const searchBtn = document.querySelector('[class*="searchButton"]');
const selectorBtn = document.querySelector('[class*="selectorClosed"]');
if (!inp || !searchBtn || !selectorBtn) return;
injected = true;
obs.disconnect();
selectorBtn.click();
requestAnimationFrame(() => {
const allOption = Array.from(document.querySelectorAll('[class*="selectOption"]'))
.find(el => el.textContent.trim() === 'All');
if (allOption) allOption.click();
const nativeSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
nativeSetter.call(inp, keyword);
inp.dispatchEvent(new Event('input', { bubbles: true }));
inp.dispatchEvent(new Event('change', { bubbles: true }));
requestAnimationFrame(() => searchBtn.click());
});
};
const obs = new MutationObserver(injectSearch);
obs.observe(document.body, { childList: true, subtree: true });
injectSearch();
}
}
const DEFAULTS = {
alertBarHidden: true,
logoStyle: 'korone',
adsHidden: false,
hideFeed: false,
hideYearText: false,
hideRagdoll: false,
mergeTix: false,
siteAccuracy: false,
noTrading: false,
textPlayButton: false,
friendSuggest: true,
koroneToRoblox: false,
};
let barHidden = GM_getValue('alertBarHidden', DEFAULTS.alertBarHidden);
let logoStyle = GM_getValue('logoStyle', DEFAULTS.logoStyle);
let adsHidden = GM_getValue('adsHidden', DEFAULTS.adsHidden);
let hideFeed = GM_getValue('hideFeed', DEFAULTS.hideFeed);
let hideYearText = GM_getValue('hideYearText', DEFAULTS.hideYearText);
let hideRagdoll = GM_getValue('hideRagdoll', DEFAULTS.hideRagdoll);
let mergeTix = GM_getValue('mergeTix', DEFAULTS.mergeTix);
let siteAccuracy = GM_getValue('siteAccuracy', DEFAULTS.siteAccuracy);
let noTrading = GM_getValue('noTrading', DEFAULTS.noTrading);
let textPlayButton = GM_getValue('textPlayButton', DEFAULTS.textPlayButton);
let friendSuggest = GM_getValue('friendSuggest', DEFAULTS.friendSuggest);
let koroneToRoblox = GM_getValue('koroneToRoblox', DEFAULTS.koroneToRoblox);
const LOGOS = {
korone: { desktop: '/img/korone1.png', mobile: '/img/korone-icon-square1.png', favicon: 'https://www.pekora.zip/favicon.ico', external: false, filter: '', faviconFilter: '' },
pekora: { desktop: 'https://i.redd.it/sfjq9qtt374f1.png', mobile: 'https://i.redd.it/sfjq9qtt374f1.png', favicon: 'https://www.pekora.zip/favicon.ico', external: true, filter: '', faviconFilter: '' },
roblox17red: { desktop: 'https://cdn.regnum.ru/uploads/pictures/news/2021/09/08/regnum_picture_163113324614928_normal.png', mobile: 'https://cdn.regnum.ru/uploads/pictures/news/2021/09/08/regnum_picture_163113324614928_normal.png', favicon: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/dc/Roblox_icon_-_2017.svg/500px-Roblox_icon_-_2017.svg.png', external: true, filter: '', faviconFilter: '' },
roblox17white: { desktop: 'https://cdn.regnum.ru/uploads/pictures/news/2021/09/08/regnum_picture_163113324614928_normal.png', mobile: 'https://cdn.regnum.ru/uploads/pictures/news/2021/09/08/regnum_picture_163113324614928_normal.png', favicon: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/dc/Roblox_icon_-_2017.svg/500px-Roblox_icon_-_2017.svg.png', external: true, filter: 'brightness(0) invert(1)', faviconFilter: 'brightness(0) invert(1)' },
robloxPre: { desktop: 'https://upload.wikimedia.org/wikipedia/commons/0/09/Roblox_logo_2015.png', mobile: 'https://upload.wikimedia.org/wikipedia/commons/0/09/Roblox_logo_2015.png', favicon: 'https://static.wikia.nocookie.net/logopedia/images/1/19/ROBLOX_Logo_2015.svg/revision/latest/scale-to-width-down/200?cb=20250518023531', external: true, filter: '', faviconFilter: '' },
};
const PAL_HAIR = 164;
const MOTORCYCLE = 176;
const DARK_GREEN = 178;
//add default avatar skin colours here at some point dumbass fuck you
const MAN_BUNDLE = new Set([167, 168, 169, 171, 172]);
function isAbandonedLoadout(assetIds) {
const ids = new Set(assetIds);
const hasPalHair = ids.has(PAL_HAIR);
const hasMotorcycle = ids.has(MOTORCYCLE);
const hasDarkGreen = ids.has(DARK_GREEN);
const hasManBundle = [...MAN_BUNDLE].some(id => ids.has(id));
if (hasPalHair && hasMotorcycle && hasManBundle) return 'skip';
if (hasPalHair && hasDarkGreen && hasManBundle) return 'skip';
if (hasPalHair && hasMotorcycle) return 'likely';
if (hasPalHair && hasDarkGreen) return 'likely';
return 'ok';
}
const b64cache = {};
const styleEls = {};
['bar','logo','ad','game','feed','year','tix','dropdown','accuracy','trading','play','seeall'].forEach(k => {
styleEls[k] = document.createElement('style');
document.head.appendChild(styleEls[k]);
});
styleEls.dropdown.textContent = `
#pek-robux-dropdown{color:var(--text-color-primary);right:5px;left:auto;background-color:var(--white-color);box-shadow:0 -5px 20px rgba(25,25,25,0.15)!important;max-height:266px;border-radius:4px;background-clip:padding-box;font-size:16px;margin:0;padding:0;position:absolute;top:100%;min-width:190px;overflow-x:hidden;overflow-y:auto;list-style:none;text-align:left;z-index:1123;}
#pek-robux-dropdown li{color:var(--text-color-primary);padding:0;margin:0;white-space:nowrap;width:100%;list-style:none;display:list-item;}
#pek-robux-dropdown li:hover{background-color:var(--background-color)!important;box-shadow:inset 4px 0 0 0 var(--primary-color);}
#pek-robux-dropdown li a{padding:10px 12px;display:block;clear:both;line-height:1.428571429;white-space:nowrap;border:none;background:transparent;width:100%;text-align:left;text-decoration:none;cursor:pointer;font-size:16px;user-select:none;color:var(--text-color-primary);}
#pek-robux-dropdown li a:hover{color:var(--text-color-primary);text-decoration:none;}
#pek-robux-dropdown li.pek-disabled a{opacity:0.5;cursor:default;pointer-events:none;}
`;
function applyBarState() { styleEls.bar.textContent = barHidden ? `[class^="alertBg"],[class*=" alertBg"]{display:none!important}` : ''; }
function applyYearTextState() { styleEls.year.textContent = hideYearText ? `[class^="yearText"],[class*=" yearText"]{display:none!important}` : ''; }
function applyRagdollState() { styleEls.game.textContent = hideRagdoll ? `li:has(a[href="/games/127175/Ragdoll-Engine-2020"]){display:none!important}` : ''; }
function applyTixCSS() { styleEls.tix.textContent = mergeTix ? `[class^="tixContainer"],[class*=" tixContainer"]{display:none!important}` : ''; }
function applyFeedState() {
styleEls.feed.textContent = hideFeed ? `
[class^="myFeedContainer"],[class*=" myFeedContainer"]{display:none!important}
[class^="blogNewsContainer"],[class*=" blogNewsContainer"]{width:100%!important;max-width:100%!important;flex:0 0 100%!important}
` : '';
}
function applyAdState() {
styleEls.ad.textContent = adsHidden ? `
[class^="adWrapper"],[class*=" adWrapper"],
[class^="advertisementContainer"],[class*=" advertisementContainer"],
[class^="skyScraperLeft"],[class*=" skyScraperLeft"],
[class^="skyScraperRight"],[class*=" skyScraperRight"]{display:none!important}
` : '';
styleEls.seeall.textContent = adsHidden ? `
[class^="containerHeader"],[class*=" containerHeader"]{display:flex!important;align-items:center!important;justify-content:space-between!important;}
[class^="containerHeader"] span,[class*=" containerHeader"] span{float:none!important;margin-left:auto!important;}
` : '';
applyLayoutExpansion();
}
function applySiteAccuracy() {
styleEls.accuracy.textContent = siteAccuracy ? `
a[href="/download"],a[href*="/download"]{display:none!important}
a[href*="discord.gg"]{display:none!important}
a[href*="tixexchange"]{display:none!important}
a[href*="robuxexchange"]{display:none!important}
` : '';
}
function applyNoTrading() {
styleEls.trading.textContent = noTrading ? `
.hover-icon-nav-trade,.hover-icon-nav-message{display:none!important}
a:has(.hover-icon-nav-trade),a:has(.hover-icon-nav-message){display:none!important}
` : '';
}
function applyTextPlayButton() {
styleEls.play.textContent = textPlayButton ? `
[class^="iconPlay"],[class*=" iconPlay"]{display:none!important}
button[class*="newBuyButton"]:has([class*="iconPlay"])::before{content:"Play";font-size:20px;font-weight:500;color:#fff;line-height:36px;display:inline-block;vertical-align:middle;}
` : '';
}
function replaceKoroneText(str) {
return str
.replace(/KORONE/g, 'ROBLOX').replace(/Korone/g, 'ROBLOX').replace(/korone/g, 'roblox')
.replace(/PEKORA/g, 'ROBLOX').replace(/Pekora/g, 'ROBLOX').replace(/pekora/g, 'roblox');
}
function applyKoroneToRoblox() {
if (!koroneToRoblox) return;
if (/(KORONE|Korone|korone|PEKORA|Pekora|pekora)/.test(document.title))
document.title = replaceKoroneText(document.title);
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, {
acceptNode(node) {
const p = node.parentElement;
if (!p) return NodeFilter.FILTER_REJECT;
if (['SCRIPT','STYLE','INPUT','TEXTAREA'].includes(p.tagName)) return NodeFilter.FILTER_REJECT;
if (p.closest('[data-pek-key="logoStyle"]')) return NodeFilter.FILTER_REJECT;
return /(KORONE|Korone|korone|PEKORA|Pekora|pekora)/.test(node.textContent) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
}
});
const nodes = []; let n;
while ((n = walker.nextNode())) nodes.push(n);
nodes.forEach(node => { node.textContent = replaceKoroneText(node.textContent); });
}
let isOnTixItemPage = false;
function checkTixItemPage() {
if (!/^\/catalog\/\d+/.test(location.pathname)) {
if (isOnTixItemPage) revertTixItemBalance();
isOnTixItemPage = false;
return;
}
const tixPriceIcon = document.querySelector('[class*="priceIcon"] .icon-tix, span.icon-tix[class*="priceIcon"], [class*="priceContainer"] .icon-tix');
if (!tixPriceIcon) {
if (isOnTixItemPage) revertTixItemBalance();
isOnTixItemPage = false;
return;
}
if (isOnTixItemPage) return;
isOnTixItemPage = true;
applyTixItemBalance();
}
function applyTixItemBalance() {
if (document.getElementById('pek-tix-balance-inject')) return;
const tixSpan = document.querySelector('[class*="tixContainer"] [class*="currencySpan"]');
const robuxSpan = document.querySelector('[class*="robuxContainer"] [class*="currencySpan"]');
const robuxIcon = document.querySelector('[class*="robuxContainer"] [class*="currencyIcon"]');
if (!tixSpan || !robuxSpan) return;
const badge = document.createElement('span');
badge.id = 'pek-tix-balance-inject';
badge.style.cssText = 'color:#fff;font-size:16px;margin-left:5px;margin-right:14px;display:inline;';
badge.textContent = tixSpan.textContent.trim();
if (robuxIcon) {
robuxIcon.dataset.pekOrigClass = robuxIcon.className;
robuxIcon.className = robuxIcon.className.replace('icon-nav-robux', 'icon-nav-tix');
}
robuxSpan.style.display = 'none';
robuxSpan.insertAdjacentElement('afterend', badge);
}
function revertTixItemBalance() {
document.getElementById('pek-tix-balance-inject')?.remove();
const robuxSpan = document.querySelector('[class*="robuxContainer"] [class*="currencySpan"]');
if (robuxSpan) robuxSpan.style.display = '';
const robuxIcon = document.querySelector('[class*="robuxContainer"] [class*="currencyIcon"]');
if (robuxIcon?.dataset.pekOrigClass) { robuxIcon.className = robuxIcon.dataset.pekOrigClass; delete robuxIcon.dataset.pekOrigClass; }
}
function syncFeedTheme() {
const iframe = document.getElementById('homepage-iframe-feed');
if (!iframe) return;
const inject = () => {
try {
const idoc = iframe.contentDocument;
if (!idoc || !idoc.head) return;
const bg = getComputedStyle(document.documentElement).getPropertyValue('--white-color').trim() || '#191919';
const text = getComputedStyle(document.documentElement).getPropertyValue('--text-color-primary').trim() || '#fff';
let s = idoc.getElementById('pek-theme-sync');
if (!s) { s = idoc.createElement('style'); s.id = 'pek-theme-sync'; idoc.head.appendChild(s); }
s.textContent = `body,html{background:${bg}!important;color:${text}!important;}a{color:${text}!important;}`;
} catch (e) {}
};
iframe.addEventListener('load', inject); inject();
}
function applyLayoutExpansion() {
document.querySelectorAll('.col-lg-9[class*="uselessFuckingClass"],.col-lg-12[class*="uselessFuckingClass"]').forEach(col => {
if (adsHidden) col.classList.replace('col-lg-9', 'col-lg-12');
else col.classList.replace('col-lg-12', 'col-lg-9');
});
const hc = document.querySelector('[class^="homeContainer"],[class*=" homeContainer"]');
if (hc) {
hc.style.flex = adsHidden ? '1 1 100%' : '';
hc.style.maxWidth = adsHidden ? '100%' : '';
const fl = hc.querySelector('[class^="friendsList"],[class*=" friendsList"]');
if (fl) fl.style.flexWrap = adsHidden ? 'wrap' : '';
}
}
function applyFaviconFromCache(url, filter) {
document.querySelectorAll('link[rel~="icon"]').forEach(el => el.remove());
if (filter) {
const img = new Image(); img.crossOrigin = 'anonymous';
img.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = img.width || 64; canvas.height = img.height || 64;
const ctx = canvas.getContext('2d'); ctx.filter = filter; ctx.drawImage(img, 0, 0);
const link = document.createElement('link'); link.rel = 'icon'; link.href = canvas.toDataURL();
link.setAttribute('data-pek-favicon', '1'); document.head.appendChild(link);
};
img.onerror = () => { const link = document.createElement('link'); link.rel = 'icon'; link.href = b64cache[url] || url; link.setAttribute('data-pek-favicon', '1'); document.head.appendChild(link); };
img.src = b64cache[url] || url;
} else {
const link = document.createElement('link'); link.rel = 'icon'; link.href = b64cache[url]; link.setAttribute('data-pek-favicon', '1'); document.head.appendChild(link);
}
}
new MutationObserver(() => {
const def = LOGOS[logoStyle] || LOGOS.korone;
if (b64cache[def.favicon] && !document.querySelector('link[data-pek-favicon]')) applyFaviconFromCache(def.favicon, def.faviconFilter);
}).observe(document.head, { childList: true });
function fetchB64(url, cb) {
if (b64cache[url]) { cb(b64cache[url]); return; }
if (url.startsWith('/') || url.startsWith(location.origin)) { b64cache[url] = url; cb(url); return; }
GM_xmlhttpRequest({ method: 'GET', url, responseType: 'blob',
onload: res => { const r = new FileReader(); r.onloadend = () => { b64cache[url] = r.result; cb(r.result); }; r.readAsDataURL(res.response); },
onerror: () => { b64cache[url] = url; cb(url); },
});
}
function applyLogoCSS(desktop, mobile, filter) {
const f = filter ? `filter:${filter}!important;` : '';
styleEls.logo.textContent = `
[class^="imgDesktop"],[class*=" imgDesktop"]{background-image:url("${desktop}")!important;background-size:contain!important;${f}}
[class^="imgMobile"],[class*=" imgMobile"]{background-image:url("${mobile}")!important;background-size:contain!important;${f}}
`;
}
function applyLogo(key) {
const def = LOGOS[key] || LOGOS.korone;
if (!def.external) { applyLogoCSS(def.desktop, def.mobile, ''); b64cache[def.favicon] = def.favicon; applyFaviconFromCache(def.favicon, ''); return; }
fetchB64(def.desktop, d => fetchB64(def.mobile, m => applyLogoCSS(d, m, def.filter)));
fetchB64(def.favicon, () => applyFaviconFromCache(def.favicon, def.faviconFilter));
}
let tixDropdown = null;
function removeTixDropdown() { if (tixDropdown) { tixDropdown.remove(); tixDropdown = null; } }
function claimRobux(tixAmount, onDone) {
GM_xmlhttpRequest({ method: 'GET', url: 'https://www.pekora.zip/internal/tixexchange',
onload: res => {
const doc = new DOMParser().parseFromString(res.responseText, 'text/html');
const token = doc.querySelector('input[name="__RequestVerificationToken"]');
if (!token) { onDone(false); return; }
GM_xmlhttpRequest({ method: 'POST', url: 'https://www.pekora.zip/internal/tixexchange',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: `tix=${encodeURIComponent(tixAmount)}&__RequestVerificationToken=${encodeURIComponent(token.value)}`,
onload: r => onDone(r.status < 400), onerror: () => onDone(false),
});
},
onerror: () => onDone(false),
});
}
function openTixDropdown(robuxLi) {
removeTixDropdown();
const tixSpan = document.querySelector('[class*="tixContainer"] [class*="currencySpan"]');
const tix = tixSpan ? (parseInt(tixSpan.textContent.replace(/,/g, ''), 10) || 0) : 0;
const claimable = Math.floor(tix / 10);
const ul = document.createElement('ul'); ul.id = 'pek-robux-dropdown';
function makeItem(label, onClick, disabled) {
const li = document.createElement('li'); if (disabled) li.className = 'pek-disabled';
const a = document.createElement('a'); a.href = '#'; a.textContent = label;
a.addEventListener('click', e => { e.preventDefault(); if (!disabled) onClick(a); });
li.appendChild(a); ul.appendChild(li);
}
makeItem('View Money', () => { removeTixDropdown(); location.href = '/My/Money.aspx'; });
if (isOnTixItemPage) {
makeItem('Claim ROBUX (leave tix item first)', null, true);
} else if (claimable > 0) {
makeItem(`Claim ROBUX (+${claimable})`, a => {
a.textContent = 'Converting…'; a.style.opacity = '0.5'; a.style.pointerEvents = 'none';
claimRobux(tix, ok => { removeTixDropdown(); if (ok) location.reload(); else alert('Conversion failed. Try the Tix Exchange page directly.'); });
});
} else {
makeItem(`Need ${10 - tix} more tix to claim`, null, true);
}
tixDropdown = ul; robuxLi.style.position = 'relative'; robuxLi.appendChild(ul);
setTimeout(() => {
document.addEventListener('click', function handler(e) {
if (!robuxLi.contains(e.target)) { removeTixDropdown(); document.removeEventListener('click', handler, true); }
}, true);
}, 0);
}
function attachTixListener() {
if (!mergeTix) return;
const robuxLi = document.querySelector('[class*="robuxContainer"]');
if (!robuxLi || robuxLi.dataset.pekTix) return;
robuxLi.dataset.pekTix = '1';
const link = robuxLi.querySelector('a'); if (!link) return;
link.addEventListener('click', e => {
e.preventDefault(); e.stopPropagation();
if (tixDropdown) removeTixDropdown(); else openTixDropdown(robuxLi);
});
}
function randomUserId() { const a = Math.floor(Math.random() * 100799) + 2, b = Math.floor(Math.random() * 100799) + 2; return Math.max(a, b); }
function sendFriendRequest(userId, btn) {
btn.textContent = '...'; btn.disabled = true;
GM_xmlhttpRequest({ method: 'POST', url: `https://www.pekora.zip/apisite/friends/v1/users/${userId}/request-friendship`,
headers: { 'Content-Type': 'application/json', 'Content-Length': '0' }, data: '',
onload: res => { if (res.status < 400) { btn.textContent = 'Pending'; btn.disabled = true; btn.style.opacity = '0.6'; } else { btn.textContent = 'Failed'; btn.disabled = false; } },
onerror: () => { btn.textContent = 'Error'; btn.disabled = false; },
});
}
function checkAvatarAndAdd(userId, userName, cards, onDone) {
GM_xmlhttpRequest({ method: 'GET', url: `https://www.pekora.zip/apisite/avatar/v1/users/${userId}/avatar`,
onload: res => {
try {
const data = JSON.parse(res.responseText);
const assetIds = (data.assets || []).map(a => a.id);
const verdict = isAbandonedLoadout(assetIds);
if (verdict === 'skip') { onDone(false); return; }
if (verdict === 'likely' && Math.random() < 0.7) { onDone(false); return; }
} catch (e) {}
GM_xmlhttpRequest({ method: 'GET', url: `https://www.pekora.zip/apisite/thumbnails/v1/users/avatar-headshot?userIds=${userId}&size=150x150&format=png`,
onload: tres => {
let thumbUrl = '/img/placeholder.png';
try { thumbUrl = JSON.parse(tres.responseText)?.data?.[0]?.imageUrl || thumbUrl; } catch (e) {}
const card = document.createElement('div');
card.style.cssText = 'display:flex;flex-direction:column;align-items:center;gap:8px;width:100px;';
const link = document.createElement('a'); link.href = `/users/${userId}/profile`;
link.style.cssText = 'display:flex;flex-direction:column;align-items:center;gap:6px;text-decoration:none;color:var(--text-color-primary);';
const img = document.createElement('img'); img.src = thumbUrl; img.alt = userName; img.onerror = () => { img.src = '/img/placeholder.png'; };
img.style.cssText = 'width:64px;height:64px;border-radius:50%;object-fit:cover;background:var(--background-color);border:2px solid var(--text-color-quinary);';
const name = document.createElement('span'); name.textContent = userName;
name.style.cssText = 'font-size:13px;text-align:center;word-break:break-word;color:var(--text-color-primary);font-weight:500;';
link.appendChild(img); link.appendChild(name); card.appendChild(link);
const btn = document.createElement('button'); btn.textContent = 'Add Friend';
btn.style.cssText = 'color:var(--text-color-primary)!important;border:1px solid var(--text-color-secondary)!important;display:inline-block!important;padding:6px 10px!important;font-size:14px!important;background:var(--white-color)!important;text-align:center!important;font-weight:500!important;line-height:100%!important;user-select:none!important;white-space:nowrap!important;border-radius:3px!important;cursor:pointer!important;font-family:inherit!important;width:100%!important;';
btn.addEventListener('mouseover', () => btn.style.boxShadow = '0 1px 3px rgb(150 150 150 / 74%)');
btn.addEventListener('mouseout', () => btn.style.boxShadow = '');
btn.addEventListener('click', () => sendFriendRequest(userId, btn));
card.appendChild(btn); cards.appendChild(card); onDone(true);
},
onerror: () => onDone(false),
});
},
onerror: () => onDone(false),
});
}
function applyFriendSuggestions() {
if (!location.pathname.includes('friends') && !location.href.includes('friend')) { document.getElementById('pek-friend-suggest')?.remove(); return; }
if (!friendSuggest) { document.getElementById('pek-friend-suggest')?.remove(); return; }
const h2 = Array.from(document.querySelectorAll('h2')).find(el => el.textContent.includes('FRIEND REQUEST') && /\(0\)/.test(el.textContent));
if (!h2 || document.getElementById('pek-friend-suggest')) return;
const box = document.createElement('div'); box.id = 'pek-friend-suggest';
box.style.cssText = 'margin-top:24px;padding:20px;background:var(--white-color);border-radius:4px;text-align:center;';
const msg = document.createElement('p'); msg.style.cssText = 'font-size:16px;margin-bottom:20px;color:var(--text-color-primary);';
msg.textContent = "There are no friend requests for you right now, but that doesn’t stop you from making new friends!";
box.appendChild(msg);
const cards = document.createElement('div'); cards.style.cssText = 'display:flex;gap:16px;justify-content:center;flex-wrap:wrap;';
box.appendChild(cards);
(h2.closest('.row') || h2.parentElement).insertAdjacentElement('afterend', box);
const tried = new Set(); let found = 0;
function tryNextUser() {
if (found >= 3 || tried.size >= 20) return;
let id; do { id = randomUserId(); } while (tried.has(id)); tried.add(id);
GM_xmlhttpRequest({ method: 'GET', url: `https://www.pekora.zip/apisite/users/v1/users/${id}`,
onload: res => {
if (res.status !== 200) { tryNextUser(); return; }
try {
const user = JSON.parse(res.responseText);
if (!user || !user.name || user.name === 'Unknown') { tryNextUser(); return; }
checkAvatarAndAdd(id, user.name, cards, added => { if (added) found++; if (found < 3) tryNextUser(); });
} catch (e) { tryNextUser(); }
},
onerror: () => tryNextUser(),
});
}
tryNextUser(); tryNextUser(); tryNextUser();
}
function getCurrentValues() {
return { alertBarHidden: barHidden, logoStyle, adsHidden, hideFeed, hideYearText, hideRagdoll, mergeTix, siteAccuracy, noTrading, textPlayButton, friendSuggest, koroneToRoblox };
}
function applyAll() {
applyBarState(); applyAdState(); applyRagdollState(); applyFeedState();
applyYearTextState(); applyTixCSS(); applySiteAccuracy(); applyNoTrading();
applyTextPlayButton(); applyLogo(logoStyle); syncFeedTheme();
if (!mergeTix) { revertTixItemBalance(); isOnTixItemPage = false; }
}
applyAll();
function makeRow(labelText, stateKey, options, currentValue, onChange) {
const ei = document.querySelector('.flex.mt-1 input[readonly]');
const es = document.querySelector('.flex.mt-1 select');
const row = document.createElement('div'); row.className = 'flex mt-1';
const lc = document.createElement('div'); lc.className = 'col pe-0';
const li = ei ? ei.cloneNode(false) : document.createElement('input');
li.readOnly = true; li.type = 'text'; li.value = labelText; lc.appendChild(li);
const sc = document.createElement('div'); sc.className = 'col ps-0 pe-0';
const sel = es ? es.cloneNode(false) : document.createElement('select');
sel.dataset.pekKey = stateKey; sel.id = `pek-${stateKey}-select`; sel.innerHTML = '';
options.forEach(([v, l]) => { const o = document.createElement('option'); o.value = v; o.textContent = l; sel.appendChild(o); });
sel.value = currentValue;
sel.addEventListener('change', () => onChange(sel.value));
sc.appendChild(sel); row.appendChild(lc); row.appendChild(sc);
return row;
}
function makeActionButtons() {
const w = document.createElement('div'); w.id = 'pek-action-buttons'; w.style.cssText = 'display:flex;gap:8px;margin-top:16px;justify-content:flex-end;';
const mkBtn = (label, fn) => { const b = document.createElement('button'); b.textContent = label; b.style.cssText = 'border:1px solid var(--text-color-quinary);cursor:pointer;padding:4px 8px;font-size:16px;background:var(--background-color);border-radius:4px;color:var(--text-color-primary);font-family:inherit;'; b.addEventListener('click', fn); return b; };
w.appendChild(mkBtn('Export Settings', () => { const blob = new Blob([JSON.stringify(getCurrentValues(), null, 2)], { type: 'application/octet-stream' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'pekora-settings.ksf'; a.click(); URL.revokeObjectURL(url); }));
w.appendChild(mkBtn('Import Settings', () => { const inp = document.createElement('input'); inp.type = 'file'; inp.accept = '.ksf'; inp.addEventListener('change', () => { const f = inp.files[0]; if (!f) return; const r = new FileReader(); r.onload = e => { try { const o = JSON.parse(e.target.result); if(o.alertBarHidden!==undefined){barHidden=!!o.alertBarHidden;GM_setValue('alertBarHidden',barHidden);}if(o.logoStyle!==undefined){logoStyle=o.logoStyle;GM_setValue('logoStyle',logoStyle);}if(o.adsHidden!==undefined){adsHidden=!!o.adsHidden;GM_setValue('adsHidden',adsHidden);}if(o.hideFeed!==undefined){hideFeed=!!o.hideFeed;GM_setValue('hideFeed',hideFeed);}if(o.hideYearText!==undefined){hideYearText=!!o.hideYearText;GM_setValue('hideYearText',hideYearText);}if(o.hideRagdoll!==undefined){hideRagdoll=!!o.hideRagdoll;GM_setValue('hideRagdoll',hideRagdoll);}if(o.mergeTix!==undefined){mergeTix=!!o.mergeTix;GM_setValue('mergeTix',mergeTix);}if(o.siteAccuracy!==undefined){siteAccuracy=!!o.siteAccuracy;GM_setValue('siteAccuracy',siteAccuracy);}if(o.noTrading!==undefined){noTrading=!!o.noTrading;GM_setValue('noTrading',noTrading);}if(o.textPlayButton!==undefined){textPlayButton=!!o.textPlayButton;GM_setValue('textPlayButton',textPlayButton);}if(o.friendSuggest!==undefined){friendSuggest=!!o.friendSuggest;GM_setValue('friendSuggest',friendSuggest);}if(o.koroneToRoblox!==undefined){koroneToRoblox=!!o.koroneToRoblox;GM_setValue('koroneToRoblox',koroneToRoblox);} applyAll(); syncDropdowns(); alert('Settings imported!'); } catch(err){alert('Invalid .ksf file.');} }; r.readAsText(f); }); inp.click(); }));
w.appendChild(mkBtn('Reset to Default', () => { if (!confirm('Reset all settings to defaults?')) return; Object.entries(DEFAULTS).forEach(([k,v])=>GM_setValue(k,v)); barHidden=DEFAULTS.alertBarHidden;logoStyle=DEFAULTS.logoStyle;adsHidden=DEFAULTS.adsHidden;hideFeed=DEFAULTS.hideFeed;hideYearText=DEFAULTS.hideYearText;hideRagdoll=DEFAULTS.hideRagdoll;mergeTix=DEFAULTS.mergeTix;siteAccuracy=DEFAULTS.siteAccuracy;noTrading=DEFAULTS.noTrading;textPlayButton=DEFAULTS.textPlayButton;friendSuggest=DEFAULTS.friendSuggest;koroneToRoblox=DEFAULTS.koroneToRoblox; revertTixItemBalance(); isOnTixItemPage=false; applyAll(); syncDropdowns(); }));
return w;
}
function syncDropdowns() {
const map = { alertBarHidden: barHidden?'hidden':'shown', logoStyle, adsHidden: adsHidden?'hidden':'shown', hideFeed: hideFeed?'hidden':'shown', hideYearText: hideYearText?'hidden':'shown', hideRagdoll: hideRagdoll?'hidden':'shown', mergeTix: mergeTix?'enabled':'disabled', siteAccuracy: siteAccuracy?'enabled':'disabled', noTrading: noTrading?'enabled':'disabled', textPlayButton: textPlayButton?'enabled':'disabled', friendSuggest: friendSuggest?'enabled':'disabled', koroneToRoblox: koroneToRoblox?'enabled':'disabled' };
document.querySelectorAll('[data-pek-key]').forEach(sel => { const v = map[sel.dataset.pekKey]; if (v !== undefined) sel.value = v; });
}
function inject() {
if (document.querySelector('[data-pek-injected]')) return;
for (const h of document.querySelectorAll('h3')) {
if (h.textContent.trim() !== 'Customize Your Korone') continue;
const card = h.nextElementSibling; if (!card) return;
const marker = document.createElement('div'); marker.setAttribute('data-pek-injected', '1'); card.appendChild(marker);
const B = (label, key, opts, val, fn) => card.appendChild(makeRow(label, key, opts, val, fn));
const tog = v => v ? 'enabled' : 'disabled', vis = v => v ? 'hidden' : 'shown';
B('Alert Bar', 'alertBarHidden', [['hidden','Hidden'],['shown','Shown']], vis(barHidden), v=>{barHidden=v==='hidden'; GM_setValue('alertBarHidden',barHidden); applyBarState();});
B('Logo Style', 'logoStyle', [['korone','Korone'],['pekora','Pekora'],['roblox17red','ROBLOX (2017 Red)'],['roblox17white','ROBLOX (2017 White)'],['robloxPre','ROBLOX (pre-2017)']], logoStyle, v=>{logoStyle=v; GM_setValue('logoStyle',logoStyle); applyLogo(v);});
B('User Ads', 'adsHidden', [['shown','Shown'],['hidden','Hidden']], vis(adsHidden), v=>{adsHidden=v==='hidden'; GM_setValue('adsHidden',adsHidden); applyAdState();});
B('My Feed', 'hideFeed', [['shown','Shown'],['hidden','Hidden']], vis(hideFeed), v=>{hideFeed=v==='hidden'; GM_setValue('hideFeed',hideFeed); applyFeedState();});
B('Year on Game Cards', 'hideYearText', [['shown','Shown'],['hidden','Hidden']], vis(hideYearText), v=>{hideYearText=v==='hidden'; GM_setValue('hideYearText',hideYearText); applyYearTextState();});
B('Hide Ragdoll Engine', 'hideRagdoll', [['shown','Shown'],['hidden','Hidden']], vis(hideRagdoll), v=>{hideRagdoll=v==='hidden'; GM_setValue('hideRagdoll',hideRagdoll); applyRagdollState();});
B('Merge TIX with ROBUX','mergeTix', [['disabled','Disabled'],['enabled','Enabled']], tog(mergeTix), v=>{mergeTix=v==='enabled'; GM_setValue('mergeTix',mergeTix); applyTixCSS(); if(!mergeTix){revertTixItemBalance();isOnTixItemPage=false;} const r=document.querySelector('[class*="robuxContainer"]'); if(r)delete r.dataset.pekTix; if(mergeTix)attachTixListener();});
B('i havent thought of a name for this one yet', 'siteAccuracy', [['disabled','Disabled'],['enabled','Enabled']], tog(siteAccuracy), v=>{siteAccuracy=v==='enabled'; GM_setValue('siteAccuracy',siteAccuracy); applySiteAccuracy();});
B('idgaf bout trading', 'noTrading', [['disabled','Disabled'],['enabled','Enabled']], tog(noTrading), v=>{noTrading=v==='enabled'; GM_setValue('noTrading',noTrading); applyNoTrading();});
B('Text Play Button', 'textPlayButton', [['disabled','Disabled'],['enabled','Enabled']], tog(textPlayButton), v=>{textPlayButton=v==='enabled'; GM_setValue('textPlayButton',textPlayButton); applyTextPlayButton();});
B('Friend Suggestions', 'friendSuggest', [['enabled','Enabled'],['disabled','Disabled']], tog(friendSuggest), v=>{friendSuggest=v==='enabled'; GM_setValue('friendSuggest',friendSuggest); applyFriendSuggestions();});
B('Korone To ROBLOX', 'koroneToRoblox', [['disabled','Disabled'],['enabled','Enabled']], tog(koroneToRoblox), v=>{koroneToRoblox=v==='enabled'; GM_setValue('koroneToRoblox',koroneToRoblox); if(koroneToRoblox)applyKoroneToRoblox();});
card.appendChild(makeActionButtons()); return;
}
}
let pending = false;
function onDOMChange() {
if (pending) return; pending = true;
requestAnimationFrame(() => {
pending = false;
inject(); applyLayoutExpansion(); attachTixListener();
applyFriendSuggestions(); syncFeedTheme();
if (mergeTix) checkTixItemPage();
if (koroneToRoblox) applyKoroneToRoblox();
});
}
function startSettingsObserver() { new MutationObserver(onDOMChange).observe(document.body, { childList: true, subtree: true }); onDOMChange(); }
let lastPath = location.pathname;
if (location.pathname.startsWith('/My/Account')) {
startSettingsObserver();
} else {
new MutationObserver(() => {
if (location.pathname !== lastPath) {
lastPath = location.pathname;
revertTixItemBalance(); isOnTixItemPage = false;
applyAll(); removeTixDropdown();
}
onDOMChange();
if (location.pathname.startsWith('/My/Account')) startSettingsObserver();
}).observe(document.body, { childList: true, subtree: true });
}
})();