diff --git a/src/modules/processing/match.js b/src/modules/processing/match.js index 3328a32..e06166d 100644 --- a/src/modules/processing/match.js +++ b/src/modules/processing/match.js @@ -17,6 +17,7 @@ import vimeo from "./services/vimeo.js"; import soundcloud from "./services/soundcloud.js"; import instagram from "./services/instagram.js"; import vine from "./services/vine.js"; +import pinterest from "./services/pinterest.js"; export default async function (host, patternMatch, url, lang, obj) { try { @@ -110,6 +111,9 @@ export default async function (host, patternMatch, url, lang, obj) { case "vine": r = await vine({ id: patternMatch["id"] }); break; + case "pinterest": + r = await pinterest({ id: patternMatch["id"] }); + break; default: return apiJSON(0, { t: errorUnsupported(lang) }); } diff --git a/src/modules/processing/matchActionDecider.js b/src/modules/processing/matchActionDecider.js index e000504..9fa52c6 100644 --- a/src/modules/processing/matchActionDecider.js +++ b/src/modules/processing/matchActionDecider.js @@ -56,6 +56,7 @@ export default function(r, host, ip, audioFormat, isAudioOnly, lang, isAudioMute case "instagram": case "tumblr": case "twitter": + case "pinterest": responseType = 1; break; } diff --git a/src/modules/processing/services/pinterest.js b/src/modules/processing/services/pinterest.js new file mode 100644 index 0000000..335d736 --- /dev/null +++ b/src/modules/processing/services/pinterest.js @@ -0,0 +1,24 @@ +import { maxVideoDuration } from "../../config.js"; + +export default async function(obj) { + const pinId = obj.id.split('--').reverse()[0]; + if (!(/^\d+$/.test(pinId))) return { error: 'ErrorCantGetID' }; + let data = await fetch(`https://www.pinterest.com/resource/PinResource/get?data=${encodeURIComponent(JSON.stringify({ + options: { + field_set_key: "unauth_react_main_pin", + id: pinId + } + }))}`).then((r) => { return r.json() }).catch(() => { return false }); + if (!data) return { error: 'ErrorCouldntFetch' }; + + data = data["resource_response"]["data"]; + + let video = null; + + if (data.videos !== null) video = data.videos.video_list.V_720P; + else if (data.story_pin_data !== null) video = data.story_pin_data.pages[0].blocks[0].video.video_list.V_EXP7; + + if (!video) return { error: 'ErrorEmptyDownload' }; + if (video.duration > maxVideoDuration) return { error: ['ErrorLengthLimit', maxVideoDuration / 60000] }; + return { urls: video.url, filename: `pinterest_${pinId}.mp4`, audioFilename: `pinterest_${pinId}_audio` } +} diff --git a/src/modules/processing/servicesConfig.json b/src/modules/processing/servicesConfig.json index 2bb7f8f..1890eda 100644 --- a/src/modules/processing/servicesConfig.json +++ b/src/modules/processing/servicesConfig.json @@ -62,6 +62,11 @@ "tld": "co", "patterns": ["v/:id"], "enabled": true + }, + "pinterest": { + "alias": "pinterest videos & stories", + "patterns": ["pin/:id"], + "enabled": true } } } diff --git a/src/modules/processing/servicesPatternTesters.js b/src/modules/processing/servicesPatternTesters.js index 8f70613..e3286c3 100644 --- a/src/modules/processing/servicesPatternTesters.js +++ b/src/modules/processing/servicesPatternTesters.js @@ -28,5 +28,7 @@ export const testers = { "instagram": (patternMatch) => (patternMatch["id"] && patternMatch["id"].length <= 12), - "vine": (patternMatch) => (patternMatch["id"] && patternMatch["id"].length <= 12) + "vine": (patternMatch) => (patternMatch["id"] && patternMatch["id"].length <= 12), + + "pinterest": (patternMatch) => (patternMatch["id"] && patternMatch["id"].length <= 128) } diff --git a/src/modules/sub/utils.js b/src/modules/sub/utils.js index 48e6b7c..92b1082 100644 --- a/src/modules/sub/utils.js +++ b/src/modules/sub/utils.js @@ -72,6 +72,9 @@ export function cleanURL(url, host) { break; case "tiktok": url = url.replace(/@([a-zA-Z]+(\.[a-zA-Z]+)+)/, "@a") + case "pinterest": + // Redirect all TLDs back to .com + url = url.replace(/:\/\/(?:www.)pinterest(?:\.[a-z.]+)/, "://pinterest.com") default: url = url.split('?')[0]; if (url.substring(url.length - 1) === "/") url = url.substring(0, url.length - 1); diff --git a/src/test/tests.json b/src/test/tests.json index cda2653..024a284 100644 --- a/src/test/tests.json +++ b/src/test/tests.json @@ -922,5 +922,50 @@ "code": 200, "status": "stream" } + }], + "pinterest": [{ + "name": "regular video", + "url": "https://www.pinterest.com/pin/70437485604616/", + "params": {}, + "expected": { + "code": 200, + "status": "redirect" + } + }, { + "name": "regular video (isAudioOnly)", + "url": "https://www.pinterest.com/pin/70437485604616/", + "params": { + "isAudioOnly": true + }, + "expected": { + "code": 200, + "status": "stream" + } + }, { + "name": "regular video (isAudioMuted)", + "url": "https://www.pinterest.com/pin/70437485604616/", + "params": { + "isAudioMuted": true + }, + "expected": { + "code": 200, + "status": "stream" + } + }, { + "name": "regular video (.ca TLD)", + "url": "https://www.pinterest.ca/pin/70437485604616/", + "params": {}, + "expected": { + "code": 200, + "status": "redirect" + } + }, { + "name": "story", + "url": "https://www.pinterest.com/pin/gadget-cool-products-amazon-product-technology-kitchen-gadgets--1084663891475263837/", + "params": {}, + "expected": { + "code": 200, + "status": "redirect" + } }] } \ No newline at end of file