Skip to content

Commit

Permalink
Add support for self signed certificates (#85) (#86)
Browse files Browse the repository at this point in the history
Added a builtin reqwest::get() function that includes a "self_signed_cert" boolean field.
Changed every reqwest::get() that interacts with jellyfin with crate::get().
Updated example.json's with "self_signed_cert" fields.
Fixed example config test.
  • Loading branch information
Radiicall authored Nov 19, 2023
1 parent 3f34ded commit 57622f2
Show file tree
Hide file tree
Showing 12 changed files with 168 additions and 97 deletions.
22 changes: 3 additions & 19 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions example.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"display": "genres",
"separator": "-"
},
"self_signed_cert": false,
"_comment": "the 4 lines below and this line arent needed and should be removed, by default nothing will display if these are present",
"blacklist": {
"media_types": ["music", "movie", "episode", "livetv"],
Expand Down
6 changes: 3 additions & 3 deletions jellyfin-rpc-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "jellyfin-rpc-cli"
version = "0.15.4"
version = "0.15.5"
edition = "2021"
description = "Displays the content you're currently watching on Discord!"
license = "GPL-3.0-or-later"
Expand All @@ -27,8 +27,8 @@ retry = "2.0"

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

[dependencies.clap]
features = ["derive"]
Expand Down
34 changes: 27 additions & 7 deletions jellyfin-rpc-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use clap::Parser;
use colored::Colorize;
use discord_rich_presence::{activity, DiscordIpc, DiscordIpcClient};
pub use jellyfin_rpc::services::imgur::*;
pub use jellyfin_rpc::prelude::*;
pub use jellyfin_rpc::services::imgur::*;
use retry::retry_with_index;
#[cfg(feature = "updates")]
mod updates;
Expand All @@ -26,6 +26,13 @@ struct Args {
help = "Path to image urls file for imgur"
)]
image_urls: Option<String>,
#[arg(
short = 's',
long = "suppress-warnings",
help = "Stops warnings from showing on startup",
default_value_t = false
)]
suppress_warnings: bool,
}

#[tokio::main]
Expand Down Expand Up @@ -68,11 +75,22 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
"Jellyfin-RPC".bright_blue()
);

if config
.clone()
.images
.and_then(|images| images.enable_images)
.unwrap_or(false)
if !args.suppress_warnings && config.jellyfin.self_signed_cert.is_some_and(|val| val) {
eprintln!(
"{}\n{}",
"------------------------------------------------------------------".bold(),
"WARNING: Self-signed certificates are enabled!"
.bold()
.red()
);
}

if !args.suppress_warnings
&& config
.clone()
.images
.and_then(|images| images.enable_images)
.unwrap_or(false)
&& !config
.clone()
.images
Expand All @@ -82,7 +100,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
eprintln!(
"{}\n{}",
"------------------------------------------------------------------".bold(),
"Images without Imgur requires port forwarding!"
"WARNING: Images without Imgur requires port forwarding!"
.bold()
.red()
)
Expand Down Expand Up @@ -174,6 +192,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
&config.jellyfin.api_key,
&content.item_id,
library,
config.jellyfin.self_signed_cert.unwrap_or(false),
)
.await?;
}
Expand Down Expand Up @@ -207,6 +226,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.and_then(|imgur| imgur.client_id)
.expect("Imgur client ID cant be loaded."),
args.image_urls.clone(),
config.jellyfin.self_signed_cert.unwrap_or(false),
)
.await
.unwrap_or_else(|e| {
Expand Down
2 changes: 1 addition & 1 deletion jellyfin-rpc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "jellyfin-rpc"
version = "0.1.4"
version = "0.1.5"
edition = "2021"
description = "Backend for the Jellyfin-RPC-cli and Jellyfin-RPC-Iced projects"
license = "GPL-3.0-or-later"
Expand Down
1 change: 1 addition & 0 deletions jellyfin-rpc/example.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"display": "genres",
"separator": "-"
},
"self_signed_cert": false,
"_comment": "the 4 lines below and this line arent needed and should be removed, by default nothing will display if these are present",
"blacklist": {
"media_types": ["music", "movie", "episode", "livetv"],
Expand Down
17 changes: 10 additions & 7 deletions jellyfin-rpc/src/core/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ use serde_json;
use std::env;

/// Main struct containing every other struct in the file.
///
///
/// The config file is parsed into this struct.
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[serde(rename_all = "lowercase")]
pub struct Config {
/// Jellyfin configuration.
///
///
/// Has every required part of the config, hence why its not an `Option<Jellyfin>`.
pub jellyfin: Jellyfin,
/// Discord configuration.
Expand All @@ -35,6 +35,8 @@ pub struct Jellyfin {
pub music: Option<Music>,
/// Blacklist configuration.
pub blacklist: Option<Blacklist>,
/// Self signed certificate option
pub self_signed_cert: Option<bool>,
}

/// Username of the person that info should be gathered from.
Expand All @@ -51,15 +53,15 @@ pub enum Username {
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct Music {
/// Display is where you tell the program what should be displayed.
///
///
/// Example: `vec![String::from("genres"), String::from("year")]`
pub display: Option<Display>,
/// Separator is what should be between the artist(s) and the `display` options.
pub separator: Option<char>,
}

/// Display is where you tell the program what should be displayed.
///
///
/// Example: `vec![String::from("genres"), String::from("year")]`
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[serde(untagged)]
Expand Down Expand Up @@ -89,7 +91,7 @@ pub struct Discord {
}

/// Button struct
///
///
/// Contains information about buttons
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct Button {
Expand All @@ -116,9 +118,9 @@ pub struct Images {
}

/// Find config.json in filesystem.
///
///
/// This is to avoid the user having to specify a filepath on launch.
///
///
/// Default config path depends on OS
/// Windows: `%appdata%\jellyfin-rpc\config.json`
/// Linux/macOS: `~/.config/jellyfin-rpc/config.json`
Expand Down Expand Up @@ -154,6 +156,7 @@ impl Default for Config {
api_key: "".to_string(),
music: None,
blacklist: None,
self_signed_cert: None,
},
discord: None,
imgur: None,
Expand Down
2 changes: 1 addition & 1 deletion jellyfin-rpc/src/core/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::prelude::MediaType;
use discord_rich_presence::activity;

/// Used to set the activity on Discord.
///
///
/// This has checks to do different things for different mediatypes and replaces images with default ones if they are needed.
pub fn setactivity<'a>(
state_message: &'a str,
Expand Down
17 changes: 15 additions & 2 deletions jellyfin-rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
/// Main module
pub mod core;
/// Useful imports
///
///
/// Contains imports that most programs will be using.
pub mod prelude;
/// External connections
pub mod services;
pub use crate::core::error;
pub use core::rpc::setactivity;
use discord_rich_presence::DiscordIpc;
use discord_rich_presence::DiscordIpcClient;
use retry::retry_with_index;
pub use core::rpc::setactivity;
#[cfg(test)]
mod tests;

Expand Down Expand Up @@ -61,3 +61,16 @@ pub fn connect(rich_presence_client: &mut DiscordIpcClient) {
)
.unwrap();
}

/// Built in reqwest::get() function, has an extra field to specify if the self signed cert should be accepted.
pub async fn get<U: reqwest::IntoUrl>(
url: U,
self_signed_cert: bool,
) -> Result<reqwest::Response, reqwest::Error> {
reqwest::Client::builder()
.danger_accept_invalid_certs(self_signed_cert)
.build()?
.get(url)
.send()
.await
}
31 changes: 24 additions & 7 deletions jellyfin-rpc/src/services/imgur.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ pub struct Imgur {
}

/// Find urls.json in filesystem, used to store images that were already previously uploaded to imgur.
///
///
/// This is to avoid the user having to specify a filepath on launch.
///
///
/// Default urls.json path depends on OS
/// Windows: `%appdata%\jellyfin-rpc\urls.json`
/// Linux/macOS: `~/.config/jellyfin-rpc/urls.json`
Expand All @@ -32,13 +32,14 @@ pub fn get_urls_path() -> Result<String, ImgurError> {

impl Imgur {
/// Queries the urls.json file for an imgur url with the same item ID attached.
///
///
/// If there's no imgur URL in the file, it will upload the image to imgur, store it in the file and then hand the URL over in a result.
pub async fn get(
image_url: &str,
item_id: &str,
client_id: &str,
image_urls_file: Option<String>,
self_signed_cert: bool,
) -> Result<Self, ImgurError> {
let file = match image_urls_file {
Some(file) => file,
Expand All @@ -53,7 +54,15 @@ impl Imgur {
}

Ok(Self {
url: Imgur::write_file(file, image_url, item_id, client_id, &mut json).await?,
url: Imgur::write_file(
file,
image_url,
item_id,
client_id,
self_signed_cert,
&mut json,
)
.await?,
})
}

Expand Down Expand Up @@ -87,12 +96,13 @@ impl Imgur {
image_url: &str,
item_id: &str,
client_id: &str,
self_signed_cert: bool,
json: &mut Value,
) -> Result<String, ImgurError> {
// Create a new map that's used for adding data to the "urls.json" file
let mut new_data = serde_json::Map::new();
// Upload the content's image to imgur
let imgur_url = Imgur::upload(image_url, client_id).await?;
let imgur_url = Imgur::upload(image_url, client_id, self_signed_cert).await?;
// Insert the item_id and the new image url into the map we created earlier
new_data.insert(item_id.to_string(), json!(imgur_url));

Expand All @@ -105,8 +115,15 @@ impl Imgur {
Ok(imgur_url)
}

async fn upload(image_url: &str, client_id: &str) -> Result<String, ImgurError> {
let img = reqwest::get(image_url).await?.bytes().await?;
async fn upload(
image_url: &str,
client_id: &str,
self_signed_cert: bool,
) -> Result<String, ImgurError> {
let img = crate::get(image_url, self_signed_cert)
.await?
.bytes()
.await?;
let client = reqwest::Client::new();
let response = client
.post("https://api.imgur.com/3/image")
Expand Down
Loading

0 comments on commit 57622f2

Please sign in to comment.