finish program init
This commit is contained in:
parent
9714c5dcaf
commit
4d3df70a2e
33
Cargo.lock
generated
33
Cargo.lock
generated
@ -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",
|
||||
|
@ -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"] }
|
||||
|
@ -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");
|
||||
}
|
@ -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?;
|
||||
|
@ -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,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -4,8 +4,8 @@ use std::{
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use log::*;
|
||||
use regex::Regex;
|
||||
use simplelog::*;
|
||||
|
||||
mod custom;
|
||||
pub mod v_drawtext;
|
||||
|
@ -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;
|
||||
|
@ -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},
|
||||
|
@ -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::{
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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}");
|
||||
return Err(1);
|
||||
};
|
||||
}
|
||||
|
||||
Err(e) => {
|
||||
error!("{e}");
|
||||
return Err(1);
|
||||
}
|
||||
if let Err(e) = insert_user(&pool, user).await {
|
||||
eprintln!("{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);
|
||||
}
|
||||
|
@ -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::{
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user