finish program init

This commit is contained in:
jb-alvarado 2024-06-14 10:37:49 +02:00
parent 9714c5dcaf
commit 4d3df70a2e
16 changed files with 145 additions and 175 deletions

33
Cargo.lock generated
View File

@ -1100,7 +1100,6 @@ dependencies = [
"serde_json",
"shlex",
"signal-child",
"simplelog",
"sqlx",
"static-files",
"sysinfo",
@ -2218,15 +2217,6 @@ dependencies = [
"libc",
]
[[package]]
name = "num_threads"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
dependencies = [
"libc",
]
[[package]]
name = "object"
version = "0.35.0"
@ -2972,18 +2962,6 @@ dependencies = [
"time",
]
[[package]]
name = "simplelog"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16257adbfaef1ee58b1363bdc0664c9b8e1e30aed86049635fb5f147d065a9c0"
dependencies = [
"log",
"paris",
"termcolor",
"time",
]
[[package]]
name = "slab"
version = "0.4.9"
@ -3435,15 +3413,6 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]]
name = "tests"
version = "0.24.0"
@ -3497,9 +3466,7 @@ checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [
"deranged",
"itoa",
"libc",
"num-conv",
"num_threads",
"powerfmt",
"serde",
"time-core",

View File

@ -50,7 +50,6 @@ rpassword = "7.2"
sanitize-filename = "0.5"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
simplelog = { version = "0.12", features = ["paris"] }
shlex = "1.1"
static-files = "0.2"
sysinfo ={ version = "0.30", features = ["linux-netdevs"] }

View File

@ -1,101 +0,0 @@
use log::{LevelFilter, Log, Metadata, Record};
use simplelog::*;
use std::fs::File;
pub struct LogMailer {
level: LevelFilter,
pub config: Config,
}
impl LogMailer {
pub fn new(log_level: LevelFilter, config: Config) -> Box<LogMailer> {
Box::new(LogMailer {
level: log_level,
config,
})
}
}
impl Log for LogMailer {
fn enabled(&self, metadata: &Metadata<'_>) -> bool {
metadata.level() <= self.level
}
fn log(&self, record: &Record<'_>) {
if self.enabled(record.metadata()) {
let _rec = record.args().to_string();
println!("{record:?}");
println!("target: {:?}", record.target());
}
}
fn flush(&self) {}
}
impl SharedLogger for LogMailer {
fn level(&self) -> LevelFilter {
self.level
}
fn config(&self) -> Option<&Config> {
Some(&self.config)
}
fn as_log(self: Box<Self>) -> Box<dyn Log> {
Box::new(*self)
}
}
struct Log2 {
logger: Box<WriteLogger<File>>,
}
impl Log2 {
fn new() -> Self {
let log_file = File::create("log_file.log").expect("Failed to create log file");
let config = ConfigBuilder::new()
.set_time_format_custom(format_description!(
"[[[year]-[month]-[day] [hour]:[minute]:[second].[subsecond digits:5]]"
))
.build();
let logger = WriteLogger::new(LevelFilter::Debug, config, log_file);
Log2 { logger }
}
fn debug(&self, message: &str) {
self.logger.log(
&Record::builder()
.args(format_args!("{}", message))
.level(Level::Debug)
.build(),
);
}
}
fn main() {
let log2 = Log2::new();
log2.debug("Debug-Message in Logger 2");
// std::thread::spawn(move || {
// log2.debug("Error-Message in Logger 2");
// });
CombinedLogger::init(vec![
TermLogger::new(
LevelFilter::Debug,
Config::default(),
TerminalMode::Mixed,
ColorChoice::Auto,
),
LogMailer::new(LevelFilter::Info, Config::default()),
])
.unwrap();
info!("Info in Logger 1");
warn!("Warning in Logger 1");
}

View File

@ -3,8 +3,8 @@ use argon2::{
Argon2, PasswordHasher,
};
use log::*;
use rand::{distributions::Alphanumeric, Rng};
use simplelog::*;
use sqlx::{sqlite::SqliteQueryResult, Pool, Sqlite};
use tokio::task;
@ -40,11 +40,28 @@ pub async fn db_migrate(conn: &Pool<Sqlite>) -> Result<&'static str, Box<dyn std
}
pub async fn select_global(conn: &Pool<Sqlite>) -> Result<GlobalSettings, sqlx::Error> {
let query = "SELECT secret, hls_path, playlist_path, storage_path, logging_path FROM global WHERE id = 1";
let query = "SELECT id, secret, hls_path, logging_path, playlist_path, storage_path, shared_storage FROM global WHERE id = 1";
sqlx::query_as(query).fetch_one(conn).await
}
pub async fn update_global(
conn: &Pool<Sqlite>,
global: GlobalSettings,
) -> Result<SqliteQueryResult, sqlx::Error> {
let query = "UPDATE global SET hls_path = $2, playlist_path = $3, storage_path = $4, logging_path = $5, shared_storage = $6 WHERE id = 1";
sqlx::query(query)
.bind(global.id)
.bind(global.hls_path)
.bind(global.playlist_path)
.bind(global.storage_path)
.bind(global.logging_path)
.bind(global.shared_storage)
.execute(conn)
.await
}
pub async fn select_channel(conn: &Pool<Sqlite>, id: &i32) -> Result<Channel, sqlx::Error> {
let query = "SELECT * FROM channels WHERE id = $1";
let mut result: Channel = sqlx::query_as(query).bind(id).fetch_one(conn).await?;

View File

@ -13,11 +13,13 @@ use crate::utils::config::PlayoutConfig;
#[derive(Debug, Deserialize, Serialize, sqlx::FromRow)]
pub struct GlobalSettings {
pub id: i32,
pub secret: Option<String>,
pub hls_path: String,
pub logging_path: String,
pub playlist_path: String,
pub storage_path: String,
pub logging_path: String,
pub shared_storage: bool,
}
impl GlobalSettings {
@ -27,11 +29,13 @@ impl GlobalSettings {
match global_settings.await {
Ok(g) => g,
Err(_) => GlobalSettings {
id: 0,
secret: None,
hls_path: String::new(),
logging_path: String::new(),
playlist_path: String::new(),
storage_path: String::new(),
logging_path: String::new(),
shared_storage: false,
},
}
}

View File

@ -79,13 +79,13 @@ async fn main() -> std::io::Result<()> {
panic!("{e}");
};
init_globales(&pool).await;
init_logging(mail_queues.clone())?;
if let Err(c) = run_args(&pool).await {
exit(c);
}
init_globales(&pool).await;
init_logging(mail_queues.clone())?;
let channel_controllers = Arc::new(Mutex::new(ChannelController::new()));
if let Some(conn) = &ARGS.listen {

View File

@ -4,8 +4,8 @@ use std::{
sync::{Arc, Mutex},
};
use log::*;
use regex::Regex;
use simplelog::*;
mod custom;
pub mod v_drawtext;

View File

@ -9,13 +9,13 @@ use std::{
time::Duration,
};
use log::*;
use notify::{
event::{CreateKind, ModifyKind, RemoveKind, RenameMode},
EventKind::{Create, Modify, Remove},
RecursiveMode, Watcher,
};
use notify_debouncer_full::new_debouncer;
use simplelog::*;
use crate::player::utils::{include_file_extension, Media};
use crate::utils::config::PlayoutConfig;

View File

@ -6,7 +6,7 @@ use std::{
};
use crossbeam_channel::Sender;
use simplelog::*;
use log::*;
use crate::utils::{
config::{PlayoutConfig, FFMPEG_IGNORE_ERRORS, FFMPEG_UNRECOVERABLE_ERRORS},

View File

@ -4,8 +4,8 @@ use std::sync::{
};
use lexical_sort::natural_lexical_cmp;
use log::*;
use rand::{seq::SliceRandom, thread_rng};
use simplelog::*;
use walkdir::WalkDir;
use crate::player::{

View File

@ -6,7 +6,7 @@ use std::{
thread,
};
use simplelog::*;
use log::*;
use crate::player::utils::{
get_date, is_remote, json_validate::validate_playlist, modified_time, time_from_header, Media,

View File

@ -12,12 +12,12 @@ use std::{
use chrono::{prelude::*, TimeDelta};
use ffprobe::{ffprobe, Stream as FFStream};
use log::*;
use rand::prelude::*;
use regex::Regex;
use reqwest::header;
use serde::{de::Deserializer, Deserialize, Serialize};
use serde_json::{json, Map, Value};
use simplelog::*;
pub mod folder;
pub mod import;

View File

@ -5,11 +5,13 @@ use std::{
};
use clap::Parser;
use log::*;
use rpassword::read_password;
use sqlx::{Pool, Sqlite};
use crate::db::{db_pool, handles::insert_user, models::User};
use crate::db::{
handles::{self, insert_user},
models::{GlobalSettings, User},
};
use crate::utils::config::PlayoutConfig;
use crate::ARGS;
@ -62,7 +64,7 @@ pub struct Args {
#[clap(
long,
env,
help = "Override logging level: trace, debug, info, warn, error"
help = "Override logging level: trace, debug, println, warn, eprintln"
)]
pub log_level: Option<String>,
@ -81,6 +83,9 @@ pub struct Args {
#[clap(long, env, help = "Storage root path")]
pub storage_path: Option<PathBuf>,
#[clap(long, env, help = "Share storage across channels")]
pub shared_storage: bool,
#[clap(short, long, help = "domain name for initialization")]
pub domain: Option<String>,
@ -102,7 +107,18 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
let mut mail = String::new();
let mut storage = String::new();
let mut playlist = String::new();
let mut logging = String::new();
let mut hls = String::new();
let mut shared_store = String::new();
let mut global = GlobalSettings {
id: 0,
secret: None,
hls_path: String::new(),
playlist_path: String::new(),
storage_path: String::new(),
logging_path: String::new(),
shared_storage: false,
};
print!("Global admin: ");
stdout().flush().unwrap();
@ -136,17 +152,86 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
.expect("Did not enter a correct path?");
if storage.trim().is_empty() {
args.storage_path = Some(PathBuf::from("/var/lib/ffplayout/tv-media"));
global.storage_path = "/var/lib/ffplayout/tv-media".to_string();
} else {
args.storage_path = Some(PathBuf::from(storage.trim()));
global.storage_path = storage
.trim()
.trim_matches(|c| c == '"' || c == '\'')
.to_string();
}
println!("{args:?}");
print!("Playlist path [/var/lib/ffplayout/playlists]: ");
stdout().flush().unwrap();
stdin()
.read_line(&mut playlist)
.expect("Did not enter a correct path?");
if playlist.trim().is_empty() {
global.playlist_path = "/var/lib/ffplayout/playlists".to_string();
} else {
global.playlist_path = playlist
.trim()
.trim_matches(|c| c == '"' || c == '\'')
.to_string();
}
print!("HLS path [/usr/share/ffplayout/public]: ");
stdout().flush().unwrap();
stdin()
.read_line(&mut hls)
.expect("Did not enter a correct path?");
if hls.trim().is_empty() {
global.hls_path = "/usr/share/ffplayout/public".to_string();
} else {
global.hls_path = hls
.trim()
.trim_matches(|c| c == '"' || c == '\'')
.to_string();
}
print!("Logging path [/var/log/ffplayout]: ");
stdout().flush().unwrap();
stdin()
.read_line(&mut logging)
.expect("Did not enter a correct path?");
if logging.trim().is_empty() {
global.logging_path = "/var/log/ffplayout".to_string();
} else {
global.logging_path = logging
.trim()
.trim_matches(|c| c == '"' || c == '\'')
.to_string();
}
print!("Shared storage [Y/n]: ");
stdout().flush().unwrap();
stdin()
.read_line(&mut shared_store)
.expect("Did not enter a correct path?");
if shared_store.trim().to_lowercase().starts_with('y') {
global.shared_storage = true;
} else {
global.shared_storage = false;
}
if let Err(e) = handles::update_global(&pool, global).await {
eprintln!("{e}");
return Err(1);
};
println!("Set global settings...");
}
if let Some(username) = args.username {
if args.mail.is_none() || args.password.is_none() {
error!("Mail/password missing!");
eprintln!("Mail/password missing!");
return Err(1);
}
@ -160,21 +245,12 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
token: None,
};
match db_pool().await {
Ok(conn) => {
if let Err(e) = insert_user(&conn, user).await {
error!("{e}");
if let Err(e) = insert_user(&pool, user).await {
eprintln!("{e}");
return Err(1);
};
}
Err(e) => {
error!("{e}");
return Err(1);
}
};
info!("Create admin user \"{username}\" done...");
println!("Create global admin user \"{username}\" done...");
return Err(0);
}
@ -182,11 +258,11 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
if let Some(id) = ARGS.dump_config {
match PlayoutConfig::dump(&pool, id).await {
Ok(_) => {
info!("Dump config to: ffplayout_{id}.toml");
println!("Dump config to: ffplayout_{id}.toml");
exit(0);
}
Err(e) => {
error!("Dump config: {e}");
eprintln!("Dump config: {e}");
exit(1);
}
@ -196,11 +272,11 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
if let Some(import) = &ARGS.import_config {
match PlayoutConfig::import(&pool, import.clone()).await {
Ok(_) => {
info!("Import config done...");
println!("Import config done...");
exit(0);
}
Err(e) => {
error!("{e}");
eprintln!("{e}");
exit(1);
}

View File

@ -12,8 +12,8 @@ use std::{
use chrono::Timelike;
use lexical_sort::{natural_lexical_cmp, StringSort};
use log::*;
use rand::{seq::SliceRandom, thread_rng, Rng};
use simplelog::*;
use walkdir::WalkDir;
use crate::player::{

View File

@ -21,12 +21,17 @@ use paris::formatter::colorize_string;
use super::ARGS;
use crate::db::models::GlobalSettings;
use crate::utils::{config::Mail, errors::ProcessError, round_to_nearest_ten};
#[derive(Debug)]
pub struct Target;
impl Target {
pub fn all() -> &'static str {
"{file,mail,_Default}"
}
pub fn console() -> &'static str {
"{console}"
}
@ -258,10 +263,12 @@ fn file_formatter(
}
pub fn log_file_path() -> PathBuf {
let config = GlobalSettings::global();
let mut log_path = ARGS
.log_path
.clone()
.unwrap_or(PathBuf::from("/var/log/ffplayout"));
.unwrap_or(PathBuf::from(&config.logging_path));
if !log_path.is_dir() {
log_path = env::current_dir().unwrap();

View File

@ -6,9 +6,10 @@ CREATE TABLE
id INTEGER PRIMARY KEY AUTOINCREMENT,
secret TEXT NOT NULL,
hls_path TEXT NOT NULL DEFAULT "/usr/share/ffplayout/public",
logging_path TEXT NOT NULL DEFAULT "/var/log/ffplayout",
playlist_path TEXT NOT NULL DEFAULT "/var/lib/ffplayout/playlists",
storage_path TEXT NOT NULL DEFAULT "/var/lib/ffplayout/tv-media",
logging_path TEXT NOT NULL DEFAULT "/var/log/ffplayout",
shared_storage INTEGER NOT NULL DEFAULT 1,
UNIQUE (secret)
);