UNPKG

rsshub

Version:
220 lines (218 loc) • 9.29 kB
import "./esm-shims-CzJ_djXG.mjs"; import { t as config } from "./config-C37vj7VH.mjs"; import "./dist-BInvbO1W.mjs"; import "./logger-Czu8UMNd.mjs"; import "./ofetch-BIyrKU3Y.mjs"; import "./helpers-DxBp0Pty.mjs"; import { t as got_default } from "./got-KxxWdaxq.mjs"; import { t as config_not_found_default } from "./config-not-found-Dyp3RlZZ.mjs"; //#region lib/routes/miniflux/entry.ts const route = { path: "/entry/:feeds/:parameters?", description: ` 1. Support to get all content: You can obtain the content of all subscription sources by using keywords such as \`/miniflux/all\` or \`/miniflux/default\`. 2. Support to get the subscription content of a specific subscription source by its ID. Please obtain the subscription source ID on the page where it is located under \`Sources\` (shortcut keys \`g\` \`f\`). The URL for each category (or subscription source) displays its ID information. There are several format options available: 1. Support \`/miniflux/feed=[feed_id]\`, please replace \`[feed_id]\` with the actual ID of the subscribed feed (note that it should be just a number without brackets). 2. Support subscribing to multiple feeds using \`/miniflux/feed=[feed1_id]&feed=[feed2_id]\` or \`/miniflux/feeds=[feed1_id]&[feed2_id]\`. 3. Additionally, you can use shorthand notation by directly using feed IDs: \`/miniflux/[feed1_id]&[feed2_id]\`. 3. Further customization options are available based on your needs: 1. All parameters/options provided by MiniFlux are supported ([link](https://miniflux.app/docs/api.html#endpoint-get-feed-entries)). As noted in their documentation, multiple filtering options should be connected with \`&\`. Except for \`status\`, only the first occurrence of duplicate filter options will be considered. 2. Specifically, this route defaults to sorting entries from new to old (\`direction=desc\`). 3. Moreover, this route supports additional options including: - Using the \`feed_name\` parameter to control title formatting; setting \`feed_name=1\` will display each title as "Article Title | Feed Name," while default is set at \`0\`, showing only article titles. - Utilizing the \`mark\` parameter to specify actions after fetching subscriptions in RSSHub, such as maintaining unchanged state (\`unchanged\`, default), marking as read (\`read\`), removing (\`removed\`) or marking as unread (\`unread\`). Note that marking as read should not simply be understood as a means for implementing synchronization services; rather, it functions more like an aid for MiniFlux's automatic cleaning feature. - Future support may include utilizing the \`link\` parameter to control output URLs (this functionality requires corresponding interfaces from MiniFlux). It could involve generating URLs through MiniFlux entity sharing features or original content links. - The output content quantity can be controlled via the 'limit' parameter; although all matching contents are typically outputted by default, **it is recommended that users set this parameter**. `, categories: ["other"], example: "/miniflux/feeds=1&2&3/mark=read&limit=7&status=unread", parameters: { feeds: "Subscribe source ID or get all.", parameters: "Filter and set parameters, use `&` to connect multiple." }, features: { requireConfig: [{ name: "MINIFLUX_INSTANCE", description: "The instance used by the user, by default, is the official MiniFlux [paid service address](https://reader.miniflux.app)" }, { name: "MINIFLUX_TOKEN", description: "User's API key, please log in to the instance used and go to `Settings` -> `API Key` -> `Create a new API key` to obtain." }], requirePuppeteer: false, antiCrawler: false, supportBT: false, supportPodcast: false, supportScihub: false }, name: "Feed entry", maintainers: ["emdoe", "DIYgod"], handler }; async function handler(ctx) { let mark = "unchanged"; let addFeedName = 0; let limit = 0; const instance = config.miniflux.instance; const token = config.miniflux.token; if (!token) throw new config_not_found_default("This RSS feed is disabled due to its incorrect configuration: the token is missing."); function filterHandler(item) { if (item.search("=") === -1) return ""; const filter = item.slice(0, item.indexOf("=")); const option = item.slice(item.lastIndexOf("=") + 1); switch (filter) { case "mark": if ((option === "read" || option === "removed" || option === "unread") && !setMark.length) { mark = option; setMark.push(1); } item = ""; break; case "feed_name": if (Number.parseInt(option) === 1 && !setFeedName.length) { addFeedName = 1; setFeedName.push(1); } item = ""; break; case "direction": if (option !== "asc") item = "direction=desc"; break; case "category": Number.isNaN(Number.parseInt(option)) ? item = "" : item = `category_id=${option}`; break; case "order": if (option !== "id" && option !== "category_title" && option !== "published_at" && option !== "status" && option !== "category_id") item = ""; break; case "limit": if (!Number.isNaN(option) && !setLimit.length) { limit = option; setLimit.push(1); } item = ""; break; default: break; } return item; } const entriesID = []; const feedsName = []; const articles = []; const setLimit = []; const setMark = []; const setFeedName = []; const feeds = ctx.req.param("feeds"); let parameters = ctx.req.param("parameters"); if (parameters.search("direction=") === -1) parameters += "&direction=desc"; parameters = parameters.split("&").map((item) => filterHandler(item)).filter(Boolean).join("&"); let queryLimit = ctx.req.query("limit"); let result; if (feeds.search(/feeds?=/g) !== -1 || !Number.isNaN(Number.parseInt(feeds.split("&").join("")))) { const feedsList = [feeds.replaceAll(/feeds?=/g, "").split("&")].flat(); if (limit && queryLimit) { if (limit < queryLimit) queryLimit = limit * feedsList.length; else { const eachLimit = Number.parseInt(queryLimit / feedsList.length); if (eachLimit) limit = eachLimit; else { limit = 1; queryLimit = feedsList.length; } } parameters += `&limit=${limit}`; } else if (limit) parameters += `&limit=${limit}`; else if (queryLimit) { const eachLimit = Number.parseInt(queryLimit / feedsList.length); if (eachLimit) limit = eachLimit; else { limit = 1; queryLimit = feedsList.length; } parameters += `&limit=${limit}`; } await Promise.all(feedsList.map(async (feed) => { const entries = (await got_default({ method: "get", url: `${instance}/v1/feeds/${feed}/entries?${parameters}`, headers: { "X-Auth-Token": token } })).data.entries; let getFeedTitle = 0; for (const entry of entries) { entriesID.push(entry.id); if (!getFeedTitle) { feedsName.push(entry.feed.title); getFeedTitle = 1; } let entryTitle = entry.title; if (addFeedName) entryTitle += ` | ${entry.feed.title}`; articles.push({ title: entryTitle, author: entry.author, pubDate: entry.published_at, description: entry.content, link: entry.url }); } })); const feedsNumber = feedsName.length; let agTitle, agInfo; if (feedsNumber > 2) { agTitle = `MiniFlux | Aggregator For ${feedsNumber} Feeds`; agInfo = `An aggregator powered by MiniFlux and RSSHub. This aggregator truthfully preserves the contents in ${feedsNumber} feeds, including: <li>${feedsName.join("<li></li>")}</li>`; } else if (feedsNumber) { agTitle = `MiniFlux | ${feedsName.join(", ")}`; agInfo = `A RSS feed powered by MiniFlux and RSSHub effortlessly republishes the contents in "${feedsName.join("\" & \"")}".`; } else { agTitle = `MiniFlux | Feeds Aggregator`; agInfo = "An aggregator powered by MiniFlux and RSSHub with empty content. If this is not your intention, please double-check your setting for parameters."; } result = { title: agTitle, link: instance, description: agInfo, item: articles, allowEmpty: true }; } else { if (limit && queryLimit) { if (limit < queryLimit) queryLimit = limit; parameters += `&limit=${queryLimit}`; } else if (queryLimit) parameters += `&limit=${queryLimit}`; else if (limit) parameters += `&limit=${limit}`; const entries = (await got_default.get(`${instance}/v1/entries?${parameters}`, { headers: { "X-Auth-Token": token } })).data.entries; const articles$1 = []; for (const entry of entries) { entriesID.push(entry.id); let entryTitle = entry.title; if (addFeedName) entryTitle += ` | ${entry.feed.title}`; articles$1.push({ title: entryTitle, author: entry.author, pubDate: entry.published_at, description: entry.content, link: entry.url }); } result = { title: `MiniFlux | All`, link: instance, description: `All feeds on ${instance} powered by MiniFlux`, item: articles$1, allowEmpty: true }; } if (mark !== "unchanged") got_default({ method: "put", url: `${instance}/v1/entries`, headers: { "Content-Type": "application/json", "X-Auth-Token": token }, json: { entry_ids: entriesID, status: mark } }); return result; } //#endregion export { route };