rsshub
Version:
Make RSS Great Again!
153 lines (147 loc) • 6.38 kB
JavaScript
import "./esm-shims-CzJ_djXG.mjs";
import { t as config } from "./config-C37vj7VH.mjs";
import "./dist-BInvbO1W.mjs";
import { t as logger_default } from "./logger-Czu8UMNd.mjs";
import "./ofetch-BIyrKU3Y.mjs";
import { t as parseDate } from "./parse-date-BrP7mxXf.mjs";
import { t as cache_default } from "./cache-Bo__VnGm.mjs";
import "./helpers-DxBp0Pty.mjs";
import { t as got_default } from "./got-KxxWdaxq.mjs";
import { t as invalid_parameter_default } from "./invalid-parameter-rr4AgGpp.mjs";
import { t as config_not_found_default } from "./config-not-found-Dyp3RlZZ.mjs";
import { load } from "cheerio";
import markdownit from "markdown-it";
import { APIErrorCode, Client, isNotionClientError } from "@notionhq/client";
import { NotionToMarkdown } from "notion-to-md";
//#region lib/routes/notion/database.ts
const md = markdownit({
html: true,
linkify: true
});
const route = {
path: "/database/:databaseId",
categories: ["other"],
example: "/notion/database/a7cc133b68454f138011f1530a13531e",
parameters: { databaseId: "Database ID" },
features: {
requireConfig: [{
name: "NOTION_TOKEN",
description: ""
}],
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false
},
radar: [{
source: ["notion.so/:id"],
target: "/database/:id"
}],
name: "Database",
maintainers: ["curly210102"],
handler,
description: `There is an optional query parameter called \`properties=\` that can be used to customize field mapping. There are three built-in fields: author, pubTime and link, which can be used to add additional information.
For example, if you have set up three properties in your database - "Publish Time", "Author", and "Original Article Link" - then execute the following JavaScript code to get the result for the properties parameter.
\`\`\`js
encodeURIComponent(JSON.stringify({"pubTime": "Publish Time", "author": "Author", "link": "Original Article Link"}))
\`\`\`
There is an optional query parameter called \`query=\` that can be used to customize the search rules for your database, such as custom sorting and filtering rules.
please refer to the [Notion API documentation](https://developers.notion.com/reference/post-database-query) and execute \`encodeURIComponent(JSON.stringify(custom rules))\` to provide the query parameter.`
};
async function handler(ctx) {
if (!config.notion.key) throw new config_not_found_default("Notion RSS is disabled due to the lack of NOTION_TOKEN(<a href=\"https://docs.rsshub.app/deploy/config#route-specific-configurations\">relevant config</a>)");
const databaseId = ctx.req.param("databaseId");
const notion_api_key = config.notion.key;
const notion = new Client({ auth: notion_api_key });
try {
const database = await notion.databases.retrieve({ database_id: databaseId });
const title = database.title[0]?.plain_text;
const description = database.description[0]?.plain_text;
const link = database.url;
const image = database.cover?.external.url ?? database.icon?.emoji;
const databaseQuery = parseCustomQuery(ctx.req.query("query"));
const { results } = await notion.databases.query({
database_id: databaseId,
...databaseQuery
});
const customProperties = parseCustomQuery(ctx.req.query("properties")) ?? {};
const properties = {
author: customProperties.author ?? "Author",
link: customProperties.link ?? "URL",
pubTime: customProperties.pubTime ?? "Created time"
};
const n2m = new NotionToMarkdown({ notionClient: notion });
const pageList = results.filter((item) => Object.values(item.properties).find((property) => property.id === "title")?.title[0]?.plain_text);
const items = await Promise.all(pageList.map(async (page) => {
const titleProperty = Object.values(page.properties).find((property) => property.id === "title");
const pageTitle = titleProperty.title[0].plain_text;
const pageLink = page.url;
const pageLastEditedTime = page.last_edited_time;
const articleLink = properties.link && notionText(page.properties[properties.link]) || titleProperty.title[0].href || "";
const pageAuthor = notionText(page.properties[properties.author]);
const pagePubTime = notionText(page.properties[properties.pubTime]);
const articleContent = await cache_default.tryGet(`${pageLink}-${pageLastEditedTime}`, async () => {
const mdblocks = await n2m.pageToMarkdown(page.id);
return n2m.toMarkdownString(mdblocks).parent;
});
let author = pageAuthor;
let pubTime = pagePubTime || pageLastEditedTime;
if (articleLink && !pageAuthor) {
const { articleAuthor, articlePubTime } = await cache_default.tryGet(`${pageLink}-${articleLink}`, async () => {
try {
const $ = load((await got_default({
method: "get",
url: articleLink
})).body);
return {
articleAuthor: $("meta[name=\"author\"]").attr("content"),
articlePubTime: $("meta[name=\"publish_date\"], meta[name=\"date\"]").attr("content")
};
} catch {
return {};
}
});
if (articleAuthor) author = articleAuthor;
if (articlePubTime) pubTime = articlePubTime;
}
return {
title: pageTitle,
author,
pubDate: parseDate(pubTime),
description: md.render(articleContent ?? ""),
link: articleLink || pageLink
};
}));
return {
title: `Notion - ${title}`,
link,
description,
image,
item: items,
allowEmpty: true
};
} catch (error) {
logger_default.error(error);
if (isNotionClientError(error)) if (error.statusCode === APIErrorCode.ObjectNotFound) throw new invalid_parameter_default("The database is not exist");
else if (error.statusCode === APIErrorCode.Unauthorized) throw new config_not_found_default("Please check the config of NOTION_TOKEN");
else ctx.throw(error.statusCode, "Notion API Error");
else ctx.throw(error);
}
}
function parseCustomQuery(queryString) {
try {
if (queryString) return JSON.parse(decodeURIComponent(queryString));
} catch {
logger_default.error("Query Parse Error");
}
}
function notionText(property) {
if (!property) return "";
if (property.type === "rich_text") return property.rich_text?.map((text) => text.plain_text).join("") ?? "";
if (property.type === "select") return property.select.name;
if (property.type === "url") return property.url;
return "";
}
//#endregion
export { route };