|
1 | 1 | import { genericUserAgent } from "../../config.js"; |
2 | 2 |
|
3 | | -export default async function({ id }) { |
| 3 | +const craftHeaders = id => ({ |
| 4 | + "user-agent": genericUserAgent, |
| 5 | + "content-type": "application/json", |
| 6 | + origin: "https://www.loom.com", |
| 7 | + referer: `https://www.loom.com/share/${id}`, |
| 8 | + cookie: `loom_referral_video=${id};`, |
| 9 | + "x-loom-request-source": "loom_web_be851af", |
| 10 | +}); |
| 11 | + |
| 12 | +async function fromTranscodedURL(id) { |
4 | 13 | const gql = await fetch(`https://www.loom.com/api/campaigns/sessions/${id}/transcoded-url`, { |
5 | 14 | method: "POST", |
6 | | - headers: { |
7 | | - "user-agent": genericUserAgent, |
8 | | - origin: "https://www.loom.com", |
9 | | - referer: `https://www.loom.com/share/${id}`, |
10 | | - cookie: `loom_referral_video=${id};`, |
11 | | - |
12 | | - "apollographql-client-name": "web", |
13 | | - "apollographql-client-version": "14c0b42", |
14 | | - "x-loom-request-source": "loom_web_14c0b42", |
15 | | - }, |
| 15 | + headers: craftHeaders(id), |
16 | 16 | body: JSON.stringify({ |
17 | 17 | force_original: false, |
18 | 18 | password: null, |
19 | 19 | anonID: null, |
20 | 20 | deviceID: null |
21 | 21 | }) |
22 | 22 | }) |
23 | | - .then(r => r.status === 200 ? r.json() : false) |
| 23 | + .then(r => r.status === 200 && r.json()) |
24 | 24 | .catch(() => {}); |
25 | 25 |
|
26 | | - if (!gql) return { error: "fetch.empty" }; |
| 26 | + if (gql?.url?.includes('.mp4?')) { |
| 27 | + return gql.url; |
| 28 | + } |
| 29 | +} |
27 | 30 |
|
28 | | - const videoUrl = gql?.url; |
| 31 | +async function fromRawURL(id) { |
| 32 | + const gql = await fetch(`https://www.loom.com/api/campaigns/sessions/${id}/raw-url`, { |
| 33 | + method: "POST", |
| 34 | + headers: craftHeaders(id), |
| 35 | + body: JSON.stringify({ |
| 36 | + anonID: crypto.randomUUID(), |
| 37 | + client_name: "web", |
| 38 | + client_version: "be851af", |
| 39 | + deviceID: null, |
| 40 | + force_original: false, |
| 41 | + password: null, |
| 42 | + supported_mime_types: ["video/mp4"], |
| 43 | + }) |
| 44 | + }) |
| 45 | + .then(r => r.status === 200 && r.json()) |
| 46 | + .catch(() => {}); |
| 47 | + |
| 48 | + if (gql?.url?.includes('.mp4?')) { |
| 49 | + return gql.url; |
| 50 | + } |
| 51 | +} |
| 52 | + |
| 53 | +export default async function({ id }) { |
| 54 | + let url = await fromTranscodedURL(id); |
| 55 | + url ??= await fromRawURL(id); |
29 | 56 |
|
30 | | - if (videoUrl?.includes('.mp4?')) { |
31 | | - return { |
32 | | - urls: videoUrl, |
33 | | - filename: `loom_${id}.mp4`, |
34 | | - audioFilename: `loom_${id}_audio` |
35 | | - } |
| 57 | + if (!url) { |
| 58 | + return { error: "fetch.empty" } |
36 | 59 | } |
37 | 60 |
|
38 | | - return { error: "fetch.empty" } |
| 61 | + return { |
| 62 | + urls: url, |
| 63 | + filename: `loom_${id}.mp4`, |
| 64 | + audioFilename: `loom_${id}_audio` |
| 65 | + } |
39 | 66 | } |
0 commit comments