• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Nikorag / iplayarr / 18683849359

21 Oct 2025 12:29PM UTC coverage: 76.094% (-3.0%) from 79.052%
18683849359

push

github

web-flow
Merge pull request #176 from Nikorag/cache-episode-metadata

Cache Episode Metadata

428 of 645 branches covered (66.36%)

Branch coverage included in aggregate %.

26 of 26 new or added lines in 4 files covered. (100.0%)

94 existing lines in 7 files now uncovered.

1711 of 2166 relevant lines covered (78.99%)

11.57 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.31
/src/validators/ConfigFormValidator.ts
1
import Handlebars from 'handlebars';
2✔
2

3
import nzbFacade from '../facade/nzbFacade';
2✔
4
import { FilenameTemplateContext } from '../types/FilenameTemplateContext';
5
import { Validator } from './Validator';
2✔
6

7
const cronRegex: RegExp =
8
    /^(\*|([0-5]?[0-9])) (\*|([01]?[0-9]|2[0-3])) (\*|([01]?[1-9]|[12][0-9]|3[01])) (\*|([1-9]|1[0-2])) (\*|([0-6]))(\s(\d{4}))?$/;
2✔
9

10
export class ConfigFormValidator extends Validator {
2✔
11
    async validate(input: any): Promise<{ [key: string]: string }> {
12
        const validatorError: { [key: string]: string } = {};
7✔
13
        if (!this.directoryExists(input.DOWNLOAD_DIR)) {
7✔
14
            validatorError['DOWNLOAD_DIR'] = `Directory ${input.DOWNLOAD_DIR} does not exist`;
4✔
15
        }
16
        if (!this.directoryExists(input.COMPLETE_DIR)) {
7✔
17
            validatorError['COMPLETE_DIR'] = `Directory ${input.COMPLETE_DIR} does not exist`;
4✔
18
        }
19
        if (!this.isNumber(input.ACTIVE_LIMIT)) {
7✔
20
            validatorError['ACTIVE_LIMIT'] = 'Download limit must be a number';
4✔
21
        } else if (input.ACTIVE_LIMIT < 0) {
3✔
22
            validatorError['ACTIVE_LIMIT'] = 'Download limit must be a positive number';
1✔
23
        }
24

25
        if (!this.isNumber(input.RSS_FEED_HOURS)) {
7✔
26
            validatorError['RSS_FEED_HOURS'] = 'RSS Feed Hours must be a number';
5✔
27
        } else if (input.RSS_FEED_HOURS < 0) {
2!
28
            validatorError['RSS_FEED_HOURS'] = 'RSS Feed Hours must be a positive number';
×
29
        }
30

31
        if (!input.AUTH_USERNAME) {
7✔
32
            validatorError['AUTH_USERNAME'] = 'Please provide a Username';
5✔
33
        }
34
        if (!input.AUTH_PASSWORD) {
7✔
35
            validatorError['AUTH_PASSWORD'] = 'Please provide a Password';
5✔
36
        }
37
        if (!this.matchesRegex(input.REFRESH_SCHEDULE, cronRegex)) {
7✔
38
            validatorError['REFRESH_SCHEDULE'] = 'Please provide a valid cron expression';
5✔
39
        }
40
        if (!this.compilesSuccessfully(input.TV_FILENAME_TEMPLATE)) {
7✔
41
            validatorError['TV_FILENAME_TEMPLATE'] = 'Template does not compile';
5✔
42
        }
43
        if (!this.compilesSuccessfully(input.MOVIE_FILENAME_TEMPLATE)) {
7✔
44
            validatorError['MOVIE_FILENAME_TEMPLATE'] = 'Template does not compile';
5✔
45
        }
46
        if (input.NZB_URL || input.NZB_API_KEY || input.NZB_TYPE || input.NZB_USERNAME || input.NZB_PASSWORD) {
7✔
47
            const response: string | boolean = await nzbFacade.testConnection(
2✔
48
                input.NZB_TYPE,
49
                input.NZB_URL,
50
                input.NZB_API_KEY,
51
                input.NZB_USERNAME,
52
                input.NZB_PASSWORD
53
            );
54
            if (response != true) {
2✔
55
                validatorError['NZB_URL'] = response as string;
1✔
56
                validatorError['NZB_API_KEY'] = response as string;
1✔
57
                validatorError['NZB_USERNAME'] = response as string;
1✔
58
                validatorError['NZB_PASSWORD'] = response as string;
1✔
59
            }
60
        }
61
        if (input.AUTH_TYPE === 'oidc') {
7!
UNCOV
62
            if (!input.OIDC_CONFIG_URL) {
×
UNCOV
63
                validatorError['OIDC_CONFIG_URL'] = 'Please provide a valid OIDC configuration URL';
×
64
            }
UNCOV
65
            if (!input.OIDC_CLIENT_ID) {
×
UNCOV
66
                validatorError['OIDC_CLIENT_ID'] = 'Please provide a valid OIDC client ID';
×
67
            }
UNCOV
68
            if (!input.OIDC_CLIENT_SECRET) {
×
UNCOV
69
                validatorError['OIDC_CLIENT_SECRET'] = 'Please provide a valid OIDC client secret';
×
70
            }
UNCOV
71
            if (!input.OIDC_CALLBACK_HOST) {
×
UNCOV
72
                validatorError['OIDC_CALLBACK_HOST'] = 'Please provide a valid OIDC callback host';
×
73
            }
UNCOV
74
            if (!input.OIDC_ALLOWED_EMAILS || input.OIDC_ALLOWED_EMAILS.length === 0) {
×
UNCOV
75
                validatorError['OIDC_ALLOWED_EMAILS'] = 'Please provide at least one allowed email';
×
76
            }
77
        }
78
        return validatorError;
7✔
79
    }
80

81
    compilesSuccessfully(template: string): boolean {
82
        try {
14✔
83
            const hbTemplate = Handlebars.compile(template, { strict: true });
14✔
84
            const dummyContext: FilenameTemplateContext = {
6✔
85
                title: 'title',
86
                season: '01',
87
                episode: '01',
88
                quality: '720p',
89
            };
90
            hbTemplate(dummyContext);
6✔
91
            return true;
4✔
92
        } catch {
93
            return false;
10✔
94
        }
95
    }
96
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc