Skip to content

Commit 9a0ec57

Browse files
committed
improved automation support
1 parent 47fd53b commit 9a0ec57

9 files changed

Lines changed: 384 additions & 250 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vsd/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- `save`
13+
- Removed `--all-streams`, `--audio-lang`, `--quality`, `--skip-audio`, `--skip-subs`, `--skip-video`, `--subs-lang` flags and merged there functionality into `--select-streams` flag,
14+
1015
### Fixed
1116

1217
- `save`

vsd/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ keywords = ["m3u8", "mpd"]
99
license = "MIT OR Apache-2.0"
1010
name = "vsd"
1111
repository = "https://github.com/clitic/vsd/tree/main/vsd"
12-
version = "0.4.1"
12+
version = "0.4.2"
1313
readme = "README.md"
1414

1515
[dependencies]

vsd/src/automation.rs

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
use std::collections::HashSet;
2+
3+
pub struct Prompter {
4+
pub interactive: bool,
5+
pub interactive_raw: bool,
6+
}
7+
8+
#[derive(Debug)]
9+
pub struct SelectOptions {
10+
pub audio: AudioSubs,
11+
pub stream_numbers: HashSet<usize>,
12+
pub subs: AudioSubs,
13+
pub video: Video,
14+
}
15+
16+
#[derive(Debug)]
17+
pub struct Video {
18+
pub all: bool,
19+
pub preference: VideoPreference,
20+
pub resolutions: HashSet<(u16, u16)>,
21+
pub skip: bool,
22+
}
23+
24+
#[derive(Debug)]
25+
pub enum VideoPreference {
26+
Best,
27+
None,
28+
Worst,
29+
}
30+
31+
#[derive(Debug)]
32+
pub struct AudioSubs {
33+
pub all: bool,
34+
pub languages: HashSet<String>,
35+
pub skip: bool,
36+
}
37+
38+
impl SelectOptions {
39+
pub fn parse(data: &str) -> SelectOptions {
40+
let mut auto = SelectOptions {
41+
audio: AudioSubs {
42+
all: false,
43+
languages: HashSet::new(),
44+
skip: false,
45+
},
46+
stream_numbers: HashSet::new(),
47+
subs: AudioSubs {
48+
all: false,
49+
languages: HashSet::new(),
50+
skip: false,
51+
},
52+
video: Video {
53+
all: false,
54+
preference: VideoPreference::None,
55+
resolutions: HashSet::new(),
56+
skip: false,
57+
},
58+
};
59+
60+
for stream in data.split_terminator(':') {
61+
if let Some((_type, queries)) = stream.split_once('=') {
62+
match _type {
63+
"v" => {
64+
for query in queries.split_terminator(',') {
65+
if let Ok(stream_number) = query.parse::<usize>() {
66+
auto.stream_numbers.insert(stream_number);
67+
}
68+
69+
match query {
70+
"all" => auto.video.all = true,
71+
"skip" => auto.video.skip = true,
72+
// resolutions
73+
"best" | "high" | "max" => {
74+
auto.video.preference = VideoPreference::Best;
75+
}
76+
"low" | "min" | "worst" => {
77+
auto.video.preference = VideoPreference::Worst;
78+
}
79+
"144p" => {
80+
let _ = auto.video.resolutions.insert((256, 144));
81+
}
82+
"240p" => {
83+
let _ = auto.video.resolutions.insert((426, 240));
84+
}
85+
"360p" => {
86+
let _ = auto.video.resolutions.insert((640, 360));
87+
}
88+
"480p" => {
89+
let _ = auto.video.resolutions.insert((854, 480));
90+
}
91+
"720p" | "hd" => {
92+
let _ = auto.video.resolutions.insert((1280, 720));
93+
}
94+
"1080p" | "fhd" => {
95+
let _ = auto.video.resolutions.insert((1920, 1080));
96+
}
97+
"2k" => {
98+
let _ = auto.video.resolutions.insert((2048, 1080));
99+
}
100+
"1440p" | "qhd" => {
101+
let _ = auto.video.resolutions.insert((2560, 1440));
102+
}
103+
"4k" => {
104+
let _ = auto.video.resolutions.insert((3840, 2160));
105+
}
106+
"8k" => {
107+
let _ = auto.video.resolutions.insert((7680, 4320));
108+
}
109+
x => {
110+
if let Some((w, h)) = x.split_once('x') {
111+
if let (Ok(w), Ok(h)) = (w.parse::<u16>(), h.parse::<u16>())
112+
{
113+
auto.video.resolutions.insert((w, h));
114+
}
115+
}
116+
}
117+
}
118+
}
119+
}
120+
"a" => {
121+
for query in queries.split_terminator(',') {
122+
if let Ok(stream_number) = query.parse::<usize>() {
123+
auto.stream_numbers.insert(stream_number);
124+
}
125+
126+
match query {
127+
"all" => auto.audio.all = true,
128+
"skip" => auto.audio.skip = true,
129+
x => {
130+
auto.audio.languages.insert(x.to_owned());
131+
}
132+
}
133+
}
134+
}
135+
"s" => {
136+
for query in queries.split_terminator(',') {
137+
if let Ok(stream_number) = query.parse::<usize>() {
138+
auto.stream_numbers.insert(stream_number);
139+
}
140+
141+
match query {
142+
"all" => auto.subs.all = true,
143+
"skip" => auto.subs.skip = true,
144+
x => {
145+
auto.subs.languages.insert(x.to_owned());
146+
}
147+
}
148+
}
149+
}
150+
_ => (),
151+
}
152+
}
153+
}
154+
155+
auto
156+
}
157+
}
158+
159+
impl AudioSubs {
160+
pub fn contains_exact_lang(&mut self, s_lang: &str) -> bool {
161+
let languages = self.languages.clone();
162+
163+
for lang in &languages {
164+
if lang == s_lang {
165+
self.languages.remove(lang);
166+
return true;
167+
}
168+
}
169+
170+
false
171+
}
172+
173+
pub fn contains_siml_lang(&mut self, s_lang: &str) -> bool {
174+
let languages = self.languages.clone();
175+
176+
for lang in &languages {
177+
if lang.to_lowercase().get(0..2) == s_lang.to_lowercase().get(0..2) {
178+
self.languages.remove(lang);
179+
return true;
180+
}
181+
}
182+
183+
false
184+
}
185+
}

0 commit comments

Comments
 (0)