⚠️警告⚠️
コマンド一覧
/omikuji/おみくじ
/good/大きく👍️の文字
/name.henkou.変更名/名前変更
/game/ゲーム
/big太文字にしたい文字/太文字送信
/p.m.送信する人の名前.メッセージ/プライベートメッセージ
/IP.ban.BANする人の名前/IP BAN 管理者専用
/anauns.アナウンス内容/アナウンス変更 管理者専用
/log out.everyone/全員を強制ログアウト 特権管理者専用
管理者専用のコマンドは、一般ユーザーが入力しても実行されません。

ASTREX.ch

表示名を入力して入室してください(あとでプロフィールから変更できます)

アカウントコードは「パスワード代わりの合言葉」です。同じコードを入れると、別の端末やブラウザからでも同じ名前・アイコン・設定のアカウントに入れます。空欄のままでもこの端末専用のゲストとして利用できます。他の人には教えないでください。

ver.2.8.1

お知らせ

0/250

管理者が追加したショートカット一覧です

読み込み中...
VOICE / VIDEO ROOM未接続
未接続
")).join("|"),"gi");function filterOn(){return lsGet("astrex-ngfilter","1")!=="0";}function maskText(t){return t.replace(NG_RE,"***");}function maskHTML(html){return html.replace(/(^|>)([^<>]+)/g,(m,a,t)=>a+maskText(t));}function applyFilter(){const on=filterOn();document.querySelectorAll(".msg-content").forEach(el=>{if(el.dataset.axOrig===undefined)el.dataset.axOrig=el.innerHTML;const orig=el.dataset.axOrig;const want=on?maskHTML(orig):orig;if(el.innerHTML!==want)el.innerHTML=want;if(!on&&el.dataset.axOrig!==undefined)el.dataset.axOrig=el.innerHTML;});}(function filterUI(){function build(){const sec=$("sec-tools");if(!sec||$("ax-ngfilter-toggle"))return;const body=sec.querySelector(".sb-body");if(!body)return;const label=document.createElement("label");label.textContent="不適切ワードフィルター";const row=document.createElement("div");row.className="toggle-row";row.style.margin="0";row.innerHTML='不適切な言葉を***で隠す';const note=document.createElement("div");note.className="sb-note";note.textContent="ONにすると不適切な言葉が「***」で表示されます(初期設定はON・自分の画面だけ)";body.appendChild(label);body.appendChild(row);body.appendChild(note);const cb=$("ax-ngfilter-toggle");cb.checked=filterOn();cb.addEventListener("change",()=>{lsSet("astrex-ngfilter",cb.checked?"1":"0");/* 表示を作り直すため、保存済みの原文から再適用する */document.querySelectorAll(".msg-content").forEach(el=>{if(el.dataset.axOrig!==undefined&&!cb.checked)el.innerHTML=el.dataset.axOrig;});applyFilter();T(cb.checked?"不適切ワードを***で隠します":"不適切ワードをそのまま表示します");});}build();setInterval(build,2500);})();setInterval(applyFilter,700);/* ---------- 10. 参加者一覧をオンライン/オフラインで表示 ---------- */(function participants(){function ensureModal(){let m=$("ax-people-modal");if(!m){m=document.createElement("div");m.id="ax-people-modal";m.className="ax-prof-modal";m.innerHTML='
現在の参加者
';document.body.appendChild(m);m.addEventListener("click",e=>{if(e.target===m)m.classList.remove("show");});m.querySelector("#ax-people-close").addEventListener("click",()=>m.classList.remove("show"));}return m;}async function openPeople(){const m=ensureModal();m.classList.add("show");const body=$("ax-people-body");body.innerHTML='
読み込み中…
';let all={},pres={};try{all=await sGetJSON("all-users",true,{})||{};}catch(e){}try{pres=await sGetJSON("presence",true,{})||{};}catch(e){}const now=Date.now();const isOnline=(id)=>{const p=pres[id];const t=p&&(p.time||p.t||p.last)||0;return now-t<70000;};const entries=Object.entries(all).filter(([id,u])=>u&&u.name);Object.entries(pres).forEach(([id,p])=>{if(!all[id]&&p&&p.name)entries.push([id,p]);});const online=entries.filter(([id])=>isOnline(id));const offline=entries.filter(([id])=>!isOnline(id));const rowHTML=(id,u,on)=>{const color=esc(u.color||"#2E7CF6");const av=u.icon?'':'';return '
'+av+''+esc(u.name||"名無し")+''+''+(on?"● オンライン":"○ オフライン")+'
';};body.innerHTML='
オンライン('+online.length+'人)
'+(online.length?online.map(([id,u])=>rowHTML(id,u,true)).join(""):'
オンラインの人はいません
')+'
オフライン('+offline.length+'人)
'+(offline.length?offline.map(([id,u])=>rowHTML(id,u,false)).join(""):'
オフラインの人はいません
');}function bind(){const btn=$("ax-online-btn");if(btn&&!btn.dataset.axBound){const clone=btn.cloneNode(true);clone.dataset.axBound="1";btn.parentNode.replaceChild(clone,btn);clone.addEventListener("click",openPeople);}}bind();setInterval(bind,2000);})();/* ---------- スタイル ---------- */const css=document.createElement("style");css.textContent=` /* --- プロフィールカード(近未来HUD) --- */ .ax-prof-card{position:relative;width:100%;display:flex;align-items:center;gap:11px;padding:12px 13px; border:1px solid color-mix(in srgb,var(--blue) 45%,var(--border));border-radius:14px;color:var(--text); background:linear-gradient(135deg,color-mix(in srgb,var(--blue) 12%,var(--bg2)) 0%,var(--bg2) 55%,color-mix(in srgb,var(--blue-deep) 30%,var(--bg2)) 100%); cursor:pointer;text-align:left;overflow:hidden;transition:.2s cubic-bezier(.2,.8,.2,1); box-shadow:0 0 0 1px rgba(255,255,255,.02) inset,0 8px 22px rgba(0,0,0,.35);} .ax-prof-card:hover{transform:translateY(-2px);border-color:var(--blue-glow); box-shadow:0 0 18px color-mix(in srgb,var(--blue) 45%,transparent),0 10px 26px rgba(0,0,0,.42);} .ax-prof-card .ax-corner{position:absolute;width:10px;height:10px;border:1.5px solid var(--blue-glow);opacity:.75;pointer-events:none;} .ax-prof-card .ax-corner.tl{top:5px;left:5px;border-right:0;border-bottom:0;} .ax-prof-card .ax-corner.tr{top:5px;right:5px;border-left:0;border-bottom:0;} .ax-prof-card .ax-corner.bl{bottom:5px;left:5px;border-right:0;border-top:0;} .ax-prof-card .ax-corner.br{bottom:5px;right:5px;border-left:0;border-top:0;} .ax-prof-card .ax-scan{position:absolute;inset:0;pointer-events:none; background:linear-gradient(100deg,transparent 40%,color-mix(in srgb,var(--blue-glow) 22%,transparent) 50%,transparent 60%); transform:translateX(-120%);} .ax-prof-card:hover .ax-scan{animation:axScan 1.1s ease;} @keyframes axScan{to{transform:translateX(120%);}} .ax-av-ring{position:relative;flex-shrink:0;width:44px;height:44px;border-radius:50%;padding:2px; background:conic-gradient(from 0deg,var(--blue-glow),transparent 35%,var(--blue) 65%,var(--blue-glow));} @keyframes axSpin{to{transform:rotate(360deg);}} .ax-av-ring img{width:100%;height:100%;border-radius:50%;object-fit:cover;background:var(--blue);display:block;} .ax-av-dot{display:none !important;} .ax-prof-meta{display:flex;flex-direction:column;min-width:0;flex:1;gap:1px;} .ax-prof-tag{font-family:'Orbitron',sans-serif;font-size:.52rem;letter-spacing:.16em;color:var(--blue-glow);opacity:.85;} .ax-prof-name{font-weight:800;font-size:.9rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;} .ax-prof-id{font-family:'Orbitron',monospace;font-size:.58rem;letter-spacing:.06em;color:var(--text-soft); white-space:nowrap;overflow:hidden;text-overflow:ellipsis;} .ax-prof-go{color:var(--blue-glow);font-size:1.2rem;transition:transform .2s;} .ax-prof-card:hover .ax-prof-go{transform:translateX(3px);} .ax-prof-note{opacity:.75;} /* --- モーダル(コンソール風) --- */ .ax-prof-modal{position:fixed;inset:0;z-index:99999;background:rgba(3,6,12,.72);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;padding:16px;} .ax-prof-modal.show{display:flex;} .ax-prof-panel{position:relative;width:min(540px,96vw);max-height:88vh;display:flex;flex-direction:column; background:linear-gradient(180deg,color-mix(in srgb,var(--blue-deep) 22%,var(--panel)) 0%,var(--panel) 32%); border:1px solid color-mix(in srgb,var(--blue) 40%,var(--border));border-radius:18px;overflow:hidden; box-shadow:0 0 40px color-mix(in srgb,var(--blue) 25%,transparent),0 30px 80px rgba(0,0,0,.6); animation:axPop .22s cubic-bezier(.2,1.3,.4,1);} @keyframes axPop{from{opacity:0;transform:translateY(10px) scale(.985);}} .ax-prof-panel .ax-beam{position:absolute;top:0;left:0;right:0;height:2px; background:linear-gradient(90deg,transparent,var(--blue-glow),transparent);animation:axBeam 3.2s ease-in-out infinite;} @keyframes axBeam{0%,100%{opacity:.35;}50%{opacity:1;}} .ax-prof-head{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid var(--border);} .ax-prof-title{display:flex;flex-direction:column;font-family:'Orbitron',sans-serif;font-weight:800; font-size:.82rem;letter-spacing:.14em;color:var(--blue-glow);} .ax-prof-title i{font-style:normal;font-family:inherit;font-size:.58rem;letter-spacing:.08em;color:var(--text-soft);} .ax-prof-close{background:transparent;border:1px solid var(--border);color:var(--text);border-radius:9px;width:30px;height:30px;cursor:pointer;transition:.15s;} .ax-prof-close:hover{border-color:var(--blue-glow);color:var(--blue-glow);box-shadow:0 0 10px color-mix(in srgb,var(--blue) 40%,transparent);} .ax-prof-hero{display:flex;align-items:center;gap:13px;padding:14px 16px;border-bottom:1px solid var(--border); background: repeating-linear-gradient(90deg,color-mix(in srgb,var(--blue) 8%,transparent) 0 1px,transparent 1px 22px), linear-gradient(180deg,color-mix(in srgb,var(--blue-deep) 26%,transparent),transparent);} .ax-hero-ring{position:relative;width:62px;height:62px;border-radius:50%;padding:2px;flex-shrink:0; background:conic-gradient(from 0deg,var(--blue-glow),transparent 40%,var(--blue) 70%,var(--blue-glow)); box-shadow:0 0 18px color-mix(in srgb,var(--blue) 45%,transparent);} .ax-hero-ring img{width:100%;height:100%;border-radius:50%;object-fit:cover;background:var(--blue);display:block;} .ax-hero-meta{display:flex;flex-direction:column;gap:3px;min-width:0;} .ax-hero-meta b{font-size:1.02rem;font-weight:800;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;} .ax-hero-meta i{font-style:normal;font-family:'Orbitron',monospace;font-size:.6rem;letter-spacing:.06em;color:var(--text-soft);} .ax-hero-stat{font-style:normal;display:flex;align-items:center;gap:6px;font-family:'Orbitron',sans-serif; font-size:.55rem;letter-spacing:.12em;color:#3ECF6E;} .ax-hero-stat .ax-dot{width:7px;height:7px;border-radius:50%;background:#3ECF6E;box-shadow:0 0 8px #3ECF6E;animation:axBeam 1.8s ease-in-out infinite;} .ax-prof-body{padding:14px 16px 18px;overflow:auto;} .ax-prof-body::-webkit-scrollbar{width:8px;} .ax-prof-body::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--blue) 45%,transparent);border-radius:9px;} /* モーダル内フォームをサイトUIに合わせる */ .ax-prof-body input[type=text],.ax-prof-body input[type=password],.ax-prof-body input:not([type]), .ax-prof-body textarea,.ax-prof-body select{ width:100%;box-sizing:border-box;padding:10px 12px;margin:4px 0 2px; background:color-mix(in srgb,var(--blue-deep) 14%,var(--bg2));color:var(--text); border:1px solid color-mix(in srgb,var(--blue) 35%,var(--border));border-radius:11px; font-size:.85rem;outline:none;transition:.15s;} .ax-prof-body input:focus,.ax-prof-body textarea:focus,.ax-prof-body select:focus{ border-color:var(--blue-glow);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 22%,transparent);} .ax-prof-body input::placeholder{color:var(--text-soft);} .ax-prof-body button:not(.ax-prof-close){ padding:10px 16px;margin:6px 6px 0 0;border:1px solid color-mix(in srgb,var(--blue) 50%,var(--border)); border-radius:11px;cursor:pointer;font-weight:800;font-size:.8rem;letter-spacing:.04em;color:#fff; background:linear-gradient(135deg,var(--blue),var(--blue-deep));transition:.16s;} .ax-prof-body button:not(.ax-prof-close):hover{ transform:translateY(-1px);box-shadow:0 0 16px color-mix(in srgb,var(--blue) 50%,transparent);} .ax-prof-body label{display:block;font-family:'Orbitron',sans-serif;font-size:.6rem;letter-spacing:.12em; color:var(--blue-glow);margin-top:12px;} .ax-prof-body input[type=color]{width:52px;height:36px;padding:2px;border-radius:10px;cursor:pointer;} .ax-prof-body input[type=file]{padding:8px;font-size:.72rem;} .ax-prof-body input[type=file]::file-selector-button{ margin-right:10px;padding:6px 12px;border-radius:9px;cursor:pointer;font-weight:700;color:#fff;border:none; background:linear-gradient(135deg,var(--blue),var(--blue-deep));} .ax-prof-body .sb-note,.ax-prof-body small{font-size:.68rem;color:var(--text-soft);line-height:1.6;} .ax-people-h{font-family:'Orbitron',sans-serif;font-size:.66rem;letter-spacing:.12em;font-weight:800;color:var(--blue-glow);margin:12px 0 6px;} .ax-people-row{display:flex;align-items:center;gap:9px;padding:8px 6px;border-bottom:1px solid var(--border);} .ax-people-row.off{opacity:.55;} .ax-people-av{width:28px;height:28px;border-radius:50%;object-fit:cover;flex-shrink:0;display:inline-block;} .ax-people-name{flex:1;min-width:0;font-size:.82rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text);} .ax-people-state{font-family:'Orbitron',sans-serif;font-size:.58rem;letter-spacing:.1em;font-weight:700;} .ax-people-state.on{color:#3ECF6E;text-shadow:0 0 8px rgba(62,207,110,.5);} .ax-people-state.off{color:var(--text-soft);} #ax-proxy-block{position:fixed;inset:0;z-index:99999;display:flex;align-items:center;justify-content:center; background:radial-gradient(circle at 50% 30%,rgba(10,20,45,.96),rgba(3,6,14,.99));backdrop-filter:blur(6px);} #ax-proxy-block .ax-pb-panel{max-width:340px;padding:26px 24px;text-align:center;border-radius:16px; border:1px solid color-mix(in srgb,var(--blue,#3B82F6) 45%,#222);background:rgba(10,16,32,.9); box-shadow:0 0 40px rgba(0,0,0,.6);} #ax-proxy-block b{display:block;font-family:'Orbitron',sans-serif;letter-spacing:.16em;font-size:.95rem; color:#ff5d6c;margin-bottom:10px;} #ax-proxy-block p{font-size:.85rem;color:#dbe6ff;line-height:1.7;margin:0 0 10px;} #ax-proxy-block small{font-size:.68rem;color:#8fa3c8;} /* --- 枠を回る光(テンプレートの色に追従) --- */ @property --ax-ang{syntax:'';initial-value:0deg;inherits:false;} @keyframes axOrbit{to{--ax-ang:360deg;}} .ax-orbit{position:relative;} .ax-orbit::after{content:"";position:absolute;inset:-2px;border-radius:inherit;padding:2px; pointer-events:none;opacity:0;transition:opacity .18s; background:conic-gradient(from var(--ax-ang), transparent 0 58%, color-mix(in srgb,var(--blue,#3B82F6) 60%,transparent) 70%, var(--blue-glow,#7dd3fc) 82%, color-mix(in srgb,var(--blue,#3B82F6) 60%,transparent) 92%, transparent 100%); -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0); -webkit-mask-composite:xor;mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0); mask-composite:exclude; filter:drop-shadow(0 0 6px color-mix(in srgb,var(--blue-glow,#7dd3fc) 60%,transparent));} .ax-orbit.ax-on::after,.ax-orbit:hover::after,.ax-orbit:focus-visible::after{ opacity:1;animation:axOrbit 2.4s linear infinite;} .ax-glow-wrap{position:relative;display:flex;flex:1;min-width:0;border-radius:var(--ax-wrap-r,10px);} .ax-glow-wrap>input{flex:1;min-width:0;} .ax-glow-wrap::after{border-radius:var(--ax-wrap-r,10px);} `;/* ---------- 枠を回る光の適用 ---------- */(function orbitGlow(){function syncRadius(wrap,inp){try{const r=getComputedStyle(inp).borderTopLeftRadius||"10px";wrap.style.setProperty("--ax-wrap-r",r);}catch(e){}}function wrapInput(){const inp=$("chat-input");if(!inp)return;let wrap=inp.parentElement;if(!wrap||!wrap.classList.contains("ax-glow-wrap")){wrap=document.createElement("span");wrap.className="ax-glow-wrap ax-orbit";inp.parentElement.insertBefore(wrap,inp);wrap.appendChild(inp);const on=()=>{syncRadius(wrap,inp);wrap.classList.add("ax-on");};const off=()=>{if(document.activeElement!==inp&&!inp.value)wrap.classList.remove("ax-on");};inp.addEventListener("focus",on);inp.addEventListener("input",on);inp.addEventListener("blur",off);}/* 入力欄の枠の形(白い四角など)に光の軌道を合わせる */syncRadius(wrap,inp);}/* 押すと何かが起きるボタンはすべて対象にする */const SKIP_ID=["ax-prof-card"];const SKIP_CLASS=["ax-prof-close","ax-av-ring","ax-hero-ring","slider-tg","switch"];function mark(){document.querySelectorAll("button,[role=button],.view-btn,.gsel,.ax-mini,.act,.icon-btn,.vx-head,.vx-item").forEach(el=>{if(SKIP_ID.includes(el.id))return;if(SKIP_CLASS.some(c=>el.classList.contains(c)))return;if(el.closest("#ax-prof-card"))return;if(!el.classList.contains("ax-orbit"))el.classList.add("ax-orbit");});}function tick(){try{wrapInput();mark();}catch(e){}}tick();setInterval(tick,1200);try{new MutationObserver(()=>{try{mark();}catch(e){}}).observe(document.body,{childList:true,subtree:true});}catch(e){}})();/* ---------- 2.9.4: 名前は12文字まで ---------- */(function nameLimit(){const LIMIT=12;function bind(id,ph){const el=$(id);if(!el)return;el.setAttribute("maxlength",String(LIMIT));if(ph)el.placeholder=ph;if(el.dataset.axLimit)return;el.dataset.axLimit="1";const cut=()=>{if([...el.value].length>LIMIT)el.value=[...el.value].slice(0,LIMIT).join("");};el.addEventListener("input",cut);el.addEventListener("change",cut);cut();}function tick(){bind("gate-name","表示名(必須・12文字まで)");bind("prof-name","表示名(12文字まで)");bind("wwx-name",null);}tick();setInterval(tick,900);})();/* ---------- 2.9.4: 🎨 を使わない ---------- */(function noPaletteEmoji(){function strip(root){try{const w=document.createTreeWalker(root||document.body,NodeFilter.SHOW_TEXT);let n;while((n=w.nextNode())){if(n.nodeValue&&n.nodeValue.indexOf("\uD83C\uDFA8")>=0){n.nodeValue=n.nodeValue.replace(/\uD83C\uDFA8\s*/g,"");}}}catch(e){}}strip();setInterval(strip,1000);})();/* ---------- 2.9.4: テトリスが始まらない不具合の修正 ---------- */(function fixTetris(){if(typeof window.getOnlineUsers==="function")return;window.getOnlineUsers=async function(excludeSelf){try{const pres=await sGetJSON("presence",true,{})||{};const all=await sGetJSON("all-users",true,{})||{};const now=Date.now(),out=[];Object.entries(pres).forEach(([id,p])=>{const t=(p&&(p.t||p.time||p.last))||0;if(now-t>=70000)return;if(excludeSelf&&typeof state!=="undefined"&&state&&id===state.userId)return;out.push({id,name:(all[id]&&all[id].name)||(p&&p.name)||"不明",icon:(all[id]&&all[id].icon)||(p&&p.icon)||null});});return out;}catch(e){return[];}};})();/* ---------- アイコン周りの回転・光点を停止 ---------- */(function stopIconSpin(){css.textContent+=` .ax-av-ring,.ax-hero-ring,.ax-av-ring::before,.ax-av-ring::after, .ax-hero-ring::before,.ax-hero-ring::after, .row-av,.row-av img,.avatar,.avatar img,#ax-prof-card{ animation:none!important;} #ax-prof-card::before,#ax-prof-card::after{animation:none!important;background:none!important;} .ax-av-dot,.ax-hero-dot,.ax-online-dot{display:none!important;} .ax-orbit.ax-av-ring,.ax-orbit.ax-hero-ring{--ax-ang:0deg;} /* プロフィールカード内は一切回さない・光点も出さない */ #ax-prof-card,#ax-prof-card *,#ax-prof-card::before,#ax-prof-card::after, #ax-prof-card *::before,#ax-prof-card *::after, .ax-prof-hero,.ax-prof-hero *,.ax-prof-hero *::before,.ax-prof-hero *::after{ animation:none!important;} #ax-prof-card::after,#ax-prof-card *::after{background:none!important;box-shadow:none!important;} .ax-av-ring,.ax-hero-ring{background:color-mix(in srgb,var(--blue) 55%,transparent)!important; box-shadow:none!important;} /* 吹き出しのボタン文字は必ず横書き1行 */ .bubble button,.msg-tools button,.reaction-row button,.bubble .read-mark{ writing-mode:horizontal-tb!important;white-space:nowrap!important; width:auto!important;min-width:max-content!important;flex:0 0 auto!important; word-break:keep-all!important;overflow-wrap:normal!important;text-orientation:mixed!important;} `;const un=()=>document.querySelectorAll("#ax-prof-card.ax-orbit,.ax-av-ring.ax-orbit,.ax-hero-ring.ax-orbit").forEach(el=>el.classList.remove("ax-orbit"));un();setInterval(un,1200);})();/* ---------- 吹き出しのツール(コピー/編集/削除)と既読を1行に ---------- */(function toolsOneLine(){css.textContent+=` .bubble .msg-tools{display:flex!important;flex-wrap:nowrap!important;align-items:center;gap:6px; margin-top:4px;width:100%;overflow-x:auto;scrollbar-width:none;} .bubble .msg-tools::-webkit-scrollbar{display:none;} .bubble .msg-tools button{flex:0 0 auto;white-space:nowrap;} .bubble .msg-tools .read-mark{flex:0 0 auto;margin:0 0 0 auto!important;padding-left:8px; white-space:nowrap;font-size:.62rem;opacity:.8;} .bubble .msg-tools,.bubble .msg-tools *{white-space:nowrap!important;} `;function merge(root){(root.querySelectorAll?root.querySelectorAll(".bubble"):[]).forEach(b=>{const tools=b.querySelector(":scope > .msg-tools");const read=b.querySelector(":scope > .read-mark");if(tools&&read)tools.appendChild(read);});}const run=()=>{try{merge(document);}catch(e){}};run();const box=document.getElementById("chat-messages")||document.body;try{new MutationObserver(run).observe(box,{childList:true,subtree:true});}catch(e){}setInterval(run,1200);})();/* ---------- 2.9.4: 文字が「…」で切れないように / 吹き出しを全部見せる ---------- */css.textContent+=` /* 名前は12文字までなので省略記号は使わない */ .ax-prof-name,.ax-prof-id,.ax-hero-meta b,.ax-hero-meta i,.ax-people-name, .online-name,.tg-nm,.msg-row .name,.msg-name,.name{ overflow:visible!important;text-overflow:clip!important;max-width:none!important;} /* 吹き出しの中身は全部見えるように */ .bubble{overflow:visible!important;} .bubble .msg-content{overflow:visible!important;overflow-wrap:anywhere;word-break:break-word;} .bubble .msg-tools{display:flex!important;flex-wrap:wrap!important;align-items:center; gap:6px;row-gap:4px;overflow:visible!important;width:100%;} .bubble .msg-tools button{flex:0 0 auto;white-space:nowrap!important;overflow:visible!important; text-overflow:clip!important;} /* 既読表示が切れないように */ .read-mark,.bubble .msg-tools .read-mark{flex:0 0 auto;margin-left:auto!important; white-space:nowrap!important;overflow:visible!important;text-overflow:clip!important; max-width:none!important;width:auto!important;display:inline-flex!important; align-items:center;line-height:1.5!important;} `;document.head.appendChild(css);})();/* ---------- 追加: デフォルト配色の廃止 + 初回テンプレート選択 ---------- */(function astrexTemplateOnboarding(){"use strict";const TPL_KEY="astrex-vyslo-theme";const get=()=>{try{return localStorage.getItem(TPL_KEY)||"";}catch(e){return "";}};/* 1. 「サイト標準」(デフォルト配色)の選択肢を消す */function stripDefault(){document.querySelectorAll('.vx-item[data-id=""]').forEach(el=>el.remove());const c=document.getElementById("vx-cur");if(c&&/サイト標準/.test(c.textContent))c.textContent="現在のテンプレート: 未選択";}setInterval(stripDefault,600);stripDefault();/* 2. 初回はテンプレートを選ぶまで先に進めない */let ov=null;function close(){if(ov){ov.remove();ov=null;}}function open(){if(ov||get())return;const grid=document.getElementById("vx-grid");if(!grid)return;ov=document.createElement("div");ov.id="ax-tpl-onboard";ov.innerHTML='
'+'

