weaver-e9-assistant-cli 1.0.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth.js +18 -8
- package/dist/blog.js +101 -8
- package/dist/cli.js +360 -59
- package/dist/client.js +26 -5
- package/dist/cube.js +121 -18
- package/dist/email.js +4 -1
- package/dist/subordinate.js +433 -0
- package/dist/todobatch.js +7 -0
- package/dist/wfuser.js +37 -0
- package/dist/workflow.js +33 -19
- package/dist/workplan.js +37 -0
- package/package.json +27 -25
package/dist/auth.js
CHANGED
|
@@ -162,15 +162,25 @@ export async function cmdAuthStatus(cfg, args) {
|
|
|
162
162
|
process.env.E9_NO_REAUTH = '1';
|
|
163
163
|
try {
|
|
164
164
|
const api = await createApiFromProfile(cfg);
|
|
165
|
-
const
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
if (
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
165
|
+
const authFail = (j) => /登录信息超时|无效认证|认证失败|E9AIAgent/i.test(String(j?.msg ?? ''));
|
|
166
|
+
const probeOk = (r) => r && r.status === 200 && r.json && r.json.status !== false && !authFail(r.json);
|
|
167
|
+
// ① token 通道探测:aiAgentToken 头(仅当 token 存在)
|
|
168
|
+
if (session.data.token) {
|
|
169
|
+
const tr = await api.get('/api/blog/at/getAtAllList', { name: 'e9check' });
|
|
170
|
+
console.log(` token 通道 ${probeOk(tr) ? '✅ 有效' : '⚠ 已失效(将自动回退 cookie 通道)'}`);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
console.log(' token 通道 (未申请 aiAgentToken,纯 cookie 模式)');
|
|
174
|
+
}
|
|
175
|
+
// ② cookie 通道探测:直接带 Cookie 头请求(不依赖 token,判 errorCode 002)
|
|
176
|
+
const cr = await fetch(ep.baseUrl + '/api/blog/at/getAtAllList?name=e9check', {
|
|
177
|
+
headers: { 'Cookie': cfg.cookie, 'User-Agent': 'Mozilla/5.0', 'X-Requested-With': 'XMLHttpRequest' },
|
|
178
|
+
}).catch(() => null);
|
|
179
|
+
const cj = cr ? await cr.json().catch(() => null) : null;
|
|
180
|
+
if (cr && cj && cj.status !== false && !authFail(cj))
|
|
181
|
+
console.log(' cookie 通道 ✅ 有效');
|
|
172
182
|
else
|
|
173
|
-
console.log(
|
|
183
|
+
console.log(' cookie 通道 ⚠ 已过期(走 cookie 的接口如卡片/邮件附件/微博关注会报 errorCode 002,需 `e9 auth token-login` 刷新)');
|
|
174
184
|
}
|
|
175
185
|
catch (e) {
|
|
176
186
|
console.log(` 鉴权有效性 ⚠ 探测请求失败:${e.message}`);
|
package/dist/blog.js
CHANGED
|
@@ -85,12 +85,14 @@ export function isBlogRecalled(item) {
|
|
|
85
85
|
// ─── 微博首页列表(支持组织视图)─────────────────────────
|
|
86
86
|
/**
|
|
87
87
|
* 获取微博首页列表,支持按 scope 查看不同范围。
|
|
88
|
-
* scope
|
|
89
|
-
*
|
|
88
|
+
* scope 映射(groupId,抓包实证不同 scope 走不同接口):
|
|
89
|
+
* 全部关注/关注/下级(-1)、特别关注(-5) → getBlogHomepageList
|
|
90
|
+
* 未读(-2) → getMyBlogHomepageNew
|
|
91
|
+
* 分享给我/共享(-3) → getWeiboPageShareToMeList
|
|
90
92
|
*/
|
|
91
93
|
export async function getBlogHomepageList(cfg, opts = {}) {
|
|
92
94
|
const api = await createApiFromProfile(cfg);
|
|
93
|
-
const scopeMap = { '全部': '-1', '关注': '-2', '共享': '-3', '
|
|
95
|
+
const scopeMap = { '全部': '-1', '全部关注': '-1', '关注': '-1', '下级': '-1', '未读': '-2', '共享': '-3', '分享给我': '-3', '特别关注': '-5', 'all': '-1', 'attention': '-1', 'subordinate': '-1', 'sub': '-1', 'unread': '-2', 'share': '-3', 'special': '-5' };
|
|
94
96
|
const groupId = scopeMap[opts.scope] ?? opts.scope ?? '-1';
|
|
95
97
|
const endDate = opts.endDate ?? todayStr();
|
|
96
98
|
// 默认查最近 30 天
|
|
@@ -106,11 +108,34 @@ export async function getBlogHomepageList(cfg, opts = {}) {
|
|
|
106
108
|
currentPage: opts.page ?? 1,
|
|
107
109
|
pageSize: 10,
|
|
108
110
|
};
|
|
109
|
-
const
|
|
111
|
+
const endpoint = groupId === '-2' ? '/api/blog/base/getMyBlogHomepageNew'
|
|
112
|
+
: groupId === '-3' ? '/api/blog/base/getWeiboPageShareToMeList'
|
|
113
|
+
: '/api/blog/base/getBlogHomepageList';
|
|
114
|
+
const r = await api.get(endpoint, params);
|
|
110
115
|
const all = extractBlogItems(r.json);
|
|
111
116
|
const items = all.filter((it) => it.id || it.content);
|
|
112
117
|
return { scope: opts.scope ?? '全部', groupId, startDate, endDate, page: opts.page ?? 1, total: r.json.total ?? items.length, items, raw: r.json };
|
|
113
118
|
}
|
|
119
|
+
// ─── 分享给我的人(用户列表)─────────────────────────────
|
|
120
|
+
/**
|
|
121
|
+
* 获取「分享给我」的用户列表(区别于 getWeiboPageShareToMeList 查分享给我的日报内容)。
|
|
122
|
+
* GET /api/blog/base/getShareToMeUserList?groupId=all
|
|
123
|
+
*/
|
|
124
|
+
export async function getShareToMeUserList(cfg, opts = {}) {
|
|
125
|
+
const api = await createApiFromProfile(cfg);
|
|
126
|
+
const r = await api.get('/api/blog/base/getShareToMeUserList', { groupId: opts.groupId ?? 'all' });
|
|
127
|
+
const j = r.json || {};
|
|
128
|
+
const items = (j.shareToMeUserList || []).map((u) => ({
|
|
129
|
+
userId: stringify(u.userId),
|
|
130
|
+
username: stringify(u.username),
|
|
131
|
+
deptName: stringify(u.deptName),
|
|
132
|
+
jobtitle: stringify(u.jobtitle),
|
|
133
|
+
isattention: stringify(u.isattention) === '1',
|
|
134
|
+
islower: stringify(u.islower) === '1',
|
|
135
|
+
})).filter((u) => u.userId);
|
|
136
|
+
return { count: j.shareToMeUserCount, items, raw: j };
|
|
137
|
+
}
|
|
138
|
+
|
|
114
139
|
// ─── 微博搜索 ────────────────────────────────────────────
|
|
115
140
|
export async function searchMyBlog(cfg, opts = {}) {
|
|
116
141
|
const api = await createApiFromProfile(cfg);
|
|
@@ -245,6 +270,7 @@ export async function getBlogWorkIndex(cfg) {
|
|
|
245
270
|
const r = await api.get('/api/blog/base/getBlogWorkIndex');
|
|
246
271
|
const j = r.json || {};
|
|
247
272
|
return {
|
|
273
|
+
schedule: { name: j.schedule?.name, title: j.schedule?.scheduleTitle, index: j.schedule?.scheduleIndex },
|
|
248
274
|
mood: { name: j.mood?.name, title: j.mood?.moodIndexTitle, index: j.mood?.moodIndex },
|
|
249
275
|
work: { name: j.work?.name, title: j.work?.workIndexTitle, index: j.work?.workIndex },
|
|
250
276
|
raw: j,
|
|
@@ -331,7 +357,13 @@ export async function recallBlog(cfg, opts = {}) {
|
|
|
331
357
|
opType,
|
|
332
358
|
});
|
|
333
359
|
const j = r.json || {};
|
|
334
|
-
|
|
360
|
+
// 修复 #1:实际 API 响应为 {blogDiscussVo:{...isReCalled:2}}(无 api_status/status 字段),
|
|
361
|
+
// 旧判断全不匹配导致「实际撤回成功但误报失败」。成功以 blogDiscussVo.isReCalled(1/2) 或 delStatus 为准。
|
|
362
|
+
const jr = j.blogDiscussVo ?? j;
|
|
363
|
+
const isRecalled = jr?.isReCalled === 1 || jr?.isReCalled === '1' || jr?.isReCalled === 2 || jr?.isReCalled === '2';
|
|
364
|
+
const ok = isRecalled || jr?.delStatus === '1' || jr?.delStatus === 1
|
|
365
|
+
|| j.api_status === '1' || j.api_status === true || j.status === '1' || j.status === 1;
|
|
366
|
+
return { sent: true, endpoint: { baseUrl: ep.baseUrl }, blogId: opts.blogId, opType, response: r, ok };
|
|
335
367
|
}
|
|
336
368
|
// ─── 删除微博评论/回复 ───────────────────────────────────
|
|
337
369
|
// 修复 #4 补充:E9 微博正文不可删,但评论可删。POST /api/blog/base/deleteBlogReplay。
|
|
@@ -371,13 +403,74 @@ export async function getMsgRemindList(cfg) {
|
|
|
371
403
|
const j = r.json || {};
|
|
372
404
|
return {
|
|
373
405
|
items: (j.remindList || []).map((it) => ({
|
|
374
|
-
id: stringify(it.id),
|
|
375
|
-
|
|
376
|
-
|
|
406
|
+
id: stringify(it.id),
|
|
407
|
+
// 提醒内容在 msg 字段(含 HTML,需去标签);旧字段 content 仅兜底
|
|
408
|
+
content: stripHtml(it.msg) || stringify(it.content),
|
|
409
|
+
creator: stringify(it.creator ?? it.username),
|
|
410
|
+
createDate: stringify(it.createdate ?? it.createDate),
|
|
411
|
+
createTime: stringify(it.createtime),
|
|
412
|
+
type: stringify(it.remindType ?? it.remindtype ?? it.type),
|
|
413
|
+
// 关注申请专用字段(抓包实证):remindid=申请人 userid、relatedid=当前登录者、remindType=1
|
|
414
|
+
remindid: stringify(it.remindid),
|
|
415
|
+
relatedid: stringify(it.relatedid),
|
|
416
|
+
remindType: stringify(it.remindType ?? it.remindtype),
|
|
417
|
+
raw: it,
|
|
377
418
|
})),
|
|
378
419
|
raw: j,
|
|
379
420
|
};
|
|
380
421
|
}
|
|
422
|
+
// ─── 微博关注(attentionOpt + dealMsgRemind)────────────────
|
|
423
|
+
/**
|
|
424
|
+
* 发起/取消关注(抓包实证:POST /api/blog/base/attentionOpt)。
|
|
425
|
+
* body: attentionStatus=3(申请关注)/4(取消?) & islower=0 & userId=<目标userid> & type=(必须为空串)。
|
|
426
|
+
* 响应 attnInfo.attentionStatus=4 表示申请已发出,等待对方同意;1=已是好友(互关)。
|
|
427
|
+
* ⚠ 此接口走 cookie 通道(token 通道实测 no-op),cookie 过期时报 errorCode 002。
|
|
428
|
+
*/
|
|
429
|
+
export async function attentionOpt(cfg, opts = {}) {
|
|
430
|
+
const ep = endpointFor(cfg);
|
|
431
|
+
if (!opts.send)
|
|
432
|
+
return { sent: false, endpoint: { baseUrl: ep.baseUrl }, userId: opts.userId, attentionStatus: opts.attentionStatus ?? 3 };
|
|
433
|
+
const base = ep.baseUrl.replace(/\/+$/, '');
|
|
434
|
+
const r = await fetch(`${base}/api/blog/base/attentionOpt`, {
|
|
435
|
+
method: 'POST',
|
|
436
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', Cookie: ep.cookie, 'X-Requested-With': 'XMLHttpRequest', Referer: `${base}/spa/blog/static/index.html` },
|
|
437
|
+
body: new URLSearchParams({
|
|
438
|
+
attentionStatus: String(opts.attentionStatus ?? 3),
|
|
439
|
+
islower: '0',
|
|
440
|
+
userId: String(opts.userId ?? ''),
|
|
441
|
+
type: '', // 必须为空串,传 '1' 会静默 no-op(抓包实证)
|
|
442
|
+
}).toString(),
|
|
443
|
+
});
|
|
444
|
+
let j = null;
|
|
445
|
+
try { j = await r.json(); } catch { j = null; }
|
|
446
|
+
const attnStatus = j?.attnInfo?.attentionStatus ?? j?.attentionStatus;
|
|
447
|
+
const ok = attnStatus === '4' || attnStatus === 4 || j?.status === '1' || j?.status === 1 || j?.api_status === true;
|
|
448
|
+
return { sent: true, endpoint: { baseUrl: ep.baseUrl }, userId: opts.userId, attentionStatus: opts.attentionStatus ?? 3, attnStatus, raw: j, ok };
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* 处理关注申请(同意/忽略)。抓包实证:POST /api/blog/base/dealMsgRemind。
|
|
452
|
+
* body: id=<提醒记录id> & relatedId=<申请人userid> & opt=1(同意)/0(忽略)。
|
|
453
|
+
* 提醒记录 id 从 getMsgRemindList 获取(remindid=申请人、remindType=1=关注申请)。
|
|
454
|
+
* ⚠ 走 cookie 通道。返回 {"status":"1"} 表示处理成功。
|
|
455
|
+
*/
|
|
456
|
+
export async function dealMsgRemind(cfg, opts = {}) {
|
|
457
|
+
const ep = endpointFor(cfg);
|
|
458
|
+
if (!opts.send)
|
|
459
|
+
return { sent: false, endpoint: { baseUrl: ep.baseUrl }, id: opts.id, relatedId: opts.relatedId, opt: opts.opt ?? 1 };
|
|
460
|
+
const base = ep.baseUrl.replace(/\/+$/, '');
|
|
461
|
+
const r = await fetch(`${base}/api/blog/base/dealMsgRemind`, {
|
|
462
|
+
method: 'POST',
|
|
463
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', Cookie: ep.cookie, 'X-Requested-With': 'XMLHttpRequest', Referer: `${base}/spa/blog/static/index.html` },
|
|
464
|
+
body: new URLSearchParams({
|
|
465
|
+
id: String(opts.id ?? ''),
|
|
466
|
+
relatedId: String(opts.relatedId ?? ''),
|
|
467
|
+
opt: String(opts.opt ?? 1),
|
|
468
|
+
}).toString(),
|
|
469
|
+
});
|
|
470
|
+
let j = null;
|
|
471
|
+
try { j = await r.json(); } catch { j = null; }
|
|
472
|
+
return { sent: true, endpoint: { baseUrl: ep.baseUrl }, id: opts.id, relatedId: opts.relatedId, opt: opts.opt ?? 1, raw: j, ok: j?.status === '1' || j?.status === 1 };
|
|
473
|
+
}
|
|
381
474
|
// ─── 微博默认模板 ────────────────────────────────────────
|
|
382
475
|
export async function getDefaultTemplate(cfg) {
|
|
383
476
|
const api = await createApiFromProfile(cfg);
|