Files
wehub-resource-sync 9b395f5cc3
E2E Headed Chrome / e2e-headed (macos-15) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (ubuntu-latest) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (windows-latest) (push) Has been cancelled
CI / build (macos-latest) (push) Has been cancelled
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
CI / unit-test (push) Has been cancelled
CI / bun-test (push) Has been cancelled
CI / adapter-test (push) Has been cancelled
CI / smoke-test (macos-latest) (push) Has been cancelled
CI / smoke-test (ubuntu-latest) (push) Has been cancelled
Security Audit / audit (push) Has been cancelled
Build Chrome Extension / build (push) Has been cancelled
Trigger Website Rebuild (Docs Updated) / dispatch (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:39:48 +08:00

65 lines
3.0 KiB
JavaScript

/**
* 一亩三分地 我的通知 — 坛友互动 / 点评 / @我 等
*
* /bbs/home.php?mod=space&do=notice&view=interactive needs login cookie.
*/
import { cli, Strategy } from '@jackwener/opencli/registry';
import { AuthRequiredError, EmptyResultError } from '@jackwener/opencli/errors';
import { fetchHtml, decodeEntities, getCookie, stripHtml, truncate, normalizePositiveInteger, BASE } from './utils.js';
cli({
site: '1point3acres',
name: 'notifications',
access: 'read',
description: '一亩三分地 站内通知(互动 / 点评 / @ 我;需要登录)',
domain: 'www.1point3acres.com',
strategy: Strategy.COOKIE,
browser: true,
navigateBefore: false,
args: [
{ name: 'kind', type: 'string', default: 'mypost',
help: '通知类型:mypost(我的帖子) / interactive(互动) / system(系统) / app(应用)' },
{ name: 'limit', type: 'int', default: 20, help: '返回条数' },
],
columns: ['index', 'from', 'summary', 'time', 'threadUrl'],
func: async (page, args) => {
const kind = String(args.kind || 'mypost').trim();
const cookie = await getCookie(page);
const url = `${BASE}/home.php?mod=space&do=notice&view=${encodeURIComponent(kind)}`;
const html = await fetchHtml(url, { cookie, headers: { Referer: `${BASE}/` } });
if (/<title>提示信息/.test(html) && /请登录/.test(html)) {
throw new AuthRequiredError('www.1point3acres.com', '请先登录一亩三分地');
}
// "No notifications" is a real empty result, not a synthetic data row.
if (/暂时没有提醒内容/.test(html)) {
throw new EmptyResultError('1point3acres notifications', '暂时没有提醒内容');
}
const rows = [];
const limit = normalizePositiveInteger(args.limit, 20, 'limit');
// Pattern 1: standard Discuz <dl class="cl">…</dl> block per notice.
const dlRe = /<dl class="[^"]*cl[^"]*"[^>]*>([\s\S]*?)<\/dl>/g;
let m;
let i = 0;
while ((m = dlRe.exec(html)) && rows.length < limit) {
const block = m[1];
const from = decodeEntities((block.match(/<dt>([\s\S]*?)<\/dt>/) || [, ''])[1])
.replace(/<[^>]+>/g, '').trim();
const summaryRaw = (block.match(/<dd class="ntc_body">([\s\S]*?)<\/dd>/) ||
block.match(/<dd>([\s\S]*?)<\/dd>/) || [, ''])[1];
const summary = truncate(stripHtml(summaryRaw), 200);
const time = ((block.match(/<dd class="[^"]*xg1[^"]*"[^>]*>([\s\S]*?)<\/dd>/) || [, ''])[1] || '')
.replace(/<[^>]+>/g, '').trim();
const linkMatch = summaryRaw.match(/href="([^"]*thread-\d+[^"]*)"/);
const threadUrl = linkMatch ? (linkMatch[1].startsWith('http') ? linkMatch[1] : `${BASE}/${linkMatch[1]}`) : '';
i += 1;
if (!from && !summary) continue;
rows.push({ index: i, from, summary, time, threadUrl });
}
return rows;
},
});