rsshub
Version:
Make RSS Great Again!
95 lines (93 loc) • 5.02 kB
JavaScript
import { n as init_esm_shims, t as __dirname } from "./esm-shims-CzJ_djXG.mjs";
import { t as config } from "./config-C37vj7VH.mjs";
import "./dist-BInvbO1W.mjs";
import "./logger-Czu8UMNd.mjs";
import { t as ofetch_default } from "./ofetch-BIyrKU3Y.mjs";
import { t as parseDate } from "./parse-date-BrP7mxXf.mjs";
import { t as cache_default } from "./cache-Bo__VnGm.mjs";
import { t as art } from "./render-BQo6B4tL.mjs";
import path from "node:path";
import * as cheerio from "cheerio";
//#region lib/routes/patreon/feed.ts
init_esm_shims();
const route = {
path: "/:creator",
categories: ["new-media"],
example: "/patreon/straightupsisters",
parameters: { creator: "Patreon creator id, can be found in the url" },
features: {
requireConfig: [{
name: "PATREON_SESSION_ID",
optional: true,
description: "The value of the session_id cookie after logging in to Patreon, required to access paid posts"
}],
nsfw: true
},
radar: [{ source: ["patreon.com/:creator"] }],
name: "Home",
maintainers: ["TonyRL"],
handler
};
async function handler(ctx) {
const { creator } = ctx.req.param();
const link = `https://www.patreon.com/${creator}`;
const creatorData = await cache_default.tryGet(`patreon:creator:${creator}`, async () => {
const response = await ofetch_default(link);
const $ = cheerio.load(response);
const bootstrapEnvelope = JSON.parse($("#__NEXT_DATA__").text()).props.pageProps.bootstrapEnvelope;
return {
id: bootstrapEnvelope.pageBootstrap.campaign.data.id,
attributes: bootstrapEnvelope.pageBootstrap.campaign.data.attributes
};
});
if (!creatorData.id) throw new Error("Creator not found");
let headers = {};
if (config.patreon?.sessionId) headers = { Cookie: `session_id=${config.patreon.sessionId}` };
const posts = await ofetch_default("https://www.patreon.com/api/posts", {
headers,
query: {
include: "campaign,access_rules,access_rules.tier.null,attachments_media,audio,audio_preview.null,drop,images,media,native_video_insights,poll.choices,poll.current_user_responses.user,poll.current_user_responses.choice,poll.current_user_responses.poll,user,user_defined_tags,ti_checks,video.null,content_unlock_options.product_variant.null",
"fields[campaign]": "currency,show_audio_post_download_links,avatar_photo_url,avatar_photo_image_urls,earnings_visibility,is_nsfw,is_monthly,name,url",
"fields[post]": "change_visibility_at,comment_count,commenter_count,content,created_at,current_user_can_comment,current_user_can_delete,current_user_can_report,current_user_can_view,current_user_comment_disallowed_reason,current_user_has_liked,embed,image,insights_last_updated_at,is_paid,like_count,meta_image_url,min_cents_pledged_to_view,monetization_ineligibility_reason,post_file,post_metadata,published_at,patreon_url,post_type,pledge_url,preview_asset_type,thumbnail,thumbnail_url,teaser_text,title,upgrade_url,url,was_posted_by_campaign_owner,has_ti_violation,moderation_status,post_level_suspension_removal_date,pls_one_liners_by_category,video,video_preview,view_count,content_unlock_options,is_new_to_current_user,watch_state",
"fields[post_tag]": "tag_type,value",
"fields[user]": "image_url,full_name,url",
"fields[access_rule]": "access_rule_type,amount_cents",
"fields[media]": "id,image_urls,display,download_url,metadata,file_name",
"fields[native_video_insights]": "average_view_duration,average_view_pct,has_preview,id,last_updated_at,num_views,preview_views,video_duration",
"fields[content-unlock-option]": "content_unlock_type",
"fields[product-variant]": "price_cents,currency_code,checkout_url,is_hidden,published_at_datetime,content_type,orders_count,access_metadata",
"filter[campaign_id]": creatorData.id,
"filter[contains_exclusive_posts]": true,
"filter[is_draft]": false,
sort: "-published_at",
"json-api-use-default-includes": false,
"json-api-version": "1.0"
}
});
const items = posts.data.map(({ attributes, relationships }) => {
for (const [key, value] of Object.entries(relationships)) if (value.data) relationships[key] = Array.isArray(value.data) ? value.data.map((item) => posts.included.find((i) => i.id === item.id)) : posts.included.find((i) => i.id === value.data.id);
if (attributes.video_preview) relationships.video_preview = posts.included.find((i) => Number.parseInt(i.id) === attributes.video_preview?.media_id);
return {
title: attributes.title,
description: art(path.join(__dirname, "templates/description-4c0b7baa.art"), {
attributes,
relationships,
included: posts.included
}),
link: attributes.url,
pubDate: parseDate(attributes.published_at),
image: attributes.thumbnail?.url ?? attributes.image?.url,
category: relationships.user_defined_tags?.map((tag) => tag.attributes.value)
};
});
return {
title: creatorData.attributes.name,
description: creatorData.attributes.creation_name,
link,
image: creatorData.attributes.avatar_photo_url,
item: items,
allowEmpty: true
};
}
//#endregion
export { route };