デザインを選んでください

'+'

最初に画面の配色を決めます。あとから「デザインテンプレート」でいつでも変更できます。

'+''+'
';const box=ov.querySelector(".ax-tpl-grid");grid.querySelectorAll('.vx-item').forEach(item=>{if(!item.dataset.id)return;const clone=item.cloneNode(true);clone.classList.remove("active");clone.addEventListener("click",()=>{const real=document.querySelector('.vx-item[data-id="'+item.dataset.id+'"]');if(real)real.click();try{localStorage.setItem(TPL_KEY,item.dataset.id);}catch(e){}close();});box.appendChild(clone);});const search=ov.querySelector(".ax-tpl-search");search.addEventListener("input",()=>{const q=search.value.trim().toLowerCase();box.querySelectorAll(".vx-item").forEach(el=>{el.style.display=(!q||(el.dataset.k||"").toLowerCase().includes(q))?"":"none";});});document.body.appendChild(ov);}setInterval(()=>{if(get())close();else open();},500);const css=document.createElement("style");css.textContent=` #ax-tpl-onboard{position:fixed;inset:0;z-index:99999;background:rgba(3,6,12,.92); display:flex;align-items:center;justify-content:center;padding:16px;backdrop-filter:blur(6px);} #ax-tpl-onboard .ax-tpl-box{width:min(720px,100%);max-height:86vh;overflow:auto; background:#0d1420;border:1px solid #22314a;border-radius:14px;padding:18px;} #ax-tpl-onboard h2{font-family:'Orbitron',sans-serif;color:#5AA9FF;margin:0 0 6px;font-size:1.05rem;} #ax-tpl-onboard p{color:#93a1b5;font-size:.8rem;margin:0 0 12px;} #ax-tpl-onboard .ax-tpl-search{width:100%;padding:9px;margin-bottom:12px;border-radius:10px; background:#0a101a;border:1px solid #22314a;color:#eef2f8;} #ax-tpl-onboard .ax-tpl-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:10px;} #ax-tpl-onboard .vx-item{cursor:pointer;} `;document.head.appendChild(css);})();/* ---------- 追加: テンプレート見出しの表記を「デザインテンプレート」だけに ---------- */(function astrexTemplateLabel(){"use strict";function fix(){const head=document.querySelector("#vx-toggle span");if(head&&head.textContent!=="デザインテンプレート")head.textContent="デザインテンプレート";const title=document.querySelector(".vx-modal-title");if(title&&title.textContent!=="デザインテンプレート")title.textContent="デザインテンプレート";}fix();setInterval(fix,600);})();/* ---------- 追加: /site.color.change.色/ コマンドの廃止 ---------- */(function astrexDisableSiteColorCommand(){"use strict";const RE=/^\/site\.color\.change\..+\/$/;function wrap(){if(typeof window.tryHandleCommand!=="function"||window.tryHandleCommand.__axNoColor)return;const orig=window.tryHandleCommand;const patched=async function(raw){if(RE.test(String(raw||"").trim())){try{toast("このコマンドは廃止されました。配色は「デザインテンプレート」から変更してください");}catch(e){}return true;}return orig.apply(this,arguments);};patched.__axNoColor=true;window.tryHandleCommand=patched;}wrap();setInterval(wrap,800);/* コマンド一覧からも削除 */function stripRow(){document.querySelectorAll("td.cc-cmd").forEach(td=>{if(td.textContent.indexOf("/site.color.change.")===0){const tr=td.closest("tr");if(tr)tr.remove();}});}stripRow();setInterval(stripRow,900);})();/* ---------- 追加: 既読タップで既読者一覧を表示 ---------- */(function astrexReadersPopup(){"use strict";const st=document.createElement("style");st.textContent=` #ax-readers{position:fixed;inset:0;z-index:99999;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.62);backdrop-filter:blur(4px);} #ax-readers .box{width:min(90vw,340px);max-height:70vh;overflow:auto;border-radius:14px;padding:16px;background:rgba(12,16,26,.94); border:1px solid var(--accent,#4DA3FF);box-shadow:0 0 24px rgba(77,163,255,.35);color:#eaf2ff;} #ax-readers h3{margin:0 0 10px;font-size:.95rem;letter-spacing:.08em;color:var(--accent,#4DA3FF);} #ax-readers ul{list-style:none;margin:0;padding:0;} #ax-readers li{display:flex;justify-content:space-between;gap:10px;padding:7px 2px;border-bottom:1px solid rgba(255,255,255,.08);font-size:.85rem;} #ax-readers li span.t{opacity:.7;font-variant-numeric:tabular-nums;} #ax-readers .cls{margin-top:12px;width:100%;padding:9px;border-radius:9px;border:1px solid rgba(255,255,255,.2); background:rgba(255,255,255,.06);color:#eaf2ff;cursor:pointer;}`;document.head.appendChild(st);function fmt(t){try{const d=new Date(t);return("0"+d.getHours()).slice(-2)+":"+("0"+d.getMinutes()).slice(-2);}catch(e){return "";}}function open(list){document.getElementById("ax-readers")?.remove();const w=document.createElement("div");w.id="ax-readers";const items=list.map(r=>`
  • ${String(r.name||"").replace(/[<>&]/g,"")}${fmt(r.time)}
  • `).join("");w.innerHTML=`

    既読 ${list.length}人

    `;w.addEventListener("click",e=>{if(e.target===w||e.target.classList.contains("cls"))w.remove();});document.body.appendChild(w);}document.addEventListener("click",e=>{const el=e.target.closest&&e.target.closest(".read-mark.read");if(!el||!el.dataset.readers)return;e.preventDefault();e.stopPropagation();let list=[];try{list=JSON.parse(el.dataset.readers)||[];}catch(_){}if(list.length)open(list);},true);})();/* ---------- 追加: 管理者ツール「自分以外のアカウントを削除」 ---------- */(function astrexDeleteAccounts(){"use strict";const $=id=>document.getElementById(id);const esc=s=>String(s==null?"":s).replace(/[&<>"]/g,c=>({"&":"&","<":"<",">":">",'"':"""}[c])); const me=()=> (typeof state!=="undefined" && state.userId) || ""; const say=t=>{ try{ toast(t); }catch(e){} }; async function getAll(){ try{ return await sGetJSON("all-users",true,{})||{}; }catch(e){ return {}; } } async function removeIds(ids){ ids=ids.filter(id=>id && id!==me()); if(!ids.length) return; const del=await sGetJSON("deleted-accounts",true,{})||{}; const now=Date.now(); ids.forEach(id=>{ del[id]=now; }); await sSet("deleted-accounts",JSON.stringify(del),true); const all=await getAll(); ids.forEach(id=>{ delete all[id]; }); await sSet("all-users",JSON.stringify(all),true); try{ const pres=await sGetJSON("presence",true,{})||{}; ids.forEach(id=>{ delete pres[id]; }); await sSet("presence",JSON.stringify(pres),true); }catch(e){} try{ const rt=await sGetJSON("read-times",true,{})||{}; ids.forEach(id=>{ delete rt[id]; }); await sSet("read-times",JSON.stringify(rt),true); }catch(e){} } function panel(html){ let m=$("ax-delacct-modal"); if(!m){ m=document.createElement("div"); m.id="ax-delacct-modal"; m.className="ax-modal"; m.innerHTML='

    アカウント削除

    '; document.body.appendChild(m); m.addEventListener("click",e=>{ if(e.target===m||e.target.hasAttribute("data-x")) m.classList.remove("show"); }); } m.querySelector("[data-body]").innerHTML=html; m.classList.add("show"); return m; } async function open(){ if(!(typeof state!=="undefined" && hasAdminPrivilege())) return; const all=await getAll(); const rows=Object.entries(all).filter(([id,u])=>id!==me()&&u); const html='
    '+(rows.length?rows.map(([id,u])=> '
    '+esc(u.name||"名前なし")+'
    ' ).join(""):'
    他のアカウントはありません
    ') +'
    '+(rows.length?'':''); const m=panel(html); m.querySelectorAll("[data-del]").forEach(b=>b.addEventListener("click",async()=>{ if(!confirm("このアカウントを削除します。よろしいですか?")) return; await removeIds([b.getAttribute("data-del")]); say("アカウントを削除しました"); open(); })); const all2=m.querySelector("[data-delall]"); if(all2) all2.addEventListener("click",async()=>{ if(!confirm("自分以外のアカウントをすべて削除します。よろしいですか?")) return; await removeIds(rows.map(r=>r[0])); say("自分以外のアカウントを削除しました"); open(); }); } function build(){ const sec=$("sec-admin"); if(!sec || $("ax-del-acct")) return; const body=sec.querySelector(".sb-body"); if(!body) return; const label=document.createElement("label"); label.textContent="アカウント削除(自分以外)"; const btn=document.createElement("button"); btn.className="act danger"; btn.id="ax-del-acct"; btn.textContent="他のアカウントを削除"; btn.addEventListener("click",open); body.appendChild(label); body.appendChild(btn); } build(); setInterval(build,2500); /* 削除された本人の端末: アカウント情報を消して初期状態に戻す */ async function selfCheck(){ const id=me(); if(!id) return; let del={}; try{ del=await sGetJSON("deleted-accounts",true,{})||{}; }catch(e){ return; } if(!del[id]) return; if(localStorage.getItem("astrex-account-wiped")===String(del[id])) return; try{ localStorage.setItem("astrex-account-wiped",String(del[id])); }catch(e){} try{ Object.keys(localStorage).forEach(k=>{ if(k==="astrex-account-wiped") return; if(/astrex|my-profile|my-user-id|my-account-code|my-admin-recovery-id/i.test(k)) localStorage.removeItem(k); }); }catch(e){} alert("このアカウントは管理者により削除されました。"); location.reload(); } setTimeout(selfCheck,3000); setInterval(selfCheck,20000); })();