aboutsummaryrefslogtreecommitdiff
path: root/import/src
diff options
context:
space:
mode:
Diffstat (limited to 'import/src')
-rw-r--r--import/src/main.rs79
1 files changed, 77 insertions, 2 deletions
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())