57DU4YHARHICJPWTTHSBB5O7MAW7GJVJUMVEREGVWEMHCGI7JMLQC
KHBYSOY7O3OGZLSIYZL6XRYHPNESD7WG2IAT7JT7HBTTCZVW4WJAC
ED7GAY6WJJ6Y3476KCKQULZ4XF73XBREX6FLX6URUAWCL5KDTBBQC
XIHPYOWDLQY2MVMVUQPH23O3TBALRG4G2CHSLWSCAYMY5NVJ32WQC
DP6ASS5FJGSZUG2B4SQOKZVHFAVZLEHFVEWBNFG3BHMC6FZAJNHQC
MQKD76RYJOC3SJ4EPKQRQFV7A2BRJAHAI4VMMLR4EKV4B3EV5YTQC
UIMZBURR7KOWSREO4GDH5C2LZDUTEZBKQNYWBYSFGUTRYJ4GKSNQC
LG3NDQDEZ65QP564QKTTYC3XI4ZN3NVW4B5T36QJEBHMJAEH4VEAC
JYSIHNS67XTGAR4HN7ZHWFMGGYSK5IY6J6EHO4YUZOR7UMMWAORQC
476KTQSS5NXVCTVLVZQRGSYD5OAFBYG75VTSWBN26Q45RSMRT5YQC
HTHQWZRRS5N2J3VMS4VFT3MMOBA4MHVTO6REWCHU2RJIDSN3HTSQC
AFGKYLKUV6QBTL7JYDNOUCO2BVUR6CUB5MAKA3V3C76XGCWJULQAC
3YR56Y65UIAL3J7PUXWVJMOOHYZYDIX4V54OT2TJPZ25WQ6MXHCQC
5JMYBRF3UYX4LFH7JK6S4BEDKRVKDFIL4YKTCWKMKP4TMNNGQFKQC
NE63ERXN7OUYSQ4PGPIQIIKEYD7OAOWXXSGMTORD6RJNUZHRLVJAC
HXMFYFMLDAJOOUUALCZRUJJFOIWUFK7CGO5MNSJVO2XMR63KOTAAC
IMRHIIAUQDSKU4D6YONK67D6GH7ZLLMMB5S2HRZT76SYNJ7M2RSQC
52CTWUQP2WCBMYNGOIOLOVUYWXF3YOJAPJY3WIHIFLIQD2WHIDFQC
O3VZ5J3LIYD3KBZLZA6HOJI7MVOV5DEODDPCPOMIBTPCO3CZW4YQC
GE7XXDPC73SUY6I6F3X6I4QFQO2BCPHD4MZALYOWG7H7SRE5XAFQC
BSPWOOHZMN3RAOHGJ2A3XKUOUCFFAOXS7YR67E3AARPPPIA5YPDAC
76TBVFPIFU3LSMXY5NAHZBH6HRJLSLK43PGOPL6QQ2YYVBJ64QAQC
EZMX4SYFEBYNJVQETRVAYONU5MIMQYTTSA5DRMTQET5B7CL6CI6AC
37X6ZKCCWP4OPXA7QMA2VG2IZHSXS6TQFTKMONU35NLMWKA47JUQC
5FEMSWRS6SMVKBJAV4IYJLEJ2CML6QNZM75UGQFIIMAR5FBAACXAC
ADXMUSFXOKBPCHW4XS3T4KLWMPGQPYDMZW6YFFSHZPAQKEGIKCBQC
MQKOX2CQ7AON24UJC7RORAC7Y2UROROVG7BBKLVWURPXKY75JV5AC
Y6BVNXQ747WQKVB4JO3AHYOMBWNNJNPC6SG2UUCCZRIIXDMXJYDQC
J64KBLKALQ3HQCY4HJU5H6WBXTATS7TKBYNNUUSNJE7JLWLYO66QC
use crate::utils::*;
use std::fs;
fn migrate_old_subscriptions() -> Result<()> {
let path = get_podcast_dir()?;
let mut old_path = path.clone();
old_path.push(".subscriptions");
if old_path.exists() {
println!("Migrating old subscriptions file...");
let new_path = get_sub_file()?;
fs::rename(&old_path, &new_path)?;
}
Ok(())
}
pub fn migrate() -> Result<()> {
migrate_old_subscriptions()
}
use anyhow::Result;
pub async fn update_subscription(client: &reqwest::Client, sub: &mut Subscription, config: Option<Config>) -> Result<()> {
pub async fn update_subscription(
client: &reqwest::Client,
index: usize,
sub: &Subscription,
config: Option<Config>,
) -> Result<[usize; 2]> {
for c in futures::future::join_all(d_vec).await.iter() {
if let Err(err) = c {
println!("Error: {}", err);
let new_subscriptions = futures::future::join_all(d_vec).await;
for c in &new_subscriptions {
match c {
Ok([index, new_ep_count]) => {
state.subscriptions[*index].num_episodes = *new_ep_count;
},
Err(err) => {
println!("Error: {}", err);
}
command_handler::handle_matches(&VERSION, &client, &mut state, config, &mut app, &matches).await?;
state.save()
// Instantiate the global state of the application
let mut state = State::new( VERSION, config).await?;
command_handler::handle_matches(&VERSION, &mut state, config, &mut app, &matches)
.await?;
let public_state: PublicState = state.into();
public_state.save()?;
Ok(())
pub struct PublicState {
pub version: String,
pub last_run_time: DateTime<Utc>,
pub config: Config,
pub subscriptions: Vec<Subscription>,
}
impl From<State> for PublicState {
fn from(internal_state: State) -> Self {
PublicState {
version: internal_state.version,
last_run_time: internal_state.last_run_time,
config: internal_state.config,
subscriptions: internal_state.subscriptions,
}
}
}
impl PublicState {
pub fn save(&self) -> Result<()> {
let mut path = config_path()?;
path.set_extension("json.tmp");
let file = File::create(&path)?;
serde_json::to_writer(BufWriter::new(file), self)?;
fs::rename(&path, config_path()?)?;
Ok(())
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
struct ParseState {
version: Option<String>,
last_run_time: Option<DateTime<Utc>>,
config: Option<Config>,
subscriptions: Option<Vec<Subscription>>,
}
impl From<ParseState> for State {
fn from(internal_state: ParseState) -> Self {
State {
version: internal_state.version.unwrap(),
last_run_time: internal_state.last_run_time.unwrap_or_else(|| Utc::now()),
config: internal_state.config.unwrap_or_else(|| Config::default()),
subscriptions: internal_state.subscriptions.unwrap_or_else(|| vec![]),
client: reqwest::Client::new(),
}
}
}
pub async fn new(client: &reqwest::Client, version: &str) -> Result<State> {
let path = get_sub_file()?;
if path.exists() {
let file = File::open(&path)?;
let mut state: State = serde_json::from_reader(BufReader::new(&file))?;
pub async fn new(version: &str, config: Config) -> Result<State> {
let config_path = config_path()?;
let legacy_subscription_path = get_sub_file()?;
// TODO This moves legacy file into new location. Remove this.
if legacy_subscription_path.exists() {
std::fs::rename(&legacy_subscription_path, &config_path)?;
}
if config_path.exists() {
let file = File::open(&config_path)?;
// Read the file into an internal struct that allows optionally missing fields
let parse_state: ParseState = serde_json::from_reader(BufReader::new(&file))?;
// Convert to our public state that has sensible default for non-present fields
let mut state: State = parse_state.into();
// Override version to the version currently running
// Check if a day has passed (86400 seconds) since last launch
if 86400
< Utc::now()
.signed_duration_since(state.last_run_time)
.num_seconds()
// Check if a day has passed since last launch
if 0 < Utc::now()
.signed_duration_since(state.last_run_time)
.num_days()
self.save()
}
pub fn save(&self) -> Result<()> {
let mut path = get_sub_file()?;
path.set_extension("json.tmp");
let file = File::create(&path)?;
serde_json::to_writer(BufWriter::new(file), self)?;
fs::rename(&path, get_sub_file()?)?;