File size: 3,066 Bytes
5bab120
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import { env } from "../../config.js";
import { cleanString } from '../../misc/utils.js';

const gqlURL = "https://gql.twitch.tv/gql";
const clientIdHead = { "client-id": "kimne78kx3ncx6brgo4mv6wki5h1ko" };

export default async function (obj) {
    const req_metadata = await fetch(gqlURL, {
        method: "POST",
        headers: clientIdHead,
        body: JSON.stringify({
            query: `{
            clip(slug: "${obj.clipId}") {
                broadcaster {
                    login
                }
                createdAt
                curator {
                    login
                }
                durationSeconds
                id
                medium: thumbnailURL(width: 480, height: 272)
                title
                videoQualities {
                    quality
                    sourceURL
                }
            }
        }`
        })
    }).then(r => r.status === 200 ? r.json() : false).catch(() => {});

    if (!req_metadata) return { error: "fetch.fail" };

    const clipMetadata = req_metadata.data.clip;

    if (clipMetadata.durationSeconds > env.durationLimit) {
        return { error: "content.too_long" };
    }
    if (!clipMetadata.videoQualities || !clipMetadata.broadcaster) {
        return { error: "fetch.empty" };
    }

    const req_token = await fetch(gqlURL, {
        method: "POST",
        headers: clientIdHead,
        body: JSON.stringify([
            {
                "operationName": "VideoAccessToken_Clip",
                "variables": {
                    "slug": obj.clipId
                },
                "extensions": {
                    "persistedQuery": {
                        "version": 1,
                        "sha256Hash": "36b89d2507fce29e5ca551df756d27c1cfe079e2609642b4390aa4c35796eb11"
                    }
                }
            }
        ])
    }).then(r => r.status === 200 ? r.json() : false).catch(() => {});

    if (!req_token) return { error: "fetch.fail" };

    const formats = clipMetadata.videoQualities;
    const format = formats.find(f => f.quality === obj.quality) || formats[0];

    return {
        type: "proxy",
        urls: `${format.sourceURL}?${new URLSearchParams({
            sig: req_token[0].data.clip.playbackAccessToken.signature,
            token: req_token[0].data.clip.playbackAccessToken.value
        })}`,
        fileMetadata: {
            title: cleanString(clipMetadata.title.trim()),
            artist: `Twitch Clip by @${clipMetadata.broadcaster.login}, clipped by @${clipMetadata.curator.login}`,
        },
        filenameAttributes: {
            service: "twitch",
            id: clipMetadata.id,
            title: cleanString(clipMetadata.title.trim()),
            author: `${clipMetadata.broadcaster.login}, clipped by ${clipMetadata.curator.login}`,
            qualityLabel: `${format.quality}p`,
            extension: 'mp4'
        },
        filename: `twitchclip_${clipMetadata.id}_${format.quality}p.mp4`,
        audioFilename: `twitchclip_${clipMetadata.id}_audio`
    }
}