rssany 0.1.4 → 0.1.6
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/app/plugins/builtin/agi-eval-evaluation.rssany.js +188 -0
- package/app/plugins/builtin/amii-research-talent.rssany.js +73 -0
- package/app/plugins/builtin/anthropic-research.rssany.js +155 -0
- package/app/plugins/builtin/appen-resources.rssany.js +155 -0
- package/app/plugins/builtin/baai-wudao-paper-article.rssany.js +185 -0
- package/app/plugins/builtin/baaidata-csdn.rssany.js +242 -0
- package/app/plugins/builtin/baidu-research.rssany.js +222 -0
- package/app/plugins/builtin/brightdata-blog.rssany.js +301 -0
- package/app/plugins/builtin/bytedance-seed-research.rssany.js +231 -0
- package/app/plugins/builtin/five-radar.rssany.js +490 -0
- package/app/plugins/builtin/flageval-news.rssany.js +118 -0
- package/app/plugins/builtin/google-deepmind-research.rssany.js +223 -0
- package/app/plugins/builtin/google-research-datasets.rssany.js +171 -0
- package/app/plugins/builtin/google-research.rssany.js +220 -0
- package/app/plugins/builtin/google.rssany.js +187 -0
- package/app/plugins/builtin/hacker-news-newest.rssany.js +130 -0
- package/app/plugins/builtin/harvard-dataverse.rssany.js +166 -0
- package/app/plugins/builtin/huaweicloud-bbs-blogs.rssany.js +185 -0
- package/app/plugins/builtin/lingowhale.rssany.js +119 -0
- package/app/plugins/builtin/meituan-tech.rssany.js +130 -0
- package/app/plugins/builtin/meta-ai-publications.rssany.js +221 -0
- package/app/plugins/builtin/mila-quebec.rssany.js +199 -0
- package/app/plugins/builtin/mit-csail-research.rssany.js +208 -0
- package/app/plugins/builtin/moonshot.rssany.js +127 -0
- package/app/plugins/builtin/opendatalab-news.rssany.js +174 -0
- package/app/plugins/builtin/opendatalab.rssany.js +109 -0
- package/app/plugins/builtin/opendrivelab-autonomous-driving.rssany.js +114 -0
- package/app/plugins/builtin/opendrivelab-embodiedai.rssany.js +114 -0
- package/app/plugins/builtin/opendrivelab-publications.rssany.js +130 -0
- package/app/plugins/builtin/opendrivelab.rssany.js +333 -0
- package/app/plugins/builtin/paperswithcode.rssany.js +227 -0
- package/app/plugins/builtin/pjlab-adg-publications.rssany.js +202 -0
- package/app/plugins/builtin/rss.rssany.js +11 -1
- package/app/plugins/builtin/selectdataset.rssany.js +206 -0
- package/app/plugins/builtin/sensetime-tech-achievements.rssany.js +154 -0
- package/app/plugins/builtin/supervisely-blog.rssany.js +159 -0
- package/app/plugins/builtin/theinformation-briefings.rssany.js +136 -0
- package/app/plugins/builtin/uci-ml-repository.rssany.js +111 -0
- package/app/plugins/builtin/venturebeat.rssany.js +97 -0
- package/app/plugins/builtin/worldlabs.rssany.js +129 -0
- package/app/plugins/builtin/x.rssany.js +328 -0
- package/app/plugins/builtin/xiaohongshu.rssany.js +283 -0
- package/app/plugins/builtin/zhipu-research.rssany.js +334 -0
- package/dist/index.js +62 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/webui/build/200.html +6 -6
- package/webui/build/_app/immutable/assets/{0.DjU2hdCQ.css → 0.BB88QFoe.css} +1 -1
- package/webui/build/_app/immutable/assets/homeFeedPanelStore.CSvlNcpm.css +1 -0
- package/webui/build/_app/immutable/chunks/BwlaCkNX.js +36 -0
- package/webui/build/_app/immutable/chunks/C0J2-L94.js +1 -0
- package/webui/build/_app/immutable/chunks/CLOXMsDk.js +36 -0
- package/webui/build/_app/immutable/chunks/{C85CNwD2.js → DgceFEv5.js} +1 -1
- package/webui/build/_app/immutable/chunks/{CllQAdvt.js → SqCUd34O.js} +1 -1
- package/webui/build/_app/immutable/entry/{app.BcD2eSsQ.js → app.B8zBPipq.js} +2 -2
- package/webui/build/_app/immutable/entry/start.CxRCKeCl.js +1 -0
- package/webui/build/_app/immutable/nodes/0.ChLNE3xy.js +11 -0
- package/webui/build/_app/immutable/nodes/{1.DU9aYGAb.js → 1.1N74-4Io.js} +1 -1
- package/webui/build/_app/immutable/nodes/{10.Db6vw7Ih.js → 10.DY30t9Ib.js} +1 -1
- package/webui/build/_app/immutable/nodes/{11.BaAcorz3.js → 11.ITuxnukH.js} +1 -1
- package/webui/build/_app/immutable/nodes/12.qLzWqB1c.js +1 -0
- package/webui/build/_app/immutable/nodes/{14.DqT4pcrQ.js → 14.BHnIxbVM.js} +1 -1
- package/webui/build/_app/immutable/nodes/{15.CCLbjxnH.js → 15.CLjT9il3.js} +1 -1
- package/webui/build/_app/immutable/nodes/{16.DiigpVdP.js → 16.BD-mKCLN.js} +1 -1
- package/webui/build/_app/immutable/nodes/{3.DEcYOQc-.js → 3.Dt5o2Fmz.js} +1 -1
- package/webui/build/_app/immutable/nodes/{5.CvM1TkLG.js → 5.Dy3vSsIP.js} +1 -1
- package/webui/build/_app/immutable/nodes/{6.Dscr6LkS.js → 6.DvclsL6H.js} +1 -1
- package/webui/build/_app/immutable/nodes/{7.Bp60MobD.js → 7.D2nJy-Uz.js} +1 -1
- package/webui/build/_app/immutable/nodes/{8.DwSg0MHh.js → 8.C75mhrqs.js} +1 -1
- package/webui/build/_app/immutable/nodes/{9.BeYOUjxR.js → 9.Bp_QXw3w.js} +1 -1
- package/webui/build/_app/version.json +1 -1
- package/webui/build/_app/immutable/assets/homeFeedPanelStore.BopJZtHu.css +0 -1
- package/webui/build/_app/immutable/chunks/CdMsRjxJ.js +0 -1
- package/webui/build/_app/immutable/chunks/CtijX1u3.js +0 -31
- package/webui/build/_app/immutable/chunks/Dv1VCsiB.js +0 -41
- package/webui/build/_app/immutable/entry/start.CbkdJdz1.js +0 -1
- package/webui/build/_app/immutable/nodes/0.DSUDmOx2.js +0 -11
- package/webui/build/_app/immutable/nodes/12.Cg8AeCSH.js +0 -1
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { promisify } from "node:util";
|
|
|
10
10
|
import puppeteerCore from "puppeteer-core";
|
|
11
11
|
import { parse, NodeType } from "node-html-parser";
|
|
12
12
|
import Database from "better-sqlite3";
|
|
13
|
-
import { mkdir, copyFile, access, rename, readFile,
|
|
13
|
+
import { mkdir, writeFile, copyFile, access, rename, readFile, readdir, stat, unlink } from "node:fs/promises";
|
|
14
14
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
15
15
|
import { createHash } from "node:crypto";
|
|
16
16
|
import { JSDOM } from "jsdom";
|
|
@@ -188,16 +188,18 @@ function mergeSourceStatsRows(rows) {
|
|
|
188
188
|
for (const row of rows) {
|
|
189
189
|
const k = canonicalHttpSourceRef(row.source_url);
|
|
190
190
|
const prev = map.get(k);
|
|
191
|
+
const count7 = row.count_7d ?? 0;
|
|
191
192
|
if (!prev) {
|
|
192
|
-
map.set(k, { count: row.count, latest_at: row.latest_at });
|
|
193
|
+
map.set(k, { count: row.count, count_7d: count7, latest_at: row.latest_at });
|
|
193
194
|
} else {
|
|
194
195
|
map.set(k, {
|
|
195
196
|
count: prev.count + row.count,
|
|
197
|
+
count_7d: prev.count_7d + count7,
|
|
196
198
|
latest_at: maxIso(prev.latest_at, row.latest_at)
|
|
197
199
|
});
|
|
198
200
|
}
|
|
199
201
|
}
|
|
200
|
-
return [...map.entries()].map(([source_url, v]) => ({ source_url, count: v.count, latest_at: v.latest_at })).sort((a, b) => b.count - a.count);
|
|
202
|
+
return [...map.entries()].map(([source_url, v]) => ({ source_url, count: v.count, count_7d: v.count_7d, latest_at: v.latest_at })).sort((a, b) => b.count - a.count);
|
|
201
203
|
}
|
|
202
204
|
const httpSourceRef = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
203
205
|
__proto__: null,
|
|
@@ -218,6 +220,9 @@ const CONFIG_PATH = join(USER_DIR, "config.json");
|
|
|
218
220
|
const LEGACY_SUBSCRIPTIONS_PATH = join(USER_DIR, "subscriptions.json");
|
|
219
221
|
const BUILTIN_PLUGINS_DIR = join(PACKAGE_ROOT, "app/plugins/builtin");
|
|
220
222
|
const USER_PLUGINS_DIR = join(USER_DIR, "plugins");
|
|
223
|
+
const USER_DIR_PACKAGE_JSON = join(USER_DIR, "package.json");
|
|
224
|
+
const USER_DIR_PACKAGE_JSON_MINIMAL = `${JSON.stringify({ type: "module", private: true, description: "RssAny user data root; marks plugins as ESM for Node" })}
|
|
225
|
+
`;
|
|
221
226
|
const PLUGIN_SITE_TEMPLATE_PATH = join(PACKAGE_ROOT, "app/plugins/site.rssany.js");
|
|
222
227
|
async function pathExists(p) {
|
|
223
228
|
try {
|
|
@@ -262,11 +267,24 @@ async function seedExampleConfigsIfMissing() {
|
|
|
262
267
|
}
|
|
263
268
|
}
|
|
264
269
|
}
|
|
270
|
+
async function ensureUserDirPackageJsonForPlugins() {
|
|
271
|
+
if (await pathExists(USER_DIR_PACKAGE_JSON)) return;
|
|
272
|
+
try {
|
|
273
|
+
await writeFile(USER_DIR_PACKAGE_JSON, USER_DIR_PACKAGE_JSON_MINIMAL, "utf-8");
|
|
274
|
+
logger.info("config", "已写入 .rssany/package.json(type: module,消除插件 ESM 歧义)", { path: USER_DIR_PACKAGE_JSON });
|
|
275
|
+
} catch (err) {
|
|
276
|
+
logger.warn("config", "写入 .rssany/package.json 失败", {
|
|
277
|
+
path: USER_DIR_PACKAGE_JSON,
|
|
278
|
+
err: err instanceof Error ? err.message : String(err)
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
265
282
|
async function initUserDir() {
|
|
266
283
|
await mkdir(USER_DIR, { recursive: true });
|
|
267
284
|
await mkdir(DATA_DIR, { recursive: true });
|
|
268
285
|
await mkdir(CACHE_DIR, { recursive: true });
|
|
269
286
|
await mkdir(USER_PLUGINS_DIR, { recursive: true });
|
|
287
|
+
await ensureUserDirPackageJsonForPlugins();
|
|
270
288
|
await seedExampleConfigsIfMissing();
|
|
271
289
|
if (!await pathExists(SOURCES_CONFIG_PATH) && await pathExists(LEGACY_SUBSCRIPTIONS_PATH)) {
|
|
272
290
|
await migrateFile(LEGACY_SUBSCRIPTIONS_PATH, SOURCES_CONFIG_PATH);
|
|
@@ -876,7 +894,11 @@ async function getSourceStats() {
|
|
|
876
894
|
const { mergeSourceStatsRows: mergeSourceStatsRows2 } = await Promise.resolve().then(() => httpSourceRef);
|
|
877
895
|
const db = await getDb();
|
|
878
896
|
const rows = db.prepare(
|
|
879
|
-
|
|
897
|
+
`SELECT source_url,
|
|
898
|
+
COUNT(*) as count,
|
|
899
|
+
SUM(CASE WHEN julianday(fetched_at) >= julianday('now', '-7 days') THEN 1 ELSE 0 END) as count_7d,
|
|
900
|
+
MAX(COALESCE(pub_date, fetched_at)) as latest_at
|
|
901
|
+
FROM items GROUP BY source_url ORDER BY count DESC`
|
|
880
902
|
).all();
|
|
881
903
|
return mergeSourceStatsRows2(rows);
|
|
882
904
|
}
|
|
@@ -3381,6 +3403,42 @@ function registerSourcesRoutes(app) {
|
|
|
3381
3403
|
return c.json({});
|
|
3382
3404
|
}
|
|
3383
3405
|
});
|
|
3406
|
+
app.post("/api/sources/open-browser", requireAdmin(), async (c) => {
|
|
3407
|
+
try {
|
|
3408
|
+
const body = await c.req.json();
|
|
3409
|
+
const raw = typeof body?.url === "string" ? body.url.trim() : "";
|
|
3410
|
+
if (!raw) return c.json({ ok: false, message: "缺少 url" }, 400);
|
|
3411
|
+
const lower = raw.toLowerCase();
|
|
3412
|
+
if (!lower.startsWith("http://") && !lower.startsWith("https://")) {
|
|
3413
|
+
return c.json({ ok: false, message: "仅支持 http(s) URL" }, 400);
|
|
3414
|
+
}
|
|
3415
|
+
const url = raw;
|
|
3416
|
+
const source = getSource(url);
|
|
3417
|
+
const merged = await getEffectiveProxyForListUrl(url, source);
|
|
3418
|
+
const proxy = resolveProxy({ proxy: merged });
|
|
3419
|
+
void launchBrowser({ headless: false, cacheDir: CACHE_DIR, proxy }).then(async (browser) => {
|
|
3420
|
+
try {
|
|
3421
|
+
const page = await browser.newPage();
|
|
3422
|
+
await applyProxyAuthToPage(page, { proxy: merged });
|
|
3423
|
+
const realUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
|
|
3424
|
+
await page.setUserAgent(realUserAgent);
|
|
3425
|
+
await page.setViewport({ width: 1366, height: 960 });
|
|
3426
|
+
await page.goto(url, { waitUntil: "domcontentloaded", timeout: 6e4 });
|
|
3427
|
+
page.once("close", () => {
|
|
3428
|
+
void browser.close().catch(() => {
|
|
3429
|
+
});
|
|
3430
|
+
});
|
|
3431
|
+
} catch {
|
|
3432
|
+
await browser.close().catch(() => {
|
|
3433
|
+
});
|
|
3434
|
+
}
|
|
3435
|
+
}).catch(() => {
|
|
3436
|
+
});
|
|
3437
|
+
return c.json({ ok: true, message: "已在爬虫浏览器中打开" });
|
|
3438
|
+
} catch {
|
|
3439
|
+
return c.json({ ok: false, message: "请求体无效" }, 400);
|
|
3440
|
+
}
|
|
3441
|
+
});
|
|
3384
3442
|
app.get("/api/sources/raw", requireAdmin(), async (c) => {
|
|
3385
3443
|
try {
|
|
3386
3444
|
const raw = await getSourcesRaw();
|