123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- use std::{fs, path::Path};
- use axum::{
- response::Redirect,
- routing::{get, get_service},
- Router,
- };
- use minijinja::Environment;
- use ost::client::OSClient;
- use serde::Serialize;
- use tower_http::services::ServeDir;
- use tracing::info;
- pub mod error;
- pub mod ost;
- pub mod routes;
- #[derive(Debug, Clone)]
- pub struct State {
- client: OSClient,
- env: Environment<'static>,
- base_path: String,
- }
- lazy_static::lazy_static! {
- pub static ref INDEX: String =
- std::fs::read_to_string("assets/index.html").expect("missing template");
- }
- lazy_static::lazy_static! {
- pub static ref FILE_CONTAINER: String =
- std::fs::read_to_string("assets/filecontainer.html").expect("missing template");
- }
- #[tokio::main]
- async fn main() {
- dotenv::dotenv().expect("could not load env");
- tracing_subscriber::fmt().init();
- let client = OSClient::init().await;
- info!("Successfully loaded client");
- let base_path = std::env::var("BASE_PATH").expect("base path not configured");
- let mut env = Environment::new();
- env.add_template("file_container", &FILE_CONTAINER)
- .expect("unable to add template");
- env.add_template("index", &INDEX)
- .expect("unable to add template");
- let state = State {
- client,
- env,
- base_path,
- };
- let router = axum::Router::new()
- .route("/", get(|| async { Redirect::permanent("/dir/root") }))
- .route("/dir/*key", get(routes::get_directory))
- .route("/subtitles", get(routes::search_subtitles))
- .route("/guess", get(routes::guess_it))
- .route("/download", get(routes::download_subtitles))
- .with_state(state);
- let router_static = Router::new().fallback(get_service(ServeDir::new("assets")));
- let listener = tokio::net::TcpListener::bind("0.0.0.0:3001").await.unwrap();
- axum::serve(listener, router.merge(router_static))
- .await
- .unwrap();
- }
- pub fn scan_dir_contents(path: impl AsRef<Path>) -> std::io::Result<Vec<FileType>> {
- let entries = fs::read_dir(path)?
- .filter_map(Result::ok)
- .collect::<Vec<_>>();
- let subs = entries
- .iter()
- .filter_map(|entry| {
- let path = entry.path();
- let ext = path.extension()?.to_str()?;
- let (name, _) = path.file_name()?.to_str()?.split_once(ext)?;
- (ext == "srt").then_some(name.to_owned())
- })
- .collect::<Vec<_>>();
- let mut files: Vec<_> = entries
- .iter()
- .filter_map(|entry| {
- if entry.path().is_dir() {
- Some(FileType::Directory(Directory {
- name: entry.file_name().to_str().unwrap_or_default().to_string(),
- path: entry.path().to_str().unwrap_or_default().to_string(),
- }))
- // Skip existing subtitles
- } else if entry.path().extension().is_some_and(|ext| {
- ext.to_str().is_some_and(|ext| ext == "srt")
- || ext.to_str().is_some_and(|ext| ext == "smi")
- }) {
- None
- } else {
- let path = entry.path();
- let ext = path.extension()?.to_str()?;
- let (name, _) = path.file_name()?.to_str()?.split_once(ext)?;
- Some(FileType::File(File {
- name: entry.file_name().to_str().unwrap_or_default().to_string(),
- path: entry.path().to_str().unwrap_or_default().to_string(),
- has_subs: subs.contains(&name.to_string()),
- }))
- }
- })
- .collect();
- files.sort();
- Ok(files)
- }
- #[derive(Debug, Serialize, PartialEq, Eq, PartialOrd, Ord)]
- pub enum FileType {
- Directory(Directory),
- File(File),
- }
- #[derive(Debug, Serialize, PartialEq, Eq, PartialOrd, Ord)]
- pub struct File {
- name: String,
- path: String,
- /// `true` if a same file exists with a `.srt` extension found
- /// in the same directory
- has_subs: bool,
- }
- #[derive(Debug, Serialize, PartialEq, Eq, PartialOrd, Ord)]
- pub struct Directory {
- name: String,
- path: String,
- }
|