Nine7 Deploy commited on
Commit
1e81421
·
1 Parent(s): 08ccb89

Move administrator controls into avatar menu

Browse files
Files changed (1) hide show
  1. 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 &lt;ID&gt;')+`<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 &lt;ID&gt;')+`<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 内打开) ================= */