File size: 4,509 Bytes
5ec2e9b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import { IRawResponse } from "youtubei.js";
import { Counter, Registry } from "prom-client";

export class Metrics {
    private METRICS_PREFIX = "invidious_companion_";
    public register = new Registry();

    public createCounter(name: string, help?: string): Counter {
        return new Counter({
            name: `${this.METRICS_PREFIX}${name}`,
            help: help || "No help has been provided for this metric",
            registers: [this.register],
        });
    }

    public potokenGenerationFailure = this.createCounter(
        "potoken_generation_failure_total",
        "Number of times that the PoToken generation job has failed for whatever reason",
    );

    private innertubeErrorStatusLoginRequired = this.createCounter(
        "innertube_error_status_loginRequired_total",
        'Number of times that the status "LOGIN_REQUIRED" has been returned by Innertube API',
    );

    private innertubeErrorStatusUnknown = this.createCounter(
        "innertube_error_status_unknown_total",
        "Number of times that an unknown status has been returned by Innertube API",
    );

    private innertubeErrorReasonSignIn = this.createCounter(
        "innertube_error_reason_SignIn_total",
        'Number of times that the message "Sign in to confirm you’re not a bot." has been returned by Innertube API',
    );

    private innertubeErrorSubreasonProtectCommunity = this.createCounter(
        "innertube_error_subreason_ProtectCommunity_total",
        'Number of times that the message "This helps protect our community." has been returned by Innertube API',
    );

    private innertubeErrorReasonUnknown = this.createCounter(
        "innertube_error_reason_unknown_total",
        "Number of times that an unknown reason has been returned by the Innertube API",
    );

    private innertubeErrorSubreasonUnknown = this.createCounter(
        "innertube_error_subreason_unknown_total",
        "Number of times that an unknown subreason has been returned by the Innertube API",
    );

    public innertubeSuccessfulRequest = this.createCounter(
        "innertube_successful_request_total",
        "Number successful requests made to the Innertube API",
    );

    private innertubeFailedRequest = this.createCounter(
        "innertube_failed_request_total",
        "Number failed requests made to the Innertube API for whatever reason",
    );

    private checkStatus(videoData: IRawResponse) {
        const status = videoData.playabilityStatus?.status;

        return {
            unplayable: status ===
                "UNPLAYABLE",
            contentCheckRequired: status ===
                "CONTENT_CHECK_REQUIRED",
            loginRequired: status === "LOGIN_REQUIRED",
        };
    }

    private checkReason(videoData: IRawResponse) {
        const reason = videoData.playabilityStatus?.reason;

        return {
            signInToConfirmAge: reason?.includes(
                "Sign in to confirm your age",
            ),
            SignInToConfirmBot: reason?.includes(
                "Sign in to confirm you’re not a bot",
            ),
        };
    }

    private checkSubreason(videoData: IRawResponse) {
        const subReason = videoData.playabilityStatus?.errorScreen
            ?.playerErrorMessageRenderer
            ?.subreason?.runs?.[0]?.text;

        return {
            thisHelpsProtectCommunity: subReason?.includes(
                "This helps protect our community",
            ),
        };
    }

    public checkInnertubeResponse(videoData: IRawResponse) {
        this.innertubeFailedRequest.inc();
        const status = this.checkStatus(videoData);

        if (status.contentCheckRequired || status.unplayable) return;

        if (status.loginRequired) {
            this.innertubeErrorStatusLoginRequired.inc();
            const reason = this.checkReason(videoData);

            if (reason.signInToConfirmAge) return;

            if (reason.SignInToConfirmBot) {
                this.innertubeErrorReasonSignIn.inc();
                const subReason = this.checkSubreason(videoData);

                if (subReason.thisHelpsProtectCommunity) {
                    this.innertubeErrorSubreasonProtectCommunity.inc();
                } else {
                    this.innertubeErrorSubreasonUnknown.inc();
                }
            } else {
                this.innertubeErrorReasonUnknown.inc();
            }
        } else {
            this.innertubeErrorStatusUnknown.inc();
        }
    }
}