Coverage for src/iptvtools/cli.py: 64%

47 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2025-01-31 13:48 +0000

1"""Command Line Interface.""" 

2 

3import logging 

4import shutil 

5 

6import click 

7 

8from iptvtools import exceptions 

9from iptvtools.config import Config 

10from iptvtools.constants import defaults, helps 

11from iptvtools.models import Playlist 

12 

13 

14@click.group( 

15 context_settings={"show_default": True}, 

16) 

17@click.version_option() 

18def cli() -> None: 

19 """CLI for IPTVTools.""" 

20 

21 

22@cli.command() 

23@click.option("--channel-exclude", help=helps.CHANNEL_EXCLUDE) 

24@click.option("--channel-include", help=helps.CHANNEL_INCLUDE) 

25@click.option("--group-exclude", help=helps.GROUP_EXCLUDE) 

26@click.option("--group-include", help=helps.GROUP_INCLUDE) 

27@click.option( 

28 "--max-height", default=defaults.MAX_HEIGHT, type=int, help=helps.MAX_HEIGHT 

29) 

30@click.option( 

31 "--min-height", default=defaults.MIN_HEIGHT, type=int, help=helps.MIN_HEIGHT 

32) 

33@click.option("-c", "--config", default=defaults.CONFIG, help=helps.CONFIG) 

34@click.option( 

35 "-i", "--inputs", multiple=True, default=defaults.INPUTS, help=helps.INPUTS 

36) 

37@click.option( 

38 "-I", "--interval", default=defaults.INTERVAL, type=int, help=helps.INTERVAL 

39) 

40@click.option("-L", "--log-level", default=defaults.LOG_LEVEL, help=helps.LOG_LEVEL) 

41@click.option( 

42 "-n", 

43 "--skip-connectivity-check", 

44 is_flag=True, 

45 help=helps.SKIP_CONNECTIVITY_CHECK, 

46) 

47@click.option("-o", "--output", default=defaults.OUTPUT, help=helps.OUTPUT) 

48@click.option( 

49 "-r", 

50 "--replace-group-by-source", 

51 is_flag=True, 

52 help=helps.REPLACE_GROUP_BY_SOURCE, 

53) 

54@click.option( 

55 "-R", 

56 "--resolution-on-title", 

57 is_flag=True, 

58 help=helps.RESOLUTION_ON_TITLE, 

59) 

60@click.option( 

61 "-s", "--sort-keys", multiple=True, default=defaults.SORT_KEYS, help=helps.SORT_KEYS 

62) 

63@click.option( 

64 "-t", "--templates", multiple=True, default=defaults.TEMPLATES, help=helps.TEMPLATES 

65) 

66@click.option("-T", "--timeout", default=defaults.TIMEOUT, type=int, help=helps.TIMEOUT) 

67@click.option("-u", "--udpxy", default=defaults.UDPXY, help=helps.UDPXY) 

68def filter( 

69 channel_exclude: str, 

70 channel_include: str, 

71 group_exclude: str, 

72 group_include: str, 

73 max_height: int, 

74 min_height: int, 

75 config: str, 

76 inputs: list[str], 

77 interval: int, 

78 log_level: str, 

79 skip_connectivity_check: bool, 

80 output: str, 

81 replace_group_by_source: bool, 

82 resolution_on_title: bool, 

83 sort_keys: list[str], 

84 templates: list[str], 

85 timeout: int, 

86 udpxy: str, 

87) -> None: 

88 """Filter m3u playlists.""" 

89 logging.basicConfig(level=log_level.upper()) 

90 

91 if (max_height or min_height or resolution_on_title) and shutil.which( 

92 "ffprobe" 

93 ) is None: 

94 raise exceptions.FFmpegNotInstalledError() 

95 

96 Config.init(config) 

97 playlist = Playlist( 

98 channel_exclude, 

99 channel_include, 

100 group_exclude, 

101 group_include, 

102 max_height, 

103 min_height, 

104 inputs, 

105 interval, 

106 skip_connectivity_check, 

107 output, 

108 replace_group_by_source, 

109 resolution_on_title, 

110 sort_keys, 

111 templates, 

112 timeout, 

113 udpxy, 

114 ) 

115 playlist.parse() 

116 playlist.filter() 

117 playlist.export() 

118 if playlist.inaccessible_urls: 

119 logging.info("Inaccessible Urls:") 

120 logging.info("\n".join(sorted(playlist.inaccessible_urls))) 

121 if playlist.low_res_urls: 

122 logging.info("Low resolution Urls:") 

123 logging.info("\n".join(sorted(playlist.low_res_urls))) 

124 if playlist.high_res_urls: 

125 logging.info("High resolution Urls:") 

126 logging.info("\n".join(sorted(playlist.high_res_urls)))