feat: AgentCheckin v1.2.2 — fnOS 应用:TRAE/WorkBuddy/Qoder 三平台每日积分自动签到
- 原生 fnOS 应用(CGI 入口 + Python 守护进程),依赖 python312 运行时 - 三平台签到:TRAE 每日 200 积分、WorkBuddy 7 天循环、Qoder 每日 100 Credits - WorkBuddy 网页授权(OAuth 设备流)、TRAE icubeAuth 解密 Token、Qoder Cosy 设备头 - 多时段调度(默认 00:05/09:00/12:30/19:00)、启动补跑、幂等签到+回查确认 - 多平台 Webhook 通知(企业微信/钉钉/飞书/Bark/Server酱/PushPlus 自动识别) - Qoder 双站点 Token 隔离自动探测与修复 - 前端:仪表盘/账号管理/签到记录/设置四个页签,30s 轮询+变化检测+隐藏暂停 - 测试:34 后端 + 25 E2E + 9 前端回归 + 真实时钟调度测试
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Agent 签到助手</title>
|
||||
<link rel="stylesheet" href="assets/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<header class="topbar">
|
||||
<div class="brand">
|
||||
<img src="assets/logo.svg" alt="" class="brand-logo">
|
||||
<div>
|
||||
<h1>Agent 签到助手</h1>
|
||||
<p class="sub">TRAE · WorkBuddy 每日积分自动签到</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="topbar-right">
|
||||
<span id="daemon-chip" class="chip chip-gray">守护进程 —</span>
|
||||
<span id="nextrun-chip" class="chip chip-blue">下次签到 —</span>
|
||||
<button id="btn-run-all" class="btn btn-primary">立即签到</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<nav class="tabs">
|
||||
<button class="tab active" data-tab="dashboard">仪表盘</button>
|
||||
<button class="tab" data-tab="accounts">账号管理</button>
|
||||
<button class="tab" data-tab="logs">签到记录</button>
|
||||
<button class="tab" data-tab="settings">设置</button>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<!-- ======================= 仪表盘 ======================= -->
|
||||
<section id="tab-dashboard" class="tabpage active">
|
||||
<div id="dash-cards" class="card-grid"></div>
|
||||
<div class="panel">
|
||||
<h2>使用说明</h2>
|
||||
<ul class="hint-list">
|
||||
<li><b>TRAE</b>(字节跳动·国内版):每日自动领取 <b>200</b> Work 专属积分。</li>
|
||||
<li><b>WorkBuddy / CodeBuddy</b>(腾讯):7 天循环签到,第 1-6 天每天 100 分,第 7 天 1000 分。</li>
|
||||
<li><b>Qoder</b>(国内版):每日自动领取 <b>100</b> Credits(活动非零点准时下发,多时段自动补领)。</li>
|
||||
<li>签到由 NAS 本地守护进程自动执行,失败会在下一个时段自动补签; Token 过期会标记需重新授权。</li>
|
||||
<li>所有凭据仅保存在本机 <code>@appdata/AgentCheckin</code>,不会上传到任何第三方。</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ======================= 账号管理 ======================= -->
|
||||
<section id="tab-accounts" class="tabpage">
|
||||
<div class="panel">
|
||||
<div class="panel-head">
|
||||
<h2>账号列表</h2>
|
||||
<button class="btn btn-primary" id="btn-add-account">+ 添加账号</button>
|
||||
</div>
|
||||
<div id="account-table-wrap"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ======================= 签到记录 ======================= -->
|
||||
<section id="tab-logs" class="tabpage">
|
||||
<div class="panel">
|
||||
<div class="panel-head">
|
||||
<h2>运行日志</h2>
|
||||
<div>
|
||||
<label class="switch-label"><input type="checkbox" id="log-autorefresh" checked> 自动刷新</label>
|
||||
<button class="btn" id="btn-refresh-logs">刷新</button>
|
||||
</div>
|
||||
</div>
|
||||
<pre id="log-view" class="log-view">加载中…</pre>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ======================= 设置 ======================= -->
|
||||
<section id="tab-settings" class="tabpage">
|
||||
<div class="panel">
|
||||
<h2>签到时间</h2>
|
||||
<p class="muted">每天在这些时间点自动检查并签到(已签会自动跳过)。错过时段后在守护进程启动时会自动补跑。</p>
|
||||
<div id="time-chips" class="chips"></div>
|
||||
<div class="row">
|
||||
<input type="time" id="new-time" class="input input-time">
|
||||
<button class="btn" id="btn-add-time">添加时间点</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<h2>消息通知(可选)</h2>
|
||||
<p class="muted">签到后向 Webhook 发送 POST JSON(<code>{"title","content","text","msgtype"}</code>),兼容企业微信/钉钉/飞书/Bark 等机器人。留空则不通知。</p>
|
||||
<input type="url" id="webhook-url" class="input input-wide" placeholder="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=...">
|
||||
<label style="margin-top:12px">通知平台
|
||||
<select id="webhook-type" class="input">
|
||||
<option value="auto">自动识别(推荐)</option>
|
||||
<option value="wecom">企业微信机器人</option>
|
||||
<option value="dingtalk">钉钉机器人</option>
|
||||
<option value="feishu">飞书机器人</option>
|
||||
<option value="bark">Bark(iOS 推送)</option>
|
||||
<option value="generic">通用 JSON(Server酱 / PushPlus 等)</option>
|
||||
</select>
|
||||
</label>
|
||||
<div class="row">
|
||||
<label class="switch-label"><input type="checkbox" id="notify-fail" checked> 失败时通知</label>
|
||||
<label class="switch-label"><input type="checkbox" id="notify-success"> 成功时也通知</label>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button class="btn btn-primary" id="btn-save-settings">保存设置</button>
|
||||
<button class="btn" id="btn-test-notify">发送测试通知</button>
|
||||
</div>
|
||||
<div id="settings-msg" class="msg"></div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<!-- ======================= 添加账号弹窗 ======================= -->
|
||||
<div id="modal-add" class="modal-mask hidden">
|
||||
<div class="modal">
|
||||
<div class="modal-head">
|
||||
<h3>添加账号</h3>
|
||||
<button class="modal-close" data-close="modal-add">×</button>
|
||||
</div>
|
||||
<div class="modal-tabs">
|
||||
<button class="mtab active" data-mtab="wb-oauth">WorkBuddy 网页授权</button>
|
||||
<button class="mtab" data-mtab="wb-manual">WorkBuddy 手动</button>
|
||||
<button class="mtab" data-mtab="trae">TRAE</button>
|
||||
<button class="mtab" data-mtab="qoder">Qoder</button>
|
||||
</div>
|
||||
|
||||
<div id="mtab-wb-oauth" class="mtabpage active">
|
||||
<p>点击下方按钮生成授权链接,在浏览器中打开并登录腾讯 CodeBuddy / WorkBuddy 账号,本页面会自动完成绑定。</p>
|
||||
<button class="btn btn-primary" id="btn-oauth-begin">生成授权链接</button>
|
||||
<div id="oauth-box" class="hidden">
|
||||
<p>请在浏览器中打开以下链接完成登录(10 分钟内有效):</p>
|
||||
<div class="row">
|
||||
<input id="oauth-url" class="input input-wide" readonly>
|
||||
<button class="btn" id="btn-oauth-copy">复制</button>
|
||||
</div>
|
||||
<p id="oauth-status" class="muted">等待登录…</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="mtab-wb-manual" class="mtabpage">
|
||||
<label>名称(可选)<input id="wb-name" class="input input-wide" placeholder="我的 CodeBuddy"></label>
|
||||
<label>Access Token <span class="req">*</span><input id="wb-token" class="input input-wide" placeholder="accessToken"></label>
|
||||
<label>Refresh Token(可选,用于自动续期)<input id="wb-refresh" class="input input-wide" placeholder="refreshToken"></label>
|
||||
<label>区域
|
||||
<select id="wb-domain" class="input">
|
||||
<option value="codebuddy.cn">国内版 codebuddy.cn(支持签到)</option>
|
||||
<option value="workbuddy.ai">国际版 workbuddy.ai(无签到)</option>
|
||||
</select>
|
||||
</label>
|
||||
<button class="btn btn-primary" id="btn-wb-manual-add">添加</button>
|
||||
</div>
|
||||
|
||||
<div id="mtab-trae" class="mtabpage">
|
||||
<label>名称(可选)<input id="trae-name" class="input input-wide" placeholder="TRAE 主账号"></label>
|
||||
<label>Access Token <span class="req">*</span><input id="trae-token" class="input input-wide" placeholder="eyJ 开头的 JWT"></label>
|
||||
<label>Refresh Token(可选)<input id="trae-refresh" class="input input-wide" placeholder="可选"></label>
|
||||
<details class="help">
|
||||
<summary>如何获取 TRAE Token?</summary>
|
||||
<div class="help-body">
|
||||
<p>在登录了 TRAE 国内版客户端的电脑上,凭据保存在:</p>
|
||||
<p><code>Windows: %APPDATA%\Trae CN\User\globalStorage\storage.json</code></p>
|
||||
<p>其中键 <code>iCubeAuthInfo://icube.cloudide</code> 的值为加密串,解密后可得 <code>token</code>(即 Access Token,JWT 格式)。</p>
|
||||
<p>也可使用社区工具 <code>trae_get_token.py</code>(Trae-AutoCheckin 项目)一键提取。</p>
|
||||
<p class="muted">Token 约 60 天有效;过期后在本页重新粘贴即可。</p>
|
||||
</div>
|
||||
</details>
|
||||
<button class="btn btn-primary" id="btn-trae-add">添加</button>
|
||||
</div>
|
||||
|
||||
<div id="mtab-qoder" class="mtabpage">
|
||||
<label>名称(可选)<input id="qoder-name" class="input input-wide" placeholder="Qoder 主账号"></label>
|
||||
<label>Access Token <span class="req">*</span><input id="qoder-token" class="input input-wide" placeholder="dt- 开头的 JWT"></label>
|
||||
<label>Refresh Token(可选,用于自动续期)<input id="qoder-refresh" class="input input-wide" placeholder="drt- 开头,可选"></label>
|
||||
<label>站点区域(重要:两个站点 Token 不互通,选错会 401)
|
||||
<select id="qoder-domain" class="input">
|
||||
<option value="openapi.qoder.com.cn">国内版 openapi.qoder.com.cn(qoder.cn 客户端)</option>
|
||||
<option value="openapi.qoder.sh">国际版 openapi.qoder.sh(qoder.com 客户端)</option>
|
||||
</select>
|
||||
</label>
|
||||
<details class="help" open>
|
||||
<summary>如何获取 Qoder Token?(三种方式)</summary>
|
||||
<div class="help-body">
|
||||
<p><b>方式 A · 设备授权登录(推荐,无需抓包)</b></p>
|
||||
<p>在电脑上下载社区工具 <code>qoder_login.py</code>(GitHub: L0NE-6/Qoder-Daily),运行 <code>python qoder_login.py</code>,在浏览器打开授权页确认一次,工具会输出 <code>access_token|refresh_token</code>,分别粘贴到上方即可。</p>
|
||||
<p><b>方式 B · 浏览器抓包(最快)</b></p>
|
||||
<p>浏览器登录 Qoder 网页版 → F12 开发者工具 → 网络 → 点页面里任意功能,任选一个请求 → 在请求头里找到 <code>authorization: Bearer dt-...</code></p>
|
||||
<p><b>复制技巧</b>:右键该值 →「Copy value」复制完整内容,粘贴后删掉开头的 <code>Bearer </code>。</p>
|
||||
<p><b>注意</b>:Qoder 的 <code>dt-</code> Token 原生就只有 <b>27/28 个字符</b>(不是截断,这是它的原生格式),<code>drt-</code> 刷新串同理。</p>
|
||||
<p><b>关键</b>:国内版(qoder.cn)与国际版(qoder.com)的 Token <b>不互通</b>——用哪个客户端登录提的 Token,上方「站点区域」就要选对应的那个,选错会直接 401。拿不准可以先用「测连接」,它会自动探测 Token 属于哪个站点。</p>
|
||||
<p><b>方式 C · 本机客户端提取</b></p>
|
||||
<p>在装了并登录 Qoder 客户端的 Windows 上运行社区工具 <code>01_extract.py</code>(GitHub: wallechfox/qoder-checkin),自动解密 <code>auth.v1.dat</code> 取出 Token 和设备标识。</p>
|
||||
<p class="muted">Token 有效期较短,过期后重新获取即可;填了 Refresh Token 的应用会自动续期。</p>
|
||||
</div>
|
||||
</details>
|
||||
<details class="help">
|
||||
<summary>设备标识(可选,领取提示风控时填写)</summary>
|
||||
<div class="help-body">
|
||||
<p>Qoder 签到需要 Cosy-* 设备标识。一般情况留空即可;若提示风控/领取失败,用方式 C 的工具提取后填入:</p>
|
||||
<div class="row"><input id="qoder-machine-id" class="input input-wide" placeholder="Cosy-MachineId"></div>
|
||||
<div class="row"><input id="qoder-machine-token" class="input input-wide" placeholder="Cosy-MachineToken"></div>
|
||||
<div class="row"><input id="qoder-machine-code" class="input input-wide" placeholder="Cosy-MachineCode"></div>
|
||||
<div class="row"><input id="qoder-machine-type" class="input input-wide" placeholder="Cosy-MachineType"></div>
|
||||
<div class="row"><input id="qoder-version" class="input input-wide" placeholder="Cosy-Version(客户端版本号)"></div>
|
||||
</div>
|
||||
</details>
|
||||
<button class="btn btn-primary" id="btn-qoder-add">添加</button>
|
||||
</div>
|
||||
<div id="add-msg" class="msg"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="toast" class="toast hidden"></div>
|
||||
|
||||
<script src="assets/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user