Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash fixes #82

Merged
merged 5 commits into from
Nov 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 2 additions & 16 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion jellyfin-rpc-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ retry = "2.0"

[dependencies.jellyfin-rpc]
features = ["imgur", "cli"]
version = "0.1.2"
#version = "0.1.2"
path = "../jellyfin-rpc"

[dependencies.clap]
features = ["derive"]
Expand Down
4 changes: 2 additions & 2 deletions jellyfin-rpc-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

// Start loop
loop {
let mut content = Content::try_get(&config).await;
let mut content = Content::try_get(&config, 1).await;

let mut blacklist_check = true;
config
Expand Down Expand Up @@ -309,6 +309,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
);
}

std::thread::sleep(std::time::Duration::from_secs(3));
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
}
}
2 changes: 1 addition & 1 deletion jellyfin-rpc-cli/src/updates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub async fn checker() {
.bold(),
"This can be safely ignored if you are running a prerelease version".bold()
);
std::thread::sleep(std::time::Duration::from_secs(1));
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
}
}

Expand Down
1 change: 1 addition & 0 deletions jellyfin-rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ discord-rich-presence = "0.2"
retry = "2.0"
serde_json = "1.0"
async-recursion = "1.0.5"
tokio = "1"

[dependencies.colored]
version = "2.0"
Expand Down
8 changes: 5 additions & 3 deletions jellyfin-rpc/src/core/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,11 @@ pub struct Images {

pub fn get_config_path() -> Result<String, ConfigError> {
if cfg!(not(windows)) {
let xdg_config_home = env::var("XDG_CONFIG_HOME").unwrap_or_else(|_| {
env::var("HOME").expect("No HOME environment variable") + "/.config"
});
let xdg_config_home = match env::var("XDG_CONFIG_HOME") {
Ok(xdg_config_home) => xdg_config_home,
Err(_) => env::var("HOME")? + "/.config",
};

Ok(xdg_config_home + ("/jellyfin-rpc/main.json"))
} else {
let app_data = env::var("APPDATA")?;
Expand Down
20 changes: 20 additions & 0 deletions jellyfin-rpc/src/core/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ impl From<env::VarError> for ConfigError {

#[derive(Debug)]
pub enum ImgurError {
InvalidResponse,
Reqwest(String),
Io(String),
Json(String),
VarError(String),
None,
}

impl From<reqwest::Error> for ImgurError {
Expand All @@ -63,3 +65,21 @@ impl From<env::VarError> for ImgurError {
Self::VarError(format!("Unable to get environment variables: {}", value))
}
}

#[derive(Debug)]
pub enum ContentError {
Reqwest(reqwest::Error, String),
Json(serde_json::Error),
}

impl From<serde_json::Error> for ContentError {
fn from(value: serde_json::Error) -> Self {
Self::Json(value)
}
}

impl From<reqwest::Error> for ContentError {
fn from(value: reqwest::Error) -> Self {
Self::Reqwest(value, "Is your Jellyfin URL set correctly?".to_string())
}
}
2 changes: 1 addition & 1 deletion jellyfin-rpc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
pub mod services;
pub use crate::services::jellyfin;
use discord_rich_presence::DiscordIpc;
use discord_rich_presence::DiscordIpcClient;
use retry::retry_with_index;
pub use crate::services::jellyfin;
pub mod core;
pub use crate::core::config::{get_config_path, Button, Config};

Expand Down
60 changes: 28 additions & 32 deletions jellyfin-rpc/src/services/imgur.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ pub struct Imgur {

pub fn get_urls_path() -> Result<String, ImgurError> {
if cfg!(not(windows)) {
let xdg_config_home = env::var("XDG_CONFIG_HOME").unwrap_or_else(|_| {
env::var("HOME").expect("No HOME environment variable") + "/.config"
});
let xdg_config_home = match env::var("XDG_CONFIG_HOME") {
Ok(xdg_config_home) => xdg_config_home,
Err(_) => env::var("HOME")? + "/.config",
};

Ok(xdg_config_home + ("/jellyfin-rpc/urls.json"))
} else {
let app_data = env::var("APPDATA")?;
Expand All @@ -31,8 +33,11 @@ impl Imgur {
client_id: &str,
image_urls_file: Option<String>,
) -> Result<Self, ImgurError> {
let file = image_urls_file
.unwrap_or_else(|| get_urls_path().expect("Failed to get \"urls.json\" file path"));
let file = match image_urls_file {
Some(file) => file,
None => get_urls_path()?,
};

let mut json = Imgur::read_file(file.clone())?;
if let Some(value) = json.get(item_id).and_then(Value::as_str) {
return Ok(Self {
Expand All @@ -46,31 +51,25 @@ impl Imgur {
}

fn read_file(file: String) -> Result<Value, ImgurError> {
let content = fs::read_to_string(file.clone()).unwrap_or_else(|_| {
// Create directories
let path = path::Path::new(&file).parent().unwrap_or_else(|| {
eprintln!("Unable to convert \"{}\" to path", file);
std::process::exit(1);
});
fs::create_dir_all(path).ok();
let content = match fs::read_to_string(file.clone()) {
Ok(content) => content,
Err(_) => {
// Create directories
let path = path::Path::new(&file).parent().ok_or(ImgurError::from(
std::io::Error::new(std::io::ErrorKind::NotFound, file.clone()),
))?;
fs::create_dir_all(path)?;

// Create urls.json file
fs::File::create(file.clone())
.map(|mut file| {
// Create urls.json file
fs::File::create(file.clone()).map(|mut file| {
write!(file, "{{\n}}").ok();
file
})
.unwrap_or_else(|err| {
eprintln!("Unable to create file: \"{}\"\nerror: {}", file, err);
std::process::exit(1)
});

// Read the newly created file
fs::read_to_string(file.clone()).unwrap_or_else(|err| {
eprintln!("Unable to read file: \"{}\"\nerror: {}", file, err);
std::process::exit(1);
})
});
})?;

// Read the newly created file
fs::read_to_string(file.clone())?
}
};

let json: Value = serde_json::from_str(&content)?;
Ok(json)
Expand All @@ -91,7 +90,7 @@ impl Imgur {
new_data.insert(item_id.to_string(), json!(imgur_url));

// Turn the old json data into a map and append the new map to the old one
let data = json.as_object_mut().expect("\"urls.json\" file is not an object, try deleting the file and running the program again.");
let data = json.as_object_mut().ok_or(ImgurError::None)?; //.expect("\"urls.json\" file is not an object, try deleting the file and running the program again.");
data.append(&mut new_data);

// Overwrite the "urls.json" file with the new data
Expand All @@ -115,10 +114,7 @@ impl Imgur {

Ok(val["data"]["link"]
.as_str()
.unwrap_or_else(|| {
eprintln!("imgur returned no image url!\n{}", val);
std::process::exit(1)
})
.ok_or(ImgurError::InvalidResponse)?
.to_string())
}
}
41 changes: 22 additions & 19 deletions jellyfin-rpc/src/services/jellyfin.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::core::config::{Config, Display, Username};
use crate::core::error::ContentError;
use async_recursion::async_recursion;
use serde::{de::Visitor, Deserialize, Serialize};
use serde_json::Value;
use async_recursion::async_recursion;

/*
TODO: Comments
Expand Down Expand Up @@ -77,14 +78,28 @@ pub struct Content {

impl Content {
#[async_recursion]
pub async fn try_get(config: &Config) -> Self {
pub async fn try_get(config: &Config, attempt: u64) -> Self {
let mut time = attempt * 5;
if time > 30 {
time = 30
}

match Content::get(config).await {
Ok(content) => content,
Err(_) => Content::try_get(config).await,
Err(error) => {
eprintln!{"{}: Error while getting content: {:#?}", attempt, error}
while time > 0 {
eprint!("\rRetrying in {} seconds…", time);
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
time -= 1
}
eprintln!("");
Content::try_get(config, attempt + 1).await
},
}
}

pub async fn get(config: &Config) -> Result<Self, reqwest::Error> {
pub async fn get(config: &Config) -> Result<Self, ContentError> {
let sessions: Vec<Value> = serde_json::from_str(
&reqwest::get(format!(
"{}/Sessions?api_key={}",
Expand All @@ -94,13 +109,7 @@ impl Content {
.await?
.text()
.await?,
)
.unwrap_or_else(|_| {
panic!(
"Can't unwrap URL, check if the Jellyfin URL is correct. Current URL: {}",
config.jellyfin.url
)
});
)?;
for session in sessions {
if session.get("UserName").is_none() {
continue;
Expand Down Expand Up @@ -572,7 +581,7 @@ pub async fn library_check(
api_key: &str,
item_id: &str,
library: &str,
) -> Result<bool, reqwest::Error> {
) -> Result<bool, Box<dyn std::error::Error>> {
let parents: Vec<Value> = serde_json::from_str(
&reqwest::get(format!(
"{}/Items/{}/Ancestors?api_key={}",
Expand All @@ -583,13 +592,7 @@ pub async fn library_check(
.await?
.text()
.await?,
)
.unwrap_or_else(|_| {
panic!(
"Can't unwrap URL, check if the Jellyfin URL is correct. Current URL: {}",
url
)
});
)?;

for i in parents {
if let Some(name) = i.get("Name").and_then(Value::as_str) {
Expand Down
Loading