From f6752dbb54742cc4a22557c181233f3693c3d8a7 Mon Sep 17 00:00:00 2001 From: radkii Date: Sun, 30 Apr 2023 04:23:52 +0100 Subject: [PATCH] Linkedin video download integration --- src/modules/processing/match.js | 9 +++++ src/modules/processing/services/linkedin.js | 38 +++++++++++++++++++ src/modules/processing/servicesConfig.json | 5 +++ .../processing/servicesPatternTesters.js | 4 +- src/test/tests.json | 21 ++++++++++ 5 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 src/modules/processing/services/linkedin.js diff --git a/src/modules/processing/match.js b/src/modules/processing/match.js index 3328a32c..756c80f5 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 linkedin from "./services/linkedin.js"; export default async function (host, patternMatch, url, lang, obj) { try { @@ -110,6 +111,13 @@ export default async function (host, patternMatch, url, lang, obj) { case "vine": r = await vine({ id: patternMatch["id"] }); break; + case "linkedin": + r = await linkedin({ + user: patternMatch["user"], + quality: obj.vQuality, + id: patternMatch["id"] + }) + break; default: return apiJSON(0, { t: errorUnsupported(lang) }); } @@ -121,6 +129,7 @@ export default async function (host, patternMatch, url, lang, obj) { return matchActionDecider(r, host, obj.ip, obj.aFormat, isAudioOnly, lang, isAudioMuted); } catch (e) { + console.log(e) return apiJSON(0, { t: genericError(lang, host) }) } } diff --git a/src/modules/processing/services/linkedin.js b/src/modules/processing/services/linkedin.js new file mode 100644 index 00000000..50b5edbb --- /dev/null +++ b/src/modules/processing/services/linkedin.js @@ -0,0 +1,38 @@ +import { genericUserAgent } from "../../config.js"; + +const qualityMatch = { + // "feedshare-ambry-analyzed_servable_progressive_video": "1080", can vary! + "mp4-720p-30fp-crf28": "720", + "mp4-640p-30fp-crf28": "640" +} + +const height = { + //"1080": "1920", + "720": "1280", + "640": "1138" +} + +export default async function(obj) { + let html = await fetch(`https://www.linkedin.com/posts/${obj["user"]}_${obj["id"]}`, { + headers: { "user-agent": genericUserAgent } + }).then((r) => { return r.text() }).catch(() => { console.log("FALSE"); return false }); + + if (!html) return { error: 'ErrorCouldntFetch' }; + + let data = html.split("data-sources=\"")[1].split("\" data-poster-url")[0] + data = data.replaceAll(""", "\"").replaceAll("&", "&") + let dataSources = JSON.parse(data) + + let available = dataSources.map(ob => qualityMatch[ob["src"].split("/")[5]]) + // let bestQuality; + // if (obj.quality === "max" || Number(obj.quality) > 1080) bestQuality = "1080"; + // else if (Number(obj.quality) < 720) bestQuality = "640"; + // else bestQuality = (available.includes(obj.quality)) ? obj.quality : "720"; + let bestQuality = (Number(obj.quality) >= 720) ? "720" : "640"; + if (!available.includes(bestQuality)) bestQuality = (bestQuality === "720") ? "640" : "720"; + + return { + urls: dataSources[available.indexOf(bestQuality)]["src"], + filename: `linkedin_${obj["id"].slice(-24)}_${bestQuality}x${height[bestQuality]}.mp4` + } +} \ No newline at end of file diff --git a/src/modules/processing/servicesConfig.json b/src/modules/processing/servicesConfig.json index 2bb7f8fe..df44bcc0 100644 --- a/src/modules/processing/servicesConfig.json +++ b/src/modules/processing/servicesConfig.json @@ -62,6 +62,11 @@ "tld": "co", "patterns": ["v/:id"], "enabled": true + }, + "linkedin": { + "alias": "linkedin video", + "patterns": ["posts/:user_:id"], + "enabled": true } } } diff --git a/src/modules/processing/servicesPatternTesters.js b/src/modules/processing/servicesPatternTesters.js index 8f70613c..1526ce9b 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), + + "linkedin": (patternMatch) => (patternMatch["user"] && patternMatch["id"].length > 24) } diff --git a/src/test/tests.json b/src/test/tests.json index 158a0ea5..795d4397 100644 --- a/src/test/tests.json +++ b/src/test/tests.json @@ -869,5 +869,26 @@ "code": 200, "status": "stream" } + }], + "linkedin": [{ + "name": "linkedin 640p video", + "url": "https://www.linkedin.com/posts/seema-yadav-211508112_mathematics-algebra-engineering-activity-7054296523567751168-uf9P", + "params": { + "vQuality": "480" + }, + "expected":{ + "code": 200, + "status": "stream" + } + }, { + "name": "linkedin 720p video", + "url": "https://www.linkedin.com/posts/seema-yadav-211508112_mathematics-algebra-engineering-activity-7054296523567751168-uf9P", + "params": { + "vQuality": "max" + }, + "expected":{ + "code": 200, + "status": "stream" + } }] } \ No newline at end of file