diff --git a/api/src/processing/match-action.js b/api/src/processing/match-action.js index 6d1b0254..95e5f2dd 100644 --- a/api/src/processing/match-action.js +++ b/api/src/processing/match-action.js @@ -104,6 +104,7 @@ export default function({ case "snapchat": case "bsky": case "xiaohongshu": + case "duitang": params = { picker: r.picker }; break; diff --git a/api/src/processing/match.js b/api/src/processing/match.js index 360ed532..a68ed456 100644 --- a/api/src/processing/match.js +++ b/api/src/processing/match.js @@ -29,6 +29,7 @@ import loom from "./services/loom.js"; import facebook from "./services/facebook.js"; import bluesky from "./services/bluesky.js"; import xiaohongshu from "./services/xiaohongshu.js"; +import duitang from "./services/duitang.js"; let freebind; @@ -267,6 +268,13 @@ export default async function({ host, patternMatch, params, authType }) { dispatcher, }); break; + + case "duitang": + r = await duitang({ + id: patternMatch.id, + type: patternMatch.type, + }); + break; default: return createResponse("error", { diff --git a/api/src/processing/service-config.js b/api/src/processing/service-config.js index 3ffcf10a..0cbc9b77 100644 --- a/api/src/processing/service-config.js +++ b/api/src/processing/service-config.js @@ -22,6 +22,10 @@ export const services = { dailymotion: { patterns: ["video/:id"], }, + duitang: { + patterns: [ ":type?id=:id" ], + subdomains: ["m"] + }, facebook: { patterns: [ "_shortLink/:shortLink", @@ -213,7 +217,7 @@ export const services = { "v/:id" ], subdomains: ["music", "m"], - } + }, } Object.values(services).forEach(service => { diff --git a/api/src/processing/service-patterns.js b/api/src/processing/service-patterns.js index fd6daef9..40dc21d2 100644 --- a/api/src/processing/service-patterns.js +++ b/api/src/processing/service-patterns.js @@ -5,6 +5,10 @@ export const testers = { "dailymotion": pattern => pattern.id?.length <= 32, + "duitang": pattern => + (pattern.type == 'blog' || pattern.type == 'atlas') && + pattern.id?.length <= 10, + "instagram": pattern => pattern.postId?.length <= 48 || pattern.shareId?.length <= 16 diff --git a/api/src/processing/services/duitang.js b/api/src/processing/services/duitang.js new file mode 100644 index 00000000..07018b6d --- /dev/null +++ b/api/src/processing/services/duitang.js @@ -0,0 +1,84 @@ +import { genericUserAgent, env } from "../../config.js"; +import { createStream } from "../../stream/manage.js" + +export default async function(post) { + let filenameBase = `duitang_${post.id}` + + if (post.type == 'blog') { + let req = await fetch(`https://www.duitang.com/napi/blog/detail/?blog_id=${post.id}`, { + headers: { + 'User-Agent': genericUserAgent, + } + }) + .then(request => request.text()) + .catch(() => {}); + + if (!req) return { error: 'fetch.fail' }; + + let json; + try { + json = JSON.parse(req); + } catch { return { error: 'fetch.empty' }; } + + let originalUrl = json.data.photo.path.toString(); + const image = { + // always proxy here because of headers + type: "photo", + url: createStream({ + service: "duitang", + type: "proxy", + url: originalUrl, + filename: `${filenameBase}_photo.jpg`, + headers: { + 'Host': 'c-ssl.dtstatic.com', + 'Referer': 'https://duitang.com' + } + }) + } + + return { + picker: [image] + }; + } + + if (post.type == 'atlas') { + let req = await fetch(`https://www.duitang.com/napi/vienna/atlas/detail/?atlas_id=${post.id}`, { + headers: { + 'User-Agent': genericUserAgent, + } + }) + .then(request => request.text()) + .catch(() => {}); + + if (!req) return { error: 'fetch.fail' }; + + let json; + try { + json = JSON.parse(req); + } catch { return { error: 'fetch.empty' }; } + + let imageLinks = json.data.blogs + .map(blog => blog.photo?.path) + .map((url, i) => { + // always proxy here because of headers + url = createStream({ + service: "duitang", + type: "proxy", + url: url, + filename: `${filenameBase}_photo_${i + 1}.jpg`, + headers: { + 'Host': 'c-ssl.dtstatic.com', + 'Referer': 'https://duitang.com' + } + }); + + return { + type: "photo", + url + }; + }); + return { + picker: imageLinks + } + } +} \ No newline at end of file diff --git a/api/src/processing/url.js b/api/src/processing/url.js index dbbda1cd..b5409b1a 100644 --- a/api/src/processing/url.js +++ b/api/src/processing/url.js @@ -134,6 +134,11 @@ function cleanURL(url) { } switch (host) { + case "duitang": + if (url.searchParams.get('id')) { + limitQuery('id'); + } + break; case "pinterest": url.hostname = 'pinterest.com'; break;