1use std::fs;
2
3use anyhow::{Context, Result};
4use camino::{Utf8Path, Utf8PathBuf};
5use etcetera::{AppStrategy, AppStrategyArgs, choose_app_strategy};
6use flash_font_injector::FontManager;
7use inquire::Text;
8use serde::{Deserialize, Serialize};
9
10use crate::cli::*;
11
12pub mod cli;
13
14const DB_FILE: &str = "fonts.db";
16
17#[derive(Deserialize, Serialize)]
19struct Config {
20 db_url: String,
21 font_root: Utf8PathBuf,
22}
23
24fn load_fonts(config: &Config, ass_path: impl AsRef<Utf8Path>) -> anyhow::Result<()> {
27 let s = ass_font::read_text_auto(ass_path.as_ref())?;
28
29 flash_font::update_font_database(&config.font_root, &config.db_url)?;
30
31 let to_load = ass_font::extract_fonts(&s)
32 .iter()
33 .filter_map(|f| flash_font::select_font_by_name(f, &config.db_url).ok())
34 .filter_map(|v| v.first().cloned())
35 .map(Utf8PathBuf::from)
36 .collect::<Vec<_>>();
37
38 let mut manager = FontManager::default();
39
40 println!("Fonts to load: {:#?}", to_load);
41
42 manager.load_all(to_load)?;
43
44 Ok(())
45}
46
47fn init(
49 font_root: Utf8PathBuf,
50 strategy: impl AppStrategy,
51 config_file: Utf8PathBuf,
52) -> Result<()> {
53 let data_dir = Utf8PathBuf::try_from(strategy.data_dir())?;
54
55 fs::create_dir_all(
56 config_file
57 .parent()
58 .ok_or_else(|| anyhow::anyhow!("config_file must have a parent"))?,
59 )?;
60 fs::create_dir_all(&data_dir)?;
61
62 let db_path = data_dir.join(DB_FILE);
63 let config = Config {
64 db_url: db_path.into_string(),
65 font_root,
66 };
67
68 let toml = toml::to_string_pretty(&config)?;
69 fs::write(&config_file, toml)?;
70
71 println!("✅ Success! Config file saved to:\n {}", config_file);
72 Ok(())
73}
74
75fn app_strategy() -> Result<impl AppStrategy> {
76 Ok(choose_app_strategy(AppStrategyArgs {
77 top_level_domain: "org".to_string(),
78 author: "OpenACGN".to_string(),
79 app_name: "Flash Font Ass".to_string(),
80 })?)
81}
82
83pub fn run(cli: Cli) -> Result<()> {
85 let strategy = app_strategy()?;
86 let config_dir = Utf8PathBuf::try_from(strategy.config_dir())?;
87 let config_file = config_dir.join("config.toml");
88
89 match cli.command {
90 Commands::Load(args) => {
91 let config_toml = fs::read_to_string(&config_file).with_context(|| {
92 format!(
93 "❌ Can't find config file: {config_file}\nPlease run `flash-font-ass init` first."
94 )
95 })?;
96
97 let config: Config = toml::from_str(&config_toml)?;
98 load_fonts(&config, &args.subtitle)?;
99 }
100 Commands::Init => {
101 let font_root =
102 Text::new("Please enter the full path to the font root directory:").prompt()?;
103 init(font_root.into(), strategy, config_file)?;
104 }
105 }
106
107 Ok(())
108}