diff options
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | client/Cargo.toml | 2 | ||||
-rw-r--r-- | common/src/impl.rs | 8 | ||||
-rw-r--r-- | common/src/lib.rs | 4 | ||||
-rw-r--r-- | import/Cargo.toml | 2 | ||||
-rw-r--r-- | import/src/main.rs | 79 | ||||
-rw-r--r-- | server/src/main.rs | 13 |
7 files changed, 102 insertions, 8 deletions
@@ -1303,6 +1303,7 @@ name = "jellything-import" version = "0.1.0" dependencies = [ "anyhow", + "base64", "bincode 2.0.0-rc.3", "clap", "env_logger", @@ -1310,6 +1311,7 @@ dependencies = [ "jellymatroska", "jellyremuxer", "log", + "rand", "reqwest", "serde", "serde_json", diff --git a/client/Cargo.toml b/client/Cargo.toml index a2bed77..aa3f94d 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" [dependencies] jellycommon = { path = "../common" } log = "0.4.19" -reqwest = "0.11.18" +reqwest = { version = "0.11.18", features = ["json"] } anyhow = "1.0.72" serde_json = "1.0.104" diff --git a/common/src/impl.rs b/common/src/impl.rs index 55364ab..d7759af 100644 --- a/common/src/impl.rs +++ b/common/src/impl.rs @@ -3,7 +3,7 @@ which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2023 metamuffin <metamuffin.org> */ -use crate::{SourceTrack, SourceTrackKind}; +use crate::{NodeKind, SourceTrack, SourceTrackKind}; impl SourceTrackKind { pub fn letter(&self) -> char { @@ -34,3 +34,9 @@ impl std::fmt::Display for SourceTrack { )) } } + +impl Default for NodeKind { + fn default() -> Self { + Self::Collection + } +} diff --git a/common/src/lib.rs b/common/src/lib.rs index 60cb37f..a96df9e 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -17,7 +17,7 @@ pub struct Node { } #[rustfmt::skip] -#[derive(Debug, Clone, Deserialize, Serialize)] +#[derive(Debug, Clone, Deserialize, Serialize, Default)] pub struct NodePrivate { #[serde(default)] pub id: Option<String>, #[serde(default)] pub import: Option<RemoteImportOptions>, @@ -27,7 +27,7 @@ pub struct NodePrivate { } #[rustfmt::skip] -#[derive(Debug, Clone, Deserialize, Serialize)] +#[derive(Debug, Clone, Deserialize, Serialize, Default)] pub struct NodePublic { pub kind: NodeKind, pub title: String, diff --git a/import/Cargo.toml b/import/Cargo.toml index 4e351c6..2e35e18 100644 --- a/import/Cargo.toml +++ b/import/Cargo.toml @@ -17,3 +17,5 @@ reqwest = { version = "0.11.18", features = ["blocking", "json"] } serde = { version = "1.0.180", features = ["derive"] } serde_json = "1.0.104" bincode = { version = "2.0.0-rc.3", features = ["serde"] } +base64 = "0.21.2" +rand = "0.8.5" diff --git a/import/src/main.rs b/import/src/main.rs index 2d66221..26899bb 100644 --- a/import/src/main.rs +++ b/import/src/main.rs @@ -3,19 +3,23 @@ which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2023 metamuffin <metamuffin.org> */ +#![feature(file_create_new)] + pub mod infojson; pub mod tmdb; use anyhow::Context; +use base64::Engine; use clap::{Parser, Subcommand}; use infojson::YVideo; use jellycommon::{ - AssetLocation, LocalTrack, MediaInfo, MediaSource, Node, NodeKind, NodePrivate, NodePublic, - Rating, + config::GlobalConfig, AssetLocation, LocalTrack, MediaInfo, MediaSource, Node, NodeKind, + NodePrivate, NodePublic, Rating, }; use jellymatroska::read::EbmlReader; use jellyremuxer::import::{import_metadata, seek_index}; use log::{info, warn}; +use rand::random; use std::{ fs::{remove_file, File}, io::{stdin, Write}, @@ -34,22 +38,39 @@ struct Args { #[derive(Subcommand)] enum Action { + /// Initialize a new jellything instance + Init { + /// Base path of the instance, must either be absolute or relative to the servers pwd + base_path: PathBuf, + #[arg(short, long)] + brand: String, + }, + /// Imports a movie, video or series given media and metadata sources New { + /// Relative path to the node's parent(!). path: PathBuf, + /// Search the node by title on TMDB #[arg(short = 't', long)] tmdb_search: Option<String>, + /// Search the node by id on TMDB #[arg(short = 'T', long)] tmdb_id: Option<String>, #[arg(long)] + /// Prefix the inferred id with something to avoid collisions ident_prefix: Option<String>, + /// Copies media into the library #[arg(long)] copy: bool, + /// Moves media into the library (potentially destructive operation) #[arg(long)] r#move: bool, + /// Marks node as a video #[arg(long)] video: bool, + /// Path to the media of the node, required for non-series #[arg(short, long)] input: Option<PathBuf>, + /// Marks node as a series #[arg(short, long)] series: bool, }, @@ -63,6 +84,56 @@ fn main() -> anyhow::Result<()> { let args = Args::parse(); match args.action { + Action::Init { + base_path: path, + brand, + } => { + info!("creating new instance..."); + std::fs::create_dir_all(path.join("library"))?; + std::fs::create_dir_all(path.join("cache"))?; + std::fs::create_dir_all(path.join("assets"))?; + File::create_new(path.join("assets/front.htm"))? + .write_fmt(format_args!("<h1>My very own jellything instance</h1>"))?; + serde_json::to_writer( + File::create_new(path.join("config.json"))?, + &GlobalConfig { + brand: brand.clone(), + slogan: "Creative slogan here".to_string(), + asset_path: path.join("assets"), + cache_path: path.join("cache"), + library_path: path.join("library"), + database_path: path.join("database"), + cookie_key: Some( + base64::engine::general_purpose::STANDARD + .encode([(); 32].map(|_| random())), + ), + session_key: Some( + base64::engine::general_purpose::STANDARD + .encode([(); 32].map(|_| random())), + ), + admin_username: "admin".to_string(), + admin_password: "hackme".to_string(), + login_expire: 10, + ..Default::default() + }, + )?; + serde_json::to_writer( + File::create_new(path.join("library/directory.json"))?, + &Node { + public: NodePublic { + kind: NodeKind::Collection, + title: "My Library".to_string(), + ..Default::default() + }, + private: NodePrivate { + ..Default::default() + }, + }, + )?; + info!("{brand:?} is ready!"); + warn!("please change the admin password."); + Ok(()) + } Action::New { path, tmdb_id, @@ -74,6 +145,10 @@ fn main() -> anyhow::Result<()> { video, r#move, } => { + if std::env::current_dir().unwrap().file_name().unwrap() != "library" { + warn!("new command can only be used in the library directory; what you are doing right now probably wont work.") + } + let tmdb_kind = if series { "tv" } else { "movie" }; let tmdb_id = if let Some(id) = tmdb_id { Some(id.parse().unwrap()) diff --git a/server/src/main.rs b/server/src/main.rs index 3da0e43..b10831f 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -19,8 +19,17 @@ pub mod federation; pub mod import; pub mod routes; -pub static CONF: Lazy<GlobalConfig> = - Lazy::new(|| serde_json::from_reader(File::open("data/config.json").unwrap()).unwrap()); +pub static CONF: Lazy<GlobalConfig> = Lazy::new(|| { + serde_json::from_reader( + File::open( + std::env::args() + .nth(1) + .expect("First argument must specify the config.json to use."), + ) + .unwrap(), + ) + .unwrap() +}); fn main() { enable_logging(); |