Nine7 Deploy commited on
Commit ·
1e81421
1
Parent(s): 08ccb89
Move administrator controls into avatar menu
Browse files- webapp.html +45 -41
webapp.html
CHANGED
|
@@ -1614,48 +1614,8 @@ function vOps(m){
|
|
| 1614 |
<button class="btn" id="r_go" style="width:100%;justify-content:center">${I('replace',15)} 开始替换</button>
|
| 1615 |
</div>
|
| 1616 |
</div>
|
| 1617 |
-
<div>
|
| 1618 |
-
<!-- 🆕 白名单:在这里随时增删,不用改环境变量 -->
|
| 1619 |
-
<div class="ops-c" data-rv>
|
| 1620 |
-
<div class="cmp-t">${I('shield-check')} 访问控制</div>
|
| 1621 |
-
<div class="cmp-s">谁能进这个控制台、谁能用机器人指令</div>
|
| 1622 |
-
<div id="aclBox"><div class="fld-h" style="padding:14px 0">读取中…</div></div>
|
| 1623 |
-
<div id="aclAdd" data-form="${esc(`<div class="sec-t">放行新用户</div>`+fld('Telegram 用户 ID',inp('acl_uid','','例如 88888888'),'让对方把 @userinfobot 的回复截图发你,或在机器人里发 /admin add <ID>')+`<button class="btn btn-acc" id="acl_add" style="width:100%;justify-content:center">${I('user-plus',15)} 加入白名单</button>`)}"></div>
|
| 1624 |
-
</div>
|
| 1625 |
-
</div>
|
| 1626 |
-
</div>
|
| 1627 |
-
<div class="ops-c" data-rv style="margin-top:20px">
|
| 1628 |
-
<div class="cmp-t">${I('key-round')} 获取 Session</div>
|
| 1629 |
-
<div class="cmp-s">仅主人可用 · 登录后自动保存并启用 Userbot,无需复制 Session · 需要服务端配置 API_ID / API_HASH</div>
|
| 1630 |
-
<div id="sessionBox" class="fld-h">读取登录状态…</div>
|
| 1631 |
</div>
|
| 1632 |
<div class="foot" data-rv><span>危险操作请二次确认</span><span>OPS MODULE</span></div>`;
|
| 1633 |
-
const sessionBox=$('#sessionBox',m);
|
| 1634 |
-
const drawSession=(j)=>{
|
| 1635 |
-
const stage=j.stage||'phone',st=j.status||{};
|
| 1636 |
-
sessionBox.innerHTML=`<div class="cmp-s">${esc(j.msg|| (st.has?`已保存 · ${st.live?'在线':'未连接'} · ${st.name||''}`:'尚未保存 Session'))}</div>
|
| 1637 |
-
${stage==='phone'?fld('手机号(含国家码)',inp('session_value','','+8613800138000','tel','autocomplete="off"')):stage==='code'?fld('Telegram 验证码',inp('session_value','','输入验证码','text','autocomplete="one-time-code" inputmode="numeric"')):fld('两步验证密码',inp('session_value','','输入两步验证密码','password','autocomplete="off"'))}
|
| 1638 |
-
<div style="display:flex;gap:8px;flex-wrap:wrap"><button class="btn btn-acc" id="session_submit">${stage==='phone'?'获取验证码':stage==='code'?'验证登录':'提交密码'}</button><button class="btn" id="session_cancel">取消登录</button><button class="btn" id="session_refresh">刷新状态</button></div>`;
|
| 1639 |
-
const run=async(action)=>{
|
| 1640 |
-
const input=$('#session_value',sessionBox),value=input.value;
|
| 1641 |
-
if(action!=='cancel'&&!value.trim())return toast('请填写登录信息','err');
|
| 1642 |
-
$$('button',sessionBox).forEach(b=>b.disabled=true);
|
| 1643 |
-
try{
|
| 1644 |
-
const body={action};if(action!=='cancel')body[stage==='phone'?'phone':stage]=value;
|
| 1645 |
-
const result=await api('/api/userbot/session',{method:'POST',body});
|
| 1646 |
-
input.value='';drawSession(result);toast(result.msg);
|
| 1647 |
-
}catch(e){input.value='';toast(e.message,'err')}
|
| 1648 |
-
finally{$$('button',sessionBox).forEach(b=>b.disabled=false)}
|
| 1649 |
-
};
|
| 1650 |
-
$('#session_submit',sessionBox).onclick=()=>run(stage==='phone'?'start':stage);
|
| 1651 |
-
$('#session_cancel',sessionBox).onclick=()=>run('cancel');
|
| 1652 |
-
$('#session_refresh',sessionBox).onclick=loadSession;
|
| 1653 |
-
};
|
| 1654 |
-
const loadSession=async()=>{
|
| 1655 |
-
if(DEMO){sessionBox.textContent='演示模式不支持登录,请勿输入真实手机号、验证码或密码。';return}
|
| 1656 |
-
try{drawSession(await api('/api/userbot/session'))}catch(e){sessionBox.textContent=e.message}
|
| 1657 |
-
};
|
| 1658 |
-
loadSession();
|
| 1659 |
bindPicker('b_src',m);bindPicker('r_ch',m);bindPicker('sp_ch',m);
|
| 1660 |
const backupBox=$('#b_progress',m);
|
| 1661 |
const refreshBackup=async()=>{
|
|
@@ -1731,7 +1691,6 @@ function vOps(m){
|
|
| 1731 |
}catch(err){toast(err.message,'err')}
|
| 1732 |
btn.disabled=false;
|
| 1733 |
};
|
| 1734 |
-
loadAcl(m);
|
| 1735 |
}
|
| 1736 |
|
| 1737 |
function vMembers(m){
|
|
@@ -1927,6 +1886,47 @@ async function memSheet(cid){
|
|
| 1927 |
};
|
| 1928 |
draw();
|
| 1929 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1930 |
/* 🆕 白名单面板 */
|
| 1931 |
async function loadAcl(m,retry=0){
|
| 1932 |
try{
|
|
@@ -2029,6 +2029,10 @@ function renderMe(){
|
|
| 2029 |
const img=$('img.av',box);
|
| 2030 |
if(img){let i=0;img.onerror=()=>{i++;if(srcs[i])img.src=srcs[i];else img.outerHTML=`<span class="av">${initials}</span>`}}
|
| 2031 |
box.style.display='flex';
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2032 |
}
|
| 2033 |
|
| 2034 |
/* ================= 🆕 09 榜单完整名单(在 Telegram 内打开) ================= */
|
|
|
|
| 1614 |
<button class="btn" id="r_go" style="width:100%;justify-content:center">${I('replace',15)} 开始替换</button>
|
| 1615 |
</div>
|
| 1616 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1617 |
</div>
|
| 1618 |
<div class="foot" data-rv><span>危险操作请二次确认</span><span>OPS MODULE</span></div>`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1619 |
bindPicker('b_src',m);bindPicker('r_ch',m);bindPicker('sp_ch',m);
|
| 1620 |
const backupBox=$('#b_progress',m);
|
| 1621 |
const refreshBackup=async()=>{
|
|
|
|
| 1691 |
}catch(err){toast(err.message,'err')}
|
| 1692 |
btn.disabled=false;
|
| 1693 |
};
|
|
|
|
| 1694 |
}
|
| 1695 |
|
| 1696 |
function vMembers(m){
|
|
|
|
| 1886 |
};
|
| 1887 |
draw();
|
| 1888 |
}
|
| 1889 |
+
function adminMenu(){
|
| 1890 |
+
const w=sheet({title:'管理员',body:`<div style="display:grid;gap:12px"><button class="btn" id="admin_acl">${I('shield-check',16)} 访问控制</button><button class="btn" id="admin_session">${I('key-round',16)} 获取 Session</button></div>`});
|
| 1891 |
+
icons();
|
| 1892 |
+
$('#admin_acl',w).onclick=()=>{w._close();openAccessControl()};
|
| 1893 |
+
$('#admin_session',w).onclick=()=>{w._close();openSessionControl()};
|
| 1894 |
+
}
|
| 1895 |
+
function openAccessControl(){
|
| 1896 |
+
const m=sheet({title:'访问控制',body:` <div id="aclBox"><div class="fld-h" style="padding:14px 0">读取中…</div></div>
|
| 1897 |
+
<div id="aclAdd" data-form="${esc(`<div class="sec-t">放行新用户</div>`+fld('Telegram 用户 ID',inp('acl_uid','','例如 88888888'),'让对方把 @userinfobot 的回复截图发你,或在机器人里发 /admin add <ID>')+`<button class="btn btn-acc" id="acl_add" style="width:100%;justify-content:center">${I('user-plus',15)} 加入白名单</button>`)}"></div>`});
|
| 1898 |
+
loadAcl(m);
|
| 1899 |
+
}
|
| 1900 |
+
function openSessionControl(){
|
| 1901 |
+
const m=sheet({title:'获取 Session',body:'<div id="sessionBox" class="fld-h">读取登录状态…</div>'});
|
| 1902 |
+
const sessionBox=$('#sessionBox',m);
|
| 1903 |
+
const drawSession=(j)=>{
|
| 1904 |
+
const stage=j.stage||'phone',st=j.status||{};
|
| 1905 |
+
sessionBox.innerHTML=`<div class="cmp-s">${esc(j.msg|| (st.has?`已保存 · ${st.live?'在线':'未连接'} · ${st.name||''}`:'尚未保存 Session'))}</div>
|
| 1906 |
+
${stage==='phone'?fld('手机号(含国家码)',inp('session_value','','+8613800138000','tel','autocomplete="off"')):stage==='code'?fld('Telegram 验证码',inp('session_value','','输入验证码','text','autocomplete="one-time-code" inputmode="numeric"')):fld('两步验证密码',inp('session_value','','输入两步验证密码','password','autocomplete="off"'))}
|
| 1907 |
+
<div style="display:flex;gap:8px;flex-wrap:wrap"><button class="btn btn-acc" id="session_submit">${stage==='phone'?'获取验证码':stage==='code'?'验证登录':'提交密码'}</button><button class="btn" id="session_cancel">取消登录</button><button class="btn" id="session_refresh">刷新状态</button></div>`;
|
| 1908 |
+
const run=async(action)=>{
|
| 1909 |
+
const input=$('#session_value',sessionBox),value=input.value;
|
| 1910 |
+
if(action!=='cancel'&&!value.trim())return toast('请填写登录信息','err');
|
| 1911 |
+
$$('button',sessionBox).forEach(b=>b.disabled=true);
|
| 1912 |
+
try{
|
| 1913 |
+
const body={action};if(action!=='cancel')body[stage==='phone'?'phone':stage]=value;
|
| 1914 |
+
const result=await api('/api/userbot/session',{method:'POST',body});
|
| 1915 |
+
input.value='';drawSession(result);toast(result.msg);
|
| 1916 |
+
}catch(e){input.value='';toast(e.message,'err')}
|
| 1917 |
+
finally{$$('button',sessionBox).forEach(b=>b.disabled=false)}
|
| 1918 |
+
};
|
| 1919 |
+
$('#session_submit',sessionBox).onclick=()=>run(stage==='phone'?'start':stage);
|
| 1920 |
+
$('#session_cancel',sessionBox).onclick=()=>run('cancel');
|
| 1921 |
+
$('#session_refresh',sessionBox).onclick=loadSession;
|
| 1922 |
+
};
|
| 1923 |
+
const loadSession=async()=>{
|
| 1924 |
+
if(DEMO){sessionBox.textContent='演示模式不支持登录,请勿输入真实手机号、验证码或密码。';return}
|
| 1925 |
+
try{drawSession(await api('/api/userbot/session'))}catch(e){sessionBox.textContent=e.message}
|
| 1926 |
+
};
|
| 1927 |
+
loadSession();
|
| 1928 |
+
}
|
| 1929 |
+
|
| 1930 |
/* 🆕 白名单面板 */
|
| 1931 |
async function loadAcl(m,retry=0){
|
| 1932 |
try{
|
|
|
|
| 2029 |
const img=$('img.av',box);
|
| 2030 |
if(img){let i=0;img.onerror=()=>{i++;if(srcs[i])img.src=srcs[i];else img.outerHTML=`<span class="av">${initials}</span>`}}
|
| 2031 |
box.style.display='flex';
|
| 2032 |
+
box.setAttribute('role','button');box.setAttribute('tabindex','0');
|
| 2033 |
+
box.setAttribute('aria-label','管理员设置');box.style.cursor='pointer';
|
| 2034 |
+
box.onclick=adminMenu;
|
| 2035 |
+
box.onkeydown=e=>{if(e.key==='Enter'||e.key===' '){e.preventDefault();adminMenu()}};
|
| 2036 |
}
|
| 2037 |
|
| 2038 |
/* ================= 🆕 09 榜单完整名单(在 Telegram 内打开) ================= */
|