UNPKG

rsshub

Version:
149 lines (146 loc) 5.22 kB
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 config_not_found_default } from "./config-not-found-Dyp3RlZZ.mjs"; import { i as queryToInteger, t as fallback } from "./readable-social-DoIL4WB3.mjs"; //#region lib/routes/tumblr/utils.ts const getAccessToken = async () => { let accessToken = await cache_default.get("tumblr:accessToken", false); if (!accessToken) try { const newAccessToken = await tokenRefresher(); if (newAccessToken) accessToken = newAccessToken; } catch (error) { logger_default.error("Failed to refresh Tumblr token, using only client id as fallback", error); } return accessToken; }; const generateAuthHeaders = async () => { const accessToken = await getAccessToken(); if (!accessToken) return {}; return { Authorization: `Bearer ${accessToken}` }; }; const generateAuthParams = () => ({ apiKey: config.tumblr.clientId }); const processPost = (post) => { let description = ""; switch (post.type) { case "text": description = post.body; break; case "photo": for (const photo of post.photos ?? []) description += `<img src="${photo.original_size.url}"/><br/>`; break; case "link": description = post.url; break; case "audio": description = post.embed; break; default: break; } return { id: post.id_string, title: post.summary ?? `New post from ${post.blog_name}`, link: post.post_url, pubDate: parseDate(post.timestamp * 1e3), category: post.tags, description }; }; let tokenRefresher = () => Promise.resolve(null); if (config.tumblr && config.tumblr.clientId && config.tumblr.clientSecret && config.tumblr.refreshToken) tokenRefresher = async () => { let refreshToken = config.tumblr.refreshToken; const previousRefreshTokenSerialized = await cache_default.get("tumblr:refreshToken", false); if (previousRefreshTokenSerialized) { const previousRefreshToken = JSON.parse(previousRefreshTokenSerialized); if (previousRefreshToken.startToken === refreshToken) refreshToken = previousRefreshToken.currentToken; } const response = await got_default.post("https://api.tumblr.com/v2/oauth2/token", { form: { grant_type: "refresh_token", client_id: config.tumblr.clientId, client_secret: config.tumblr.clientSecret, refresh_token: refreshToken } }); if (!response.data?.access_token || !response.data?.refresh_token) return null; const accessToken = response.data.access_token; const newRefreshToken = response.data.refresh_token; const expiresIn = response.data.expires_in; await cache_default.set("tumblr:accessToken", accessToken, (expiresIn ?? 2520) - 30); const cacheEntry = { startToken: config.tumblr.refreshToken, currentToken: newRefreshToken }; await cache_default.set(`tumblr:refreshToken`, JSON.stringify(cacheEntry), 31536e3); return accessToken; }; var utils_default = { processPost, generateAuthParams, generateAuthHeaders }; //#endregion //#region lib/routes/tumblr/posts.ts const route = { path: "/posts/:blog", categories: ["blog"], example: "/tumblr/posts/biketouring-nearby", parameters: { blog: "Blog identifier (see `https://www.tumblr.com/docs/en/api/v2#blog-identifiers`)" }, radar: [], features: { requireConfig: [ { name: "TUMBLR_CLIENT_ID", description: "Please see above for details." }, { name: "TUMBLR_CLIENT_SECRET", description: "Please see above for details." }, { name: "TUMBLR_REFRESH_TOKEN", description: "Please see above for details." } ], requirePuppeteer: false, antiCrawler: false, supportBT: false, supportPodcast: false, supportScihub: false }, name: "Posts", maintainers: ["Rakambda"], description: `::: tip Tumblr provides official RSS feeds for non "dashboard only" blogs, for instance [https://biketouring-nearby.tumblr.com](https://biketouring-nearby.tumblr.com/rss). :::`, handler }; async function handler(ctx) { if (!config.tumblr || !config.tumblr.clientId) throw new config_not_found_default("Tumblr RSS is disabled due to the lack of <a href=\"https://docs.rsshub.app/deploy/config#route-specific-configurations\">relevant config</a>"); const blogIdentifier = ctx.req.param("blog"); const limit = fallback(void 0, queryToInteger(ctx.req.query("limit")), 20); const response = await got_default.get(`https://api.tumblr.com/v2/blog/${blogIdentifier}/posts`, { searchParams: { ...utils_default.generateAuthParams(), limit }, headers: await utils_default.generateAuthHeaders() }); const blog = response.data.response.blog; const posts = response.data.response.posts.map((post) => utils_default.processPost(post)); return { title: `Tumblr - ${blogIdentifier} - Posts`, author: blog?.name, link: blog?.url ?? `https://${blogIdentifier}/`, item: posts, allowEmpty: true, image: blog?.avatar?.slice(-1)?.url, description: blog?.description }; } //#endregion export { route };