UNPKG

rsshub

Version:
100 lines (98 loc) 4.1 kB
import "./esm-shims-CzJ_djXG.mjs"; import { t as config } from "./config-C37vj7VH.mjs"; import { t as logger_default } from "./logger-Czu8UMNd.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 "./proxy-Db7uGcYb.mjs"; import { t as invalid_parameter_default } from "./invalid-parameter-rr4AgGpp.mjs"; import { n as puppeteer_default } from "./puppeteer-DGmvuGvT.mjs"; import { n as queryToBoolean, t as fallback } from "./readable-social-DoIL4WB3.mjs"; import { i as templates, n as proxyVideo, r as resolveUrl, t as getOriginAvatar } from "./utils-CQKS3rFA.mjs"; //#region lib/routes/douyin/user.ts const route = { path: "/user/:uid/:routeParams?", categories: ["social-media"], example: "/douyin/user/MS4wLjABAAAARcAHmmF9mAG3JEixq_CdP72APhBlGlLVbN-1eBcPqao", parameters: { uid: "uid,可在用户页面 URL 中找到", routeParams: "额外参数,query string 格式,请参阅上面的表格" }, features: { requireConfig: false, requirePuppeteer: true, antiCrawler: true, supportBT: false, supportPodcast: false, supportScihub: false }, radar: [{ source: ["douyin.com/user/:uid"], target: "/user/:uid" }], name: "博主", maintainers: ["Max-Tortoise", "Rongronggg9"], handler }; async function handler(ctx) { const uid = ctx.req.param("uid"); if (!uid.startsWith("MS4wLjABAAAA")) throw new invalid_parameter_default("Invalid UID. UID should start with <b>MS4wLjABAAAA</b>."); const routeParams = Object.fromEntries(new URLSearchParams(ctx.req.param("routeParams"))); const embed = fallback(void 0, queryToBoolean(routeParams.embed), false); const iframe = fallback(void 0, queryToBoolean(routeParams.iframe), false); const relay = resolveUrl(routeParams.relay, true, true); const pageUrl = `https://www.douyin.com/user/${uid}`; const pageData = await cache_default.tryGet(`douyin:user:${uid}`, async () => { let postData; const browser = await puppeteer_default(); const page = await browser.newPage(); await page.setRequestInterception(true); page.on("request", (request) => { request.resourceType() === "document" || request.resourceType() === "script" || request.resourceType() === "xhr" ? request.continue() : request.abort(); }); page.on("response", async (response) => { if (response.request().url().includes("/web/aweme/post") && !postData) postData = await response.json(); }); logger_default.http(`Requesting ${pageUrl}`); await page.goto(pageUrl, { waitUntil: "networkidle2" }); await browser.close(); if (!postData) throw new Error("Empty post data. The request may be filtered by WAF."); return postData; }, config.cache.routeExpire, false); if (!pageData.aweme_list?.length) throw new Error("Empty post data. The request may be filtered by WAF."); const userInfo = pageData.aweme_list[0].author; return { title: userInfo.nickname, image: getOriginAvatar(userInfo.avatar_thumb.url_list.at(-1)), link: pageUrl, item: pageData.aweme_list.map((post) => { let videoList = post.video?.bit_rate?.map((item) => resolveUrl(item.play_addr.url_list.at(-1))); if (relay) videoList = videoList.map((item) => proxyVideo(item, relay)); let duration = post.video?.duration; duration = duration && duration / 1e3; let img; img = img || post.video?.cover?.url_list.at(-1) || post.video?.origin_cover?.url_list.at(-1); img = img && resolveUrl(img); const desc = post.desc?.replaceAll("\n", "<br>"); let media = art(embed && videoList ? templates.embed : templates.cover, { img, videoList, duration }); media = embed && videoList && iframe ? art(templates.iframe, { content: media }) : media; const description = art(templates.desc, { desc, media }); return { title: post.desc.split("\n")[0], description, link: `https://www.douyin.com/video/${post.aweme_id}`, pubDate: parseDate(post.create_time * 1e3), category: post.video_tag.map((t) => t.tag_name) }; }) }; } //#endregion export { route };