项目文件夹

文件
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

72 行
2.8 KiB
JavaScript

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
/**
* 一亩三分地 站内搜索 — /bbs/search.php?mod=forum
*
* Guests get a "请登录" alert page, so this command needs the live browser
* session's cookie. Discuz routes search through a 302 redirect to
* search.php?searchid=<ID>. Node fetch follows redirects automatically as
* long as we pass the session cookie along.
*/
import { cli, Strategy } from '@jackwener/opencli/registry';
import { ArgumentError, EmptyResultError } from '@jackwener/opencli/errors';
import { fetchHtml, parseSearchList, assertNotGuestAlert, getCookie, decodeEntities, normalizeLimit, BASE } from './utils.js';
cli({
site: '1point3acres',
name: 'search',
access: 'read',
description: '一亩三分地 站内关键字搜索(需要登录)',
domain: 'www.1point3acres.com',
strategy: Strategy.COOKIE,
browser: true,
navigateBefore: false,
args: [
{ name: 'query', required: true, positional: true, help: '搜索关键字' },
{ name: 'limit', type: 'int', default: 20, help: '返回条数(默认 20,最多 50' },
{ name: 'fid', type: 'string', default: '', help: '限定版块 ID(可选)' },
],
columns: ['rank', 'tid', 'title', 'forum', 'author', 'replies', 'views', 'postTime', 'url'],
func: async (page, args) => {
const query = String(args.query || '').trim();
if (!query) throw new ArgumentError('query 不能为空');
const limit = normalizeLimit(args.limit, 20, 50);
const fid = String(args.fid || '').trim();
const cookie = await getCookie(page);
const qs = new URLSearchParams({
mod: 'forum',
srchtxt: query,
searchsubmit: 'yes',
...(fid ? { srchfid: fid } : {}),
});
const url = `${BASE}/search.php?${qs.toString()}`;
// Node fetch with the session cookie — Discuz's 302 to search.php?searchid=…
// is followed by default.
const html = await fetchHtml(url, {
cookie,
headers: { Referer: `${BASE}/` },
});
assertNotGuestAlert(html);
const items = parseSearchList(html);
if (items.length === 0) {
const hint = html.match(/<p>([^<]*?抱歉[^<]*?)<\/p>/);
if (hint) {
throw new EmptyResultError('1point3acres search', decodeEntities(hint[1].trim()));
}
throw new EmptyResultError('1point3acres search', `No results for "${query}"`);
}
return items.slice(0, limit).map((t, i) => ({
rank: i + 1,
tid: t.tid,
title: t.title,
forum: t.forum,
author: t.author,
replies: t.replies,
views: t.views,
postTime: t.postTime,
url: t.url,
}));
},
});