Pastel Live 2.0

Gartic.io Pastel Live – watch rooms, players and chat in real time.

目前為 2025-10-15 提交的版本,檢視 最新版本

// ==UserScript==
// @name             Pastel Live 2.0
// @namespace        https://github.com/GameSketchers/Pastel-Live
// @version          2.0.2
// @description      Gartic.io Pastel Live – watch rooms, players and chat in real time.
// @description:tr   Gartic.io Pastel Live – odalari, oyunculari ve sohbeti anlik takip et.
// @author           Qwyua
// @match            *://gartic.io/*
// @match            *://www.croxyproxy.com/*
// @match            *://*/__cpi.php?s=*
// @run-at           document-start
// @grant            GM_addStyle
// @grant            GM_setValue
// @grant            GM_getValue
// @grant            GM_addValueChangeListener
// @grant            GM_removeValueChangeListener
// @grant            GM_xmlhttpRequest
// @grant            unsafeWindow
// @connect          *
// @license          MIT
// ==/UserScript==


// ==>>>> https://gartic.io/pastel <<<<== //


const W=unsafeWindow,B=W.__gmBus??=new EventTarget(),I=Symbol();Object.assign(W,{GM_scriptSendMessage:(c,...d)=>B.dispatchEvent(new CustomEvent(c,{detail:{from:I,data:d}})),GM_scriptOnMessage:(c,f)=>B.addEventListener(c,e=>e.detail.from!==I&&f?.(...e.detail.data))});
const {GM_scriptSendMessage, GM_scriptOnMessage}=W;
const baseHeaders={Accept:"*/*","Content-Type":"application/x-www-form-urlencoded","sec-ch-ua-mobile":"?0","sec-ch-ua-platform":"\"Windows\"","sec-fetch-dest":"document","sec-fetch-mode":"navigate","sec-fetch-site":"none","sec-fetch-user":"?1","upgrade-insecure-requests":"1"};
const [GM_onMessage,GM_sendMessage,getCookie,onBodyReady,observer,rand,GM_req,randomColor]=[
    (k,c)=>GM_addValueChangeListener(k,(_,__,o)=>c(...o)),
    (k,...d)=>GM_setValue(k,d),
    c=>document.cookie.split("; ").find(e=>e.startsWith(c+"="))?.split("=")[1],
    cb=>document.body?cb():new MutationObserver((_,o)=>document.body&&(o.disconnect(),cb())).observe(document.documentElement,{childList:1}),
    (s,c)=>{const w=()=>{const e=document.querySelector(s);e&&(c(e),o.disconnect())};const o=new MutationObserver(w);document.body?o.observe(document.body,{childList:1,subtree:1}):new MutationObserver((_,m)=>{document.body&&(m.disconnect(),o.observe(document.body,{childList:1,subtree:1}))}).observe(document.documentElement,{childList:1})},
    _=>Math.floor(Math.random()*100)+1,
    q=>GM_xmlhttpRequest({...q,onerror:e=>console.error(e)}),
    w=>`rgb(${Math.floor(Math.random()*256)},${Math.floor(Math.random()*256)},${Math.floor(Math.random()*256)},0.20)`
];
document.URL.includes("/__cpi")&&window.self!==window.top&&(async()=>{try{GM_sendMessage('iframe-msg',`succes`,window.location.href)}catch(e){console.error("w",e)}})();
document.URL.includes("pr0xy")&&window.self!==window.top&&(window.name=window.location.search.split('=').pop())|observer('.fa.fa-arrow-right',btn=>btn.dispatchEvent(new MouseEvent("click",{bubbles:!0,button:0})));
document.URL.includes("/servers")&&window.self!==window.top&&observer('input[name=proxyServerId]',e=>{e.value=window.name;e.parentElement.submit()});
document.URL.includes("/requests?fso=")&&window.self!==window.top&&(console.log("wwww")|GM_sendMessage('iframe-msg', 'error'));
//document.URL.includes("")&&window.self!==window.top&&(async()=>{try{const[params,ip,token,reqNum,colors]=[new URL(location.href).searchParams,params.get("ip"),params.get("token"),params.get("req"),{"1":"red","2":"blue","3":"green","4":"orange","5":"purple"}];GM_scriptOnMessage(`req${reqNum}`,msg=>{console.log(`%cScript${reqNum} aldindi:%c${msg.slice(0,50)}`,`color:${colors[reqNum]||"black"};font-weight:bold`,"color:white;background:#222;padding:2px")})}catch(e){}})();
class GM_queue{#s=[];#t=[];#e=[];#i=0;#r=0;#h=!1;#o=!1;constructor({maxConcurrent:s=1,maxConcurrentDynamic:t=1,dynamicThreshold:e=0,retryCountPerItem:i=3,minProcessTime:r=200,maxProcessTime:h=800,retryDelay:o=150,waitForNextApproval:n=!1,onStart:a,onProcess:u,onProgress:m,onError:c,onErrorData:y,onPause:l,onResume:p,onClear:d,onEmpty:g,onFinish:P,onMaxError:w}={}){Object.assign(this,{maxConcurrent:s,maxConcurrentDynamic:t,dynamicThreshold:e,retryCountPerItem:i,minProcessTime:r,maxProcessTime:h,retryDelay:o,waitForNextApproval:n,onStart:a,onProcess:u,onProgress:m,onError:c,onErrorData:y,onPause:l,onResume:p,onClear:d,onEmpty:g,onFinish:P,onMaxError:w}),this.system={queue:this.#s,retryQueue:this.#t,processing:this.#e,done:[],errors:new Map,paused:this.#h,waitForNextApproval:this.waitForNextApproval,enqueue:this.enqueue.bind(this),pause:this.pause.bind(this),resume:this.resume.bind(this),clear:this.clear.bind(this),progress:this.progress.bind(this)}}enqueue(s){const t=s.id??crypto.randomUUID?.()??Math.random().toString(36).slice(2),e={data:s,id:t};this.#s.push(e),this.#r++,this.system.errors.set(t,0),this.onErrorData?.(this.system,s,t),this.#o||(this.#o=!0,this.onStart?.(this.system),this.#n())}async#n(){for(;this.#s.length||this.#t.length||this.#e.length;){if(this.#h){await this.#a();continue}const s=this.#r<this.dynamicThreshold?Math.min(this.maxConcurrentDynamic,this.maxConcurrent):this.maxConcurrent;for(;this.#e.length<s;){let t;if(this.#t.length)t=this.#t.shift();else{if(!this.#s.length)break;t=this.#s.shift()}const{data:e,id:i}=t;this.#e.push({data:e,id:i});const r=((this.#s.length+this.#t.length)/s).toFixed(1);this.onProcess?.(this.system,{qw:e,id:i},{eta:r,current:this.#i+1,total:this.#r});try{await this.#u(e),this.#i++,this.system.processing=this.#e,this.system.done.push({data:e,id:i});let s=!0;if(this.waitForNextApproval&&this.onProgress){const t=this.onProgress(this.system,(this.#i/this.#r*100).toFixed(0),{current:this.#i,total:this.#r,eta:r});s=t instanceof Promise?await t:t}else this.onProgress?.(this.system,(this.#i/this.#r*100).toFixed(0),{current:this.#i,total:this.#r,eta:r});if(!s){this.#s.unshift({data:e,id:i}),this.#e=this.#e.filter((s=>s.id!==i));break}}catch(s){const t=(this.system.errors.get(i)??0)+1;this.system.errors.set(i,t),this.onError?.(this.system,s,e,t),t<this.retryCountPerItem?(await this.#m(this.retryDelay),this.#t.push({data:e,id:i})):this.onMaxError?.(this.system,e,t,i)}finally{this.#e=this.#e.filter((s=>s.id!==i))}}this.#s.length||this.#t.length||this.#e.length||(this.onClear?.(this.system),this.onEmpty?.(this.system),this.onFinish?.(this.system,{current:this.#i,total:this.#r}),this.#c()),this.#e.length>=s&&await this.#m(10)}}pause(){this.#h=!0,this.system.paused=!0,this.onPause?.(this.system)}resume(){this.#h&&(this.#h=!1,this.system.paused=!1,this.onResume?.(this.system))}clear(){this.#s.length=0,this.#t.length=0,this.#e=[],this.system.queue=this.#s,this.system.retryQueue=this.#t,this.system.processing=this.#e,this.onClear?.(this.system)}progress(){return(this.#i/(this.#r||1)*100).toFixed(1)}async#u(s){const t=Math.floor(Math.random()*(this.maxProcessTime-this.minProcessTime)+this.minProcessTime);await this.#m(t)}async#m(s){return new Promise((t=>setTimeout(t,s)))}async#a(){for(;this.#h;)await this.#m(50)}#c(){this.#s=[],this.#t=[],this.#e=[],this.#i=0,this.#r=0,this.system.queue=this.#s,this.system.retryQueue=this.#t,this.system.processing=this.#e,this.system.done=[],this.system.errors=new Map,this.#o=!1,this.system.paused=!1}}
document.URL.includes("https://gartic.io/")&&["/live","/pastel"].some(p=>document.URL.includes(p))&&(()=>{
    GM_addStyle(`*{margin:0;padding:0;box-sizing:border-box}body{font-family:"Segoe UI",sans-serif;height:100vh;display:flex;flex-direction:column;background:linear-gradient(145deg,#1b1a2e,#161429 70%,#12101f);color:#eee;overflow:hidden}.PastelLive-mainTitle{font-size:2em;font-weight:700;text-align:center;padding:20px;background:linear-gradient(90deg,#c2a6f0,#8bbcd4);-webkit-background-clip:text;-webkit-text-fill-color:transparent;text-shadow:0 0 12px #221b3a,0 0 20px #2e224f}#PastelLive-startScreen{position:fixed;inset:0;display:flex;flex-direction:column;justify-content:center;align-items:center;gap:25px;background:linear-gradient(160deg,#0f0c29,#302b63,#24243e);color:#fff;z-index:9999;font-family:"Segoe UI",sans-serif;animation:fadeIn 1s ease;user-select:none}#PastelLive-startScreen h1{font-size:4.5em;color:#ff4e50;position:relative;display:inline-block;letter-spacing:1px}#PastelLive-startScreen h1{font-size:3.5em;background:linear-gradient(270deg, #fffb7d 20%, #ff4e50 40%, #f9d423 60%, #fffb7d 80%);background-size:400% 100%;-webkit-background-clip:text;-webkit-text-fill-color:transparent;animation:shine 7s linear infinite;letter-spacing:1px}#PastelLive-version{font-size:0.20em;bottom:0;right:0;color:#ccc;text-shadow:none}@keyframes shine{0%{background-position:0% 0}100%{background-position:100% 0}}.PastelLive-subtitle{font-size:1.2em;color:#ccc;text-shadow: 0 0 6px #302b63}#PastelLive-startScreen select {padding: 10px 20px;font-size: 1.1em;font-weight: 600;background: #1b1a2e;color: #fff;border: none;outline: none;box-shadow: inset 0 0 5px #ff4e50;transition: 0.2s;}#PastelLive-startScreen select:hover {box-shadow: inset 0 0 12px #f9d423;transform: scale(1.03);}.PastelLive-btn-container {display:flex;flex-direction:column;align-items:center;gap:10px}.PastelLive-btn-row{display:flex;justify-content:center;gap:10px}#PastelLive-startScreen button{padding:12px 28px;font-size:1.1em;font-weight:700;background:linear-gradient(90deg,#ff4e50,#f9d423);color: #0f0c29;border:none;outline:none;cursor:pointer;transition:0.25s;box-shadow:0 0 8px #ff4e50,0 0 12px #f9d423}#PastelLive-startScreen button:hover{transform:scale(1.05);box-shadow:0 0 15px #ff4e50, 0 0 20px #f9d423}.PastelLive-btn-row button:disabled{background:#3a3a4f !important;color:#999 !important;cursor:not-allowed !important;box-shadow:inset 0 0 8px #000 !important}#PastelLive-proxyBtn {background: #1b1a2e;color: #f9d423;box-shadow: 0 0 8px #f9d423;transition: 0.25s;cursor: pointer;opacity: 0.9;}#PastelLive-proxyBtn:hover {transform: scale(1.05);box-shadow: 0 0 15px #f9d423, 0 0 20px #ff4e50;}#PastelLive-proxyBtn:disabled{background:#3a3a4f;color:#999;cursor:not-allowed;box-shadow:inset 0 0 8px #000;pointer-events:none;opacity:0.7}@keyframes fadeIn{from{opacity:0}to{opacity:1}}main.PastelLive-main{flex:1;display:none;grid-template-columns:2fr 1fr;gap:20px;padding:15px;overflow:hidden;opacity:0;animation:fadeIn 0.8s forwards}.PastelLive-left{display:flex;flex-direction:column;gap:12px;overflow:hidden}.PastelLive-filters{display:flex;gap:10px;align-items:center;background:#2a2a3e;padding:10px;border-radius:25px;box-shadow:0 0 8px #8bbcd4;flex-wrap:wrap;justify-content:space-between;opacity:0;animation:fadeIn 0.8s 0.2s forwards}.PastelLive-filters input{flex:2;padding:10px 14px;border-radius:20px;border:none;background:#212133;color:#eee;box-shadow:inset 0 0 6px #8bbcd4}.PastelLive-filters select{flex:1;padding:10px 14px;border-radius:20px;border:none;background:#212133;color:#eee;box-shadow:inset 0 0 6px #8bbcd4}#PastelLive-stats{display:flex;gap:10px;flex-direction:column;color:#c8b6ff;font-size:0.85em}.PastelLive-players{flex:1;overflow-y:auto;display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:15px;padding-right:5px;opacity:0;animation:fadeIn 0.8s 0.4s forwards}.PastelLive-card{background:#212133;border-radius:15px;padding:15px;text-align:center;cursor:pointer;transition:.25s;box-shadow:0 3px 10px #0007;display:flex;flex-direction:column;align-items:center}.PastelLive-card:hover{transform:translateY(-4px) scale(1.03);box-shadow:0 0 15px #c2a6f0,0 0 22px #8bbcd4}.PastelLive-avatar{width:60px;height:60px;border-radius:50%;margin-bottom:10px;background:linear-gradient(135deg,#c2a6f0,#8bbcd4);display:flex;align-items:center;justify-content:center;font-size:1.4em;color:#fff;text-shadow:0 0 3px #000}.PastelLive-name{font-size:1.05em;font-weight:600;margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.PastelLive-status{font-size:.85em}.PastelLive-online{color:#7fffd4}.PastelLive-offline{color:#ff9aa2}.PastelLive-chat{background:#1f1f30;border-radius:15px;display:flex;flex-direction:column;overflow:hidden;box-shadow:0 0 12px #000a;opacity:0;animation:fadeIn 0.8s 0.6s forwards}.PastelLive-chatHeader{background:linear-gradient(90deg, #5510c7, #210d65);padding:10px;color:#000;font-weight:600;font-size:1.1em;display:flex;justify-content:space-between;align-items:center;border-radius:12px 12px 0 0;box-shadow:0 0 10px #000a}.PastelLive-chatButtons{display:flex;gap:5px}.PastelLive-chatButtons button{padding:5px 10px;border:none;border-radius:15px;background:#2a2a3e;color:#fff;cursor:pointer;transition:.2s;box-shadow:0 0 6px #8bbcd4}.PastelLive-chatButtons button:hover{transform:scale(1.05);box-shadow:0 0 10px #c2a6f0}.PastelLive-searchMsg{padding:8px;background:#2a2a3e}.PastelLive-searchMsg input{width:100%;padding:10px;border-radius:20px;border:none;background:#212133;color:#eee;box-shadow:inset 0 0 6px #8bbcd4}.PastelLive-msgs{flex:1;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:10px}.PastelLive-msg{background:#212133;border-radius:12px;padding:8px 12px;max-width:100%;box-shadow:0 0 5px #0007}.PastelLive-msg b{color:#c8b6ff;margin-right:6px}.PastelLive-players::-webkit-scrollbar,.PastelLive-msgs::-webkit-scrollbar{width:10px}.PastelLive-players::-webkit-scrollbar-track,.PastelLive-msgs::-webkit-scrollbar-track{background:#1f1f30;border-radius:10px}.PastelLive-players::-webkit-scrollbar-thumb,.PastelLive-msgs::-webkit-scrollbar-thumb{background:linear-gradient(180deg,#8bbcd4,#c2a6f0);border-radius:10px}.PastelLive-players::-webkit-scrollbar-thumb:hover,.PastelLive-msgs::-webkit-scrollbar-thumb:hover{background:linear-gradient(180deg,#c2a6f0,#8bbcd4)}@media(max-width:900px){main.PastelLive-main,#PastelLive-app.PastelLive-main {grid-template-columns:1fr;grid-template-rows:1fr 1fr;}}@media(max-width:500px){.PastelLive-players,#PastelLive-players {grid-template-columns:repeat(auto-fill,minmax(140px,1fr));}.PastelLive-avatar{width:55px;height:55px;font-size:1.2em;}}.PastelLive-credit{position:absolute;bottom:10px;left:10px;font-size:15px;color:#bbb;font-family:"Segoe UI",sans-serif;opacity:0.8}.PastelLive-credit a{color:#6cf;text-decoration:none;font-weight:600}.PastelLive-credit a:hover{text-decoration:underline}.PastelLive-credit .heart{color:#e25555;margin:0 2px}.PastelLive2-search-container{max-width:1200px;width:100%;padding:15px 20px;border-radius:15px;box-shadow:0 10px 30px rgba(0,0,0,0.3);align-items:center;margin:0 auto;margin-bottom:20px;box-sizing:border-box}.PastelLive2-search-input-container{display:flex;gap:12px;align-items:center;justify-content:center;margin-bottom:15px}.PastelLive2-search-input{flex:1;max-width:500px;padding:12px 16px;border:2px solid rgba(255,255,255,0.1);border-radius:10px;background:rgba(26,32,44,0.8);color:#e2e8f0;font-size:16px}.PastelLive2-search-input:focus{outline:none;border-color:#4299e1;box-shadow:0 0 0 3px rgba(66,153,225,0.3)}.PastelLive2-player-list{width:100%;height:70vh;padding:0 25px 25px 25px;box-sizing:border-box;display:grid;grid-template-columns:repeat(auto-fit, minmax(200px, 1fr));grid-gap:20px;overflow-y:auto;overflow-x:hidden}.PastelLive2-player-list::-webkit-scrollbar{width:8px}.PastelLive2-player-list::-webkit-scrollbar-track{border-radius:4px}.PastelLive2-player-list::-webkit-scrollbar-thumb{border-radius:4px}.PastelLive2-player-card{height:80px;position:relative;background-color:#fff;border-radius:5px;padding:10px;box-shadow:0 2px 4px rgba(0,0,0,0.1);display:flex;align-items:center;cursor:pointer;transition:transform 0.3s ease}.PastelLive2-player-card:hover{transform:translateY(-3px);box-shadow:0 8px 20px rgba(0,0,0,0.4);border-color:#4299e1}.PastelLive2-player-avatar{width:60px;height:60px;border-radius:50%;margin-right:10px}.PastelLive2-player-info{flex:1}.PastelLive2-player-name{font-weight:bold;font-size:16px;color:#e0e0e0;margin-bottom:5px;text-shadow:1px 1px 2px rgba(0,0,0,0.6)}.PastelLive2-player-id{font-size:14px;color:#888;margin-bottom:5px}.PastelLive2-player-status{font-size:14px;color:#888}.PastelLive2-win {position:absolute;left:0;bottom:0;width:36px;height:36px;background-image:url(https://gartic.io/static/images/new/trofeu.svg);background-size:contain;background-repeat:no-repeat;background-position:center;display:flex;align-items:center;justify-content:center}.PastelLive2-win span{display:inline-block;transform:translateY(-4px);font-family:"NunitoBlack";font-size:12px;color:#043172}.PastelLive2-search-info{display:flex;justify-content:center;gap:20px;margin-top:15px;flex-wrap:wrap}.PastelLive2-search-info h5{margin:0;padding:6px 12px;background:rgba(45,55,72,0.6);border-radius:6px;color:#a0aec0;font-size:12px;border:1px solid rgba(255,255,255,0.1)}`)
    const overlay = Object.assign(document.createElement('div'),{id:'PastelLiveOverlay',style:'position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:999;background:#161429;overflow:hidden;display:flex;flex-direction:column;font-family:"Segoe UI",sans-serif;color:#eee;'});
    overlay.innerHTML = `
            <div class="PastelLive-mainTitle">Pastel Live</div>
               <div id="PastelLive-startScreen">
               <h1>Pastel Live<span id="PastelLive-version">v2.0.2</span></h1>
               <p class="PastelLive-subtitle">Select Language & Start</p>
               <select id="PastelLive-lang">
                  <option value="all">All Languages</option>
                  <option value="2">English</option>
                  <option value="8">Türkçe</option>
                  <option value="1">Português</option>
                  <option value="45">Bahasa Indonesia</option>
                  <option value="7">Русский</option>
                  <option value="3">Español</option>
                  <option value="19">العربية</option>
                  <option value="23">Azərbaycanca</option>
                  <option value="11">Čeština</option>
                  <option value="14">Deutsch</option>
                  <option value="4">Français</option>
                  <option value="6">Italiano</option>
                  <option value="44">Magyar</option>
                  <option value="18">Nederlands</option>
                  <option value="10">Polski</option>
                  <option value="58">Română</option>
                  <option value="22">Slovenčina</option>
                  <option value="13">Tiếng Việt</option>
                  <option value="21">български език</option>
                  <option value="40">עברית</option>
                  <option value="34">فارسی</option>
                  <option value="12">ภาษาไทย</option>
                  <option value="16">中文 (简化字)</option>
                  <option value="9">中文 (臺灣)</option>
                  <option value="17">中文 (香港)</option>
                  <option value="15">日本語</option>
                  <option value="20">한국어</option>
               </select>
               <div class="PastelLive-btn-container">
               <button id="PastelLive-proxyBtn">Get Proxy (0)</button>
                <div class="PastelLive-btn-row">
                  <button id="PastelLive-liveBtn">Live</button>
                  <button id="PastelLive-whowhereBtn">Who Where</button>
                </div>
               </div>
               <div class="PastelLive-credit">GameSketchers • by <a href="https://github.com/GameSketchers/Pastel-Live" target="_blank">Qwyua</a>  <span class="heart">♥</span> with love</div>
            </div>
            <main id="PastelLive-app" class="PastelLive-main" style="display:none;flex:1;grid-template-columns:2fr 1fr;gap:20px;padding:15px;overflow:hidden;">
              <div class="PastelLive-left">
                <div class="PastelLive-filters">
                   <input id="PastelLive-search" placeholder="oyuncu ara">
                   <input id="PastelLive-roomCode" placeholder="oda kodu">
                   <div id="PastelLive-stats">
                      <span id="PastelLive-activePlayers">Aktif Oyuncular: 0</span>
                      <span id="PastelLive-activeRooms">Aktif Odalar: 0</span>
                   </div>
                </div>
                <div class="PastelLive-players" id="PastelLive-players"></div>
            </div>
            <div class="PastelLive-chat">
                <div class="PastelLive-chatHeader">Chat
                    <div class="PastelLive-chatButtons">
                        <button id="PastelLive-saveChat">Kaydet</button>
                        <button id="PastelLive-resetChat">Reset</button>
                    </div>
                </div>
                <div class="PastelLive-searchMsg"><input id="PastelLive-msgSearch" placeholder="mesaj ara"></div>
                <div class="PastelLive-msgs" id="PastelLive-msgs">
                </div>
            </div>
        </main>
        <main id="PastelLive-app" class="PastelLive-main" style="display:none;flex:1;grid-template-columns:2fr 1fr;gap:20px;padding:15px;overflow:hidden;">
         <div class="PastelLive2-search-container">
              <div class="PastelLive2-search-input-container">
                <input type="text" class="PastelLive2-search-input" placeholder="Oyuncu arayın">
              </div>
              <div class="PastelLive2-search-info">
                <h5 class="PastelLive2-players-log">oyuncu: 0</h5>
                <h5 class="PastelLive2-rooms-log">odalar: 0</h5>
                <h5 class="PastelLive2-searchspeed-log">arama hızı: </h5>
              </div>
         </div>
         <div class="PastelLive2-player-list"></div>
        </main>
    `;
    document.documentElement.prepend(overlay);

    class PastelLive {
      CURRENT_VERSION = "2.0.2"
      proxies=GM_getValue("PastelLive-Proxies");
      servers={"server07":"c","server06":"Y","server05":"U","server04":"Q","server03":"M","server02":"I","server01":"E"};
      proxylist=["198.23.160.245","217.154.250.99","38.135.25.236","104.223.85.164","45.136.30.85","205.185.122.126","38.135.25.235"]
      static ProxyRotator=class{constructor(proxyList=[]){if(!Array.isArray(proxyList)||proxyList.length===0){throw new Error("Proxy listesi boş olamaz.")};this.proxyList=proxyList;this.index=0}nextProxy(){const proxy=this.proxyList[this.index];this.index=(this.index+1)%this.proxyList.length;return proxy}}
      static PlayerSt=class{
        map=new Map();
        constructor(list=[]){list.forEach(p=>this.map.set(String(p.id),p.name))}
        add=q=>this.map.set(String(q.id),q.name);
        getName=w=>this.map.get(String(w))??null;
        remove=y=>this.map.delete(String(y));
        update=(u,a)=>this.map.has(String(u))&&this.map.set(String(u),a);
      }
      odalar=0;
      oyuncular=0;
      whmod=!1;
      plst = new PastelLive.PlayerSt([]);
      constructor(overlay) {
        this.overlay = overlay;
        this.playersContainer = overlay.querySelector("#PastelLive-players");
        this.messagesContainer = overlay.querySelector("#PastelLive-msgs");
        this.startScreen = overlay.querySelector("#PastelLive-startScreen");
        this.liveTitle = overlay.querySelector(".PastelLive-mainTitle")
        this.playerslog2 = overlay.querySelector(".PastelLive2-players-log")
        this.roomslog2 = overlay.querySelector(".PastelLive2-rooms-log")
        this.searchspeedlog2 =  overlay.querySelector(".PastelLive2-searchspeed-log")
        this.app = overlay.querySelector("#PastelLive-app");
        this.app2 = overlay.querySelector("#PastelLive-app:nth-of-type(2)");
        this.activePlayersSpan = overlay.querySelector("#PastelLive-activePlayers");
        this.activeRoomsSpan = overlay.querySelector("#PastelLive-activeRooms");
        this.liveButton = overlay.querySelector("#PastelLive-liveBtn");
        this.whowhereButton = overlay.querySelector("#PastelLive-whowhereBtn");
        this.proxyButton = overlay.querySelector("#PastelLive-proxyBtn")
        this.activePlayers = overlay.querySelector("#PastelLive-activePlayers")
        this.activeRooms = overlay.querySelector("#PastelLive-activeRooms")
        this.searchInput = overlay.querySelector("#PastelLive-search");
        this.roomInput = overlay.querySelector("#PastelLive-roomCode");
        this.msgSearchInput = overlay.querySelector("#PastelLive-msgSearch");
        this.langSelect = overlay.querySelector("#PastelLive-lang")
        this.langSelect.addEventListener("change",()=>{GM_setValue("PastelLive-lang",this.langSelect.value)});
        this.initEvents();
        this.proxyRotator = new PastelLive.ProxyRotator(this.proxylist);
        GM_getValue("version")!==this.CURRENT_VERSION&&(GM_setValue("version",this.CURRENT_VERSION),GM_setValue("PastelLive",{}),GM_setValue("PastelLive-Proxies",[]),GM_setValue("iframe-msg",[]),location.reload());
        if (this.proxies === undefined){this.proxies=[];GM_setValue("PastelLive-Proxies", this.proxies)}
            if (Array.isArray(this.proxies)&&this.proxies.length===0){
                this.liveButton.disabled=!0;
                this.whowhereButton.disabled=!0;
                this.proxies=[];
                GM_setValue("PastelLive-Proxies",this.proxies);
            }
            Array.isArray(this.proxies)&&this.proxies.length&&(()=>{
                const ws = new WebSocket(`wss://${this.proxies[0].ip}/__cpw.php?u=d3NzOi8vc2VydmVyMDYuZ2FydGljLmlvL3NvY2tldC5pby8/RUlPPTMmdHJhbnNwb3J0PXdlYnNvY2tldA==&o=aHR0cHM6Ly9nYXJ0aWMuaW8=`);
                ws.onopen=()=>{ws.close()};
                ws.onerror=()=>{GM_setValue("PastelLive-Proxies",this.proxies=[]);location.reload()};
            })();
            this.proxyButton.textContent = `Get Proxy (${this.proxies?.length||0})`;

      }

      checkDeepProxy(yua){
        const{ip,cookie:cpc,poss}=yua.proxy,{iframeMode,room}=yua,host=this.proxyRotator.nextProxy();
        return new Promise((ok, fail)=>{const hdr=`__poss@${host}=${poss};__cpc=${cpc}`,
        yurl=`https://${ip}/server?check=1&v3=1&room=${room}&__pot=aHR0cHM6Ly9nYXJ0aWMuaW8&__cpo=${btoa(`https://${host}`)}`;
        GM_req({method:"GET",url:yurl,headers:{...baseHeaders,Cookie:hdr},
        onloadend:(r4)=>{const finalURL=r4.responseText.match(/this\.permalink\s*=\s*this\.URI\(['"]([^'"]+)['"]\)/)?.[1];
        if(!finalURL){ok({info:{ip,cpc,room},response:r4.responseText});return}
        GM_req({method:"POST",url:finalURL,headers:{...baseHeaders,Cookie:hdr,"Content-Type":"application/json"},
        onloadend:(r5)=>{if(r5.responseText.includes("gartic.io:443?c")){ok({info:{ip,cpc,room},response:r4.responseText});return}
        else{fail({info:{ip,cpc,room},response:null})}
        }});}});});
      }

      initEvents(){
        this.searchInput.addEventListener("input",()=>this.filterPlayers());
        this.roomInput.addEventListener("input",()=>this.filterPlayers());
        this.msgSearchInput.addEventListener("input",()=>this.filterChat());
        this.liveButton.addEventListener("click",()=>{
        const lang = document.querySelector("#PastelLive-lang").value;
        if(lang==="all"&&this.proxies.length<50){alert("To use this feature, you need at least 50 proxies.");return}
        this.startScreen.style.display = "none";
        this.app.style.display = "grid";
        this.playerSearchGO(lang);
        });
        this.whowhereButton.addEventListener("click", () => {
        const lang = document.querySelector("#PastelLive-lang").value;
        if (lang==="all"&&this.proxies.length<50){alert("To use this feature, you need at least 50 proxies.");return}
        this.whmod=!0;
        this.playerSearchGO(lang)
        this.startScreen.style.display = "none";
        this.liveTitle.style.display = "none"
        this.searchspeedlog2.innerText = `arama hızı: x${this.proxies.length}`
        this.app2.style.display = "block";
        });
        this.proxyButton.addEventListener('click',()=>{
        this.liveButton.disabled=!0;
        this.proxyButton.disabled=!0;
        this.whowhereButton.disabled=!0;
        this.addNewProxy()
        });
      }

      filterChat(){[...this.messagesContainer.children].forEach(msg=>{msg.style.display = msg.textContent.toLowerCase().includes(this.msgSearchInput.value.toLowerCase())?"block":"none"})}
      async addNewProxy(){try{
          const data=await GM_getValue('PastelLive');
          this.proxies=GM_getValue("PastelLive-Proxies")??[];
          const list=data?.ProxyList??[];
          if(!list.length) return console.log('!asd');
          const existing=new Set(this.proxies.map(p => p.ip));
          const limit=existing.size?15:10;
          const newProxies=list.map(x=>x.ip).filter(ip=>!existing.has(ip)).slice(0,limit);
          if(!newProxies.length) return console.log('!!asd');
          const targets=list.filter(x=>newProxies.includes(x.ip)).slice(0,15);
          console.log(targets);
          targets.forEach(x=>document.body.append(Object.assign(document.createElement`iframe`,{
          id:'proxy-iframe-'+x.id,
          style:'display:none!important;width:0;height:0;opacity:0;pointer-events:none;position:absolute;top:0;left:0;z-index:-9999',
          src:`https://www.croxyproxy.com/?pr0xy=true&proxyid=${x.id}`,
          sandbox:'allow-scripts allow-same-origin allow-forms allow-top-navigation'})));
          const proxiesWithCookies=await new Promise(resolve=>{
          const c=[],t=setTimeout(()=>resolve(c),30e3);
          const h=(_,u)=>{try{const ip=new URL(u).hostname;
          GM_req({method:"GET",url:u,headers:baseHeaders,
          onload:r1=>{const cpc=r1.responseHeaders.match(/set-cookie:\s*__cpc=([^;\r\n]+)/i)?.[1];
          if(!cpc) return;
          GM_req({method:"POST",url:`https://${ip}/?__cpo=aHR0cHM6Ly9wcm94eW9yYi5jb20`,headers:{...baseHeaders,Cookie:`__cpc=${cpc}`},
          onload:r2=>{const poss=r2.responseText.match(/\\"initialToken\\":\\"([^\\]+)\\"/)?.[1];
          if(!poss) return;
          c.push({ip,cookie:`${cpc};`,poss:`${poss}`});
          if(c.length>=targets.length){clearTimeout(t);GM_removeValueChangeListener?.('iframe-msg',h);resolve(c)}
          }});}});}catch(e){console.error("proxy handler error", e)}};
          GM_onMessage('iframe-msg',h)});
          this.proxies.push(...proxiesWithCookies);
          GM_setValue("PastelLive-Proxies",this.proxies);
          this.proxyButton.textContent=`Get Proxy (${this.proxies.length})`;
          this.proxyButton.disabled=!9;
          this.liveButton.disabled=!8;
          this.whowhereButton.disabled=!7;
          document.querySelectorAll('iframe')?.forEach(f=>f.remove());
          console.log("✅ Added proxies:", proxiesWithCookies);
          }catch(err){console.error(err)}
      }

      getSocialMedia=(url)=>{
        const socialMedia=(url.match(/discordapp|redditmedia|googleusercontent|twimg\.com|gartic\.io|facebook|fbsbx\.com|userapi\.com/i)||[''])[0].toLowerCase();
        const mediaMap={
        "discordapp":"Discord",
        "redditmedia":"Reddit",
        "googleusercontent":"Google",
        "twimg.com":"Twitter",
        "facebook":"Facebook",
        "fbsbx.com":"Facebook",
        "userapi.com":"Vkontakte",
        "gartic.io":"Gartic",
        };
        return mediaMap[socialMedia]||null;
      };

      handlePlayerData(data,code){
        const cardColor = randomColor();
        const playerList = this.overlay.querySelector(".PastelLive2-player-list");
        const playersLog = this.overlay.querySelector(".PastelLive2-players-log");
        const roomsLog = this.overlay.querySelector(".PastelLive2-rooms-log");
        const fragment = document.createDocumentFragment();
        data[5].forEach(player=>{
          const foto = player.foto??"https://gartic.io/static/images/avatar/svg/"+player.avatar+".svg";
          const card = Object.assign(document.createElement("div"),{
          className: "PastelLive2-player-card",
          innerHTML:'<img class="PastelLive2-player-avatar" src="'+foto+'">'+'<div class="PastelLive2-player-info">'+
          '<div class="PastelLive2-player-name">'+player.nick+'</div>'+
          '<a href="https://gartic.io/'+code+'" target="_blank" class="PastelLive2-player-id">#'+code+'</a>'+
          '<div class="PastelLive2-player-status"><span class="PastelLive2-status">'+this.getSocialMedia(foto)+'</span></div>'+
          '</div>'+
          (player.vitorias?'<span class="PastelLive2-win"><span>'+player.vitorias+'</span></span>':'')
          });
          card.setAttribute("name", player.id);
          card.style.backgroundColor = cardColor;
          //card.addEventListener("click", () => this.createPopup(player, foto, data[4], data[5].length));
          fragment.appendChild(card);
          playersLog.innerText = `oyuncular: ${++this.oyuncular}`;
        });
        playerList.appendChild(fragment);
        roomsLog.innerText = `odalar: ${++this.odalar}`;
      }



      addMessage(author,text,room){
        const msg = document.createElement("div");
        msg.className = "PastelLive-msg";
        msg.innerHTML = `<b>${room}${author}:</b> ${text}`;
        this.messagesContainer.appendChild(msg);
        this.filterChat()
      }

      filterPlayers(){
        const q = this.searchInput.value.toLowerCase(),
        r=this.roomInput.value.toLowerCase();
        [...this.playersContainer.children].forEach(card=>{
        const name=card.querySelector(".PastelLive-name").textContent.toLowerCase();
        const room=card.querySelector(".PastelLive-status").textContent.toLowerCase();
        card.style.display=(name.includes(q)&&room.includes(r))?"flex":"none"});
        const visible=[...this.playersContainer.children].filter(c=>c.style.display!=="none");
        this.activePlayersSpan.textContent=`Aktif Oyuncular: ${visible.length}`;
        this.activeRoomsSpan.textContent=`Aktif Odalar: ${new Set(visible.map(c=>c.querySelector(".PastelLive-status").textContent)).size}`;
      }
      startLiveRoomAction(inf,servertext,succ,proc=6){
        let server=(()=>{try{return new URL(servertext).hostname.split(".")[0]}catch{return null}})()??`server0${proc}`;
        const scode = this.servers[server];
        const roomid = inf.room.substring(2)
        const websocket = new WebSocket(`wss://${inf.ip}/__cpw.php?u=d3NzOi8vc2VydmVyMD${scode}uZ2FydGljLmlvL3NvY2tldC5pby8/RUlPPTMmdHJhbnNwb3J0PXdlYnNvY2tldA==&o=aHR0cHM6Ly9nYXJ0aWMuaW8=`);
        websocket.onopen = () => {
          websocket.send(`42[12,{"v":20000,"sala":"${roomid}"}]`);
          !this.whmod&&websocket.send(`42[46,0]`);
          const ping=()=>{
            if(websocket.readyState===WebSocket.OPEN){
             websocket.send("2");
             setTimeout(ping,7e3);
            }
          };
          !this.whmod&&ping();
        };
        websocket.onmessage=e=>{
          try{
            if (!e.data.startsWith("42")) return;
            const data=JSON.parse(e.data.slice(2));
            if(data[0]==="5"){inf.roomdetails=`(${data[4].tema.split(" ")[0]} ${data[4].codigo.slice(-3)}) ~ `;this.whmod?(()=>{websocket.close();this.handlePlayerData(data,inf.room)})():(()=>{for(const player of data[5]){this.plst.add({id:player.id,name:player.nick});this.addPlayer(player.foto??`https://gartic.io/static/images/avatar/svg/${player.avatar}.svg`,player.nick,inf.room);this.activePlayers.innerText = `oyuncular: ${++this.oyuncular}`}this.activeRooms.innerText = `odalar: ${++this.odalar}`})()}
            if(!servertext||data[1]==6){websocket.close();
            if(!servertext&&this.whmod){console.error("asdsaddsa",proc);const nextProcMap={6:2,2:5,5:4,4:3,3:1,1:7},nextProc=nextProcMap[proc];
            nextProc&&setTimeout(()=>this.startLiveRoomAction(inf,!7,succ,nextProc),200)}}
            !this.whmod&&data[0]==="11"&&this.addMessage(this.plst.getName(data[1]),data[2],inf.roomdetails)
          }catch{}
        };
        websocket.onerror=e=>{};
      }

      addPlayer(avatar,name,room){
        const card = Object.assign(document.createElement("div"),{className:"PastelLive-card"});
        card.append(Object.assign(document.createElement("img"),{className:"PastelLive-avatar",src:avatar}),
        Object.assign(document.createElement("div"),{className:"PastelLive-name",textContent:name}),
        Object.assign(document.createElement("div"),{className:"PastelLive-status",textContent:`Oda Kodu: ${room}`}));
        this.playersContainer.appendChild(card);
        this.filterPlayers();
      }
      logRoomServer(d,s){console.log("%c🌟 Live Room Started! 🌟\nIP: "+d.ip+"\nRoom: "+d.room+"\nServer: "+s,"background:linear-gradient(90deg,#ff6ec4,#7873f5);color:white;font-size:20px;font-weight:bold;padding:10px 20px;border-radius:10px;text-shadow:2px 2px 4px rgba(0,0,0,0.3)")}

      miniNotificationPopup=(()=>{let t,e;return a=>{t||(t=document.createElement("div"),Object.assign(t.style,{position:"fixed",top:"20px",right:"20px",background:"linear-gradient(135deg, #ff7e5f, #feb47b)",color:"#fff",padding:"15px 25px",borderRadius:"15px",boxShadow:"0 8px 25px rgba(0,0,0,0.4)",fontFamily:"Arial, sans-serif",fontSize:"16px",fontWeight:"bold",opacity:"0",transform:"translateX(50px)",transition:"opacity 0.5s ease, transform 0.5s ease",maxWidth:"350px",pointerEvents:"none",zIndex:9999}),document.body.appendChild(t)),t.textContent=a,t.style.opacity="1",t.style.transform="translateX(0)",e&&clearTimeout(e),e=setTimeout((()=>{t.style.opacity="0",t.style.transform="translateX(50px)"}),2500)}})();
      async playerSearchGO(languagecode){
        try{
          console.log("calisiyom abi")
          const langOrder=[23,1,8,2,9,7,45,13,11,16,19];
          const allRooms=[];
          for(const lang of"all"===languagecode?langOrder:[languagecode]){let a=await new Promise((a,e)=>{GM_xmlhttpRequest({method:"GET",url:`https://gartic.io/req/list?search=&language[]=${lang}`,onload(t){try{a(JSON.parse(t.responseText))}catch(r){e(r)}},onerror:a=>e(a)})});allRooms.push(...a.filter(({quant:a})=>a>0)),await new Promise(a=>setTimeout(a,1e3))}
          const proxies=await GM_getValue("PastelLive-Proxies");
          const roomCodes=allRooms.map(({code:o})=>o);
          const xmlplugins=["yua"];
          const proxyToRooms=roomCodes.map((o,e)=>({room:o,proxy:proxies[e%proxies.length],iframeMode:xmlplugins[e%xmlplugins.length]}));
          console.log(proxyToRooms)
          this.queue = new GM_queue({
            ...(this.whmod&&{minProcessTime:100,maxProcessTime:200}),
            onStart:system=>console.log("▶️ Kuyruk baslatildi."),
            onProcess:(system, im, stats)=>{
              this.checkDeepProxy(im.qw.yua)
              .then(({info,response})=>{this.logRoomServer(info,response);this.startLiveRoomAction(info,response,true);})
              .catch(({info,response})=>{this.startLiveRoomAction(info,!7,!6)});
            },
            onProgress:(system,percent,stats)=>this.miniNotificationPopup(`📊 ${percent}% (${stats.current}/${stats.total})`)
          });
          for(const proxyToRoom of proxyToRooms){
            const {ip,cookie:cpc}=proxyToRoom.proxy;
            const {iframeMode,room}=proxyToRoom;
            if("yua"!==iframeMode){let e=document.createElement("iframe");e.src="aHR0cHM6Ly86RC8/cmVxPSZpcD0mdG9rZW49",Object.assign(e.style,{display:"block",position:"fixed",bottom:"10px",right:"10px",width:"400px",height:"300px",zIndex:9999999999}),document.body.appendChild(e)}
            else this.queue.enqueue({yua:proxyToRoom})}
          }catch(e){console.log(e)}
      }

      async initProxies(){
        try{
          this.langSelect.value = await GM_getValue("PastelLive-lang", "all");
          const existing = await GM_getValue('PastelLive');
          if(existing&&(typeof existing!=="object"||Object.keys(existing).length>0))return console.log('PastelLive running...');
          const json = await (await fetch('https://raw.githubusercontent.com/Qwyua/ProxyModule/main/src/ProxyModuleList.json')).json();
          const newProxies = json?.proxyList?.filter(p=>p.active&&!p.ip.startsWith('51.'))??[];
          const data = {ProxyList:newProxies,runProxy:!0};
          await GM_setValue('PastelLive', data);
          console.log('PastelLive Started.', data);
        }catch(e){console.error('PastelLive error!',e)}
      }
    }

    (async () => {
        const overlay = document.querySelector('#PastelLiveOverlay');
        const live = new PastelLive(overlay);
        await live.initProxies();
    })();


})();