Skip to content

Commit 55a9a77

Browse files
feat: Improve cli and dod parsing
1 parent 68bee59 commit 55a9a77

File tree

2 files changed

+96
-72
lines changed

2 files changed

+96
-72
lines changed

src/cli.rs

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use std::{fmt::Display, path::PathBuf};
2+
3+
use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, Utc};
4+
use clap::{command, Args, Parser, ValueEnum};
5+
6+
use crate::{
7+
data_providers::{
8+
flightradar24_provider::FlightRadar24ApiProvider, json_provider::FlightDataFileProvider,
9+
FlightDataProvider,
10+
},
11+
models::result::{GTError, GTResult},
12+
};
13+
14+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
15+
pub enum FlightDataSrc {
16+
Json,
17+
Api,
18+
}
19+
20+
impl Display for FlightDataSrc {
21+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22+
let text = match self {
23+
Self::Json => "json",
24+
Self::Api => "api",
25+
};
26+
f.write_str(text)
27+
}
28+
}
29+
30+
fn parse_dod_date(s: &str) -> Result<DateTime<Utc>, String> {
31+
match NaiveDate::parse_from_str(s, "%d %b %Y") {
32+
Ok(date) => {
33+
let dod = NaiveDateTime::new(
34+
date,
35+
NaiveTime::from_num_seconds_from_midnight_opt(0, 0)
36+
.expect("Midnight value should have succeeded."),
37+
);
38+
39+
Ok(dod.and_utc())
40+
}
41+
Err(e) => Err(format!("Invalid dod value provided ('{s}'). Error: {e}")),
42+
}
43+
}
44+
45+
#[derive(Args)]
46+
#[command(version, about)]
47+
pub struct TagArgs {
48+
/// The flight code of the flight on which the images were taken.
49+
#[arg(long)]
50+
pub flight_code: String,
51+
52+
/// Which source to use for flight geodata.
53+
#[arg(short, long, name = "src", default_value_t = FlightDataSrc::Json)]
54+
pub flight_data_src: FlightDataSrc,
55+
56+
/// Date of flight departure.
57+
#[arg(short, long, name = "dod", value_parser = parse_dod_date, default_value_t = Utc::now())]
58+
pub date_of_departure: DateTime<Utc>,
59+
60+
/// File path to flight geodata json file.
61+
#[arg(short, long)]
62+
pub json_file: Option<PathBuf>,
63+
64+
/// Path to directory containing all images to geotag.
65+
pub images_dir: PathBuf,
66+
}
67+
68+
impl TagArgs {
69+
pub fn try_get_provider(&self) -> GTResult<Box<dyn FlightDataProvider>> {
70+
match self.flight_data_src {
71+
FlightDataSrc::Json => {
72+
if let Some(ref path) = self.json_file {
73+
Ok(Box::new(FlightDataFileProvider::new(path.clone())))
74+
} else {
75+
GTResult::Err(GTError::Args("Invalid configuration.".to_string()))
76+
}
77+
}
78+
FlightDataSrc::Api => Ok(Box::new(FlightRadar24ApiProvider::new(
79+
self.flight_code.clone(),
80+
self.date_of_departure,
81+
))),
82+
}
83+
}
84+
}
85+
86+
#[derive(Parser)]
87+
#[command(name = "airmode-tagger")]
88+
#[command(bin_name = "airmode-tagger")]
89+
pub enum Cli {
90+
Tag(TagArgs),
91+
}

src/main.rs

+5-72
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,15 @@
1+
mod cli;
12
mod data_providers;
23
mod image_geotagger;
34
mod models;
45
mod parsers;
56

6-
use std::{fmt::Display, path::PathBuf, process::exit};
7+
use std::process::exit;
78

8-
use chrono::{DateTime, Utc};
9-
use clap::{Args, Parser, ValueEnum};
10-
use data_providers::{
11-
flightradar24_provider::FlightRadar24ApiProvider, json_provider::FlightDataFileProvider,
12-
FlightDataProvider,
13-
};
9+
use clap::Parser;
10+
use cli::{Cli, TagArgs};
1411
use image_geotagger::ImageGeotagger;
15-
use models::result::{GTError, GTResult};
16-
17-
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
18-
enum FlightDataSrc {
19-
Json,
20-
Api,
21-
}
22-
23-
impl Display for FlightDataSrc {
24-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25-
let text = match self {
26-
Self::Json => "json",
27-
Self::Api => "api",
28-
};
29-
f.write_str(text)
30-
}
31-
}
32-
33-
#[derive(Args)]
34-
#[command(version, about)]
35-
struct TagArgs {
36-
/// The flight code of the flight on which the images were taken.
37-
#[arg(long)]
38-
flight_code: String,
39-
40-
/// Which source to use for flight geodata.
41-
#[arg(short, long, name = "src", default_value_t = FlightDataSrc::Json)]
42-
flight_data_src: FlightDataSrc,
43-
44-
/// Date of flight departure.
45-
#[arg(short, long, name = "dod", default_value_t = Utc::now())]
46-
date_of_departure: DateTime<Utc>,
47-
48-
/// File path to flight geodata json file.
49-
#[arg(short, long)]
50-
json_file: Option<PathBuf>,
51-
52-
/// Path to directory containing all images to geotag.
53-
images_dir: PathBuf,
54-
}
55-
56-
impl TagArgs {
57-
pub fn try_get_provider(&self) -> GTResult<Box<dyn FlightDataProvider>> {
58-
match self.flight_data_src {
59-
FlightDataSrc::Json => {
60-
if let Some(ref path) = self.json_file {
61-
Ok(Box::new(FlightDataFileProvider::new(path.clone())))
62-
} else {
63-
GTResult::Err(GTError::Args("Invalid configuration.".to_string()))
64-
}
65-
}
66-
FlightDataSrc::Api => Ok(Box::new(FlightRadar24ApiProvider::new(
67-
self.flight_code.clone(),
68-
self.date_of_departure,
69-
))),
70-
}
71-
}
72-
}
73-
74-
#[derive(Parser)]
75-
#[command(name = "airmode-tagger")]
76-
#[command(bin_name = "airmode-tagger")]
77-
enum Cli {
78-
Tag(TagArgs),
79-
}
12+
use models::result::GTResult;
8013

8114
fn main() {
8215
let Cli::Tag(tag) = Cli::parse();

0 commit comments

Comments
 (0)