Skip to content

Commit

Permalink
fixed and polished FILENAME_TITLE_TYPE
Browse files Browse the repository at this point in the history
  • Loading branch information
9-FS committed Nov 23, 2024
1 parent 7d21165 commit 186efc8
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 138 deletions.
166 changes: 87 additions & 79 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ license = "MIT"
name = "nhentai_archivist"
readme = "readme.md"
repository = "https://github.com/9-FS/nhentai_archivist"
version = "3.5.1"
version = "3.6.0"

[dependencies]
chrono = { version = "^0.4.0", features = ["serde"] }
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
services:
nhentai_archivist:
container_name: "nhentai_archivist"
image: "ghcr.io/9-fs/nhentai_archivist:3.5.1"
image: "ghcr.io/9-fs/nhentai_archivist:3.6.0"
environment:
HOST_OS: "Unraid"
TZ: "UTC"
Expand Down
16 changes: 10 additions & 6 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,17 @@ I'm happy about anyone who finds my software useful and feedback is also always

This is the path to the file containing the nHentai ID you want to download, separated by line breaks. If this file exists, it has priority over tag search and console input.

- `FILENAME_TITLE_TYPE`, optional, defaults to `english`
- `FILENAME_TITLE_TYPE`, optional, defaults to `English`

Sets which title to use when naming downloaded files. Available options:
- `english`: Use the English title (default)
- `japanese`: Use the Japanese title if available, falls back to default if not present
- `pretty`: Use the Pretty title if available, falls back to default if not present
Determines which title type to use when naming downloaded hentai files. Available settings:
- `English`
- `Japanese`
- `Pretty`

If a Japanese or pretty title is not available, the English title will be used instead.

> [!IMPORTANT]
> If `FILENAME_TITLE_TYPE` is changed after hentai files have already been downloaded, existing files will not be renamed. They also will not be detected as already downloaded any more which can lead to duplicates. I therefore recommend to only change this setting before starting a fresh library.
- `LIBRARY_PATH`

Expand Down Expand Up @@ -152,7 +157,6 @@ CSRFTOKEN = "your token here"
DATABASE_URL = "./db/db.sqlite"
DONTDOWNLOADME_FILEPATH = "./config/dontdownloadme.txt"
DOWNLOADME_FILEPATH = "./config/downloadme.txt"
FILENAME_TITLE_TYPE = "english"
LIBRARY_PATH = "./hentai/"
LIBRARY_SPLIT = 10000
NHENTAI_TAGS = ['language:"english"']
Expand Down
47 changes: 18 additions & 29 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,5 @@
// Copyright (c) 2024 구FS, all rights reserved. Subject to the MIT licence in `licence.md`.

/// # Summary
/// Available title types for filenames
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Title {
/// Use English title
English,
/// Use Japanese title
Japanese,
/// Use Pretty title
Pretty,
}

impl std::str::FromStr for Title {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().trim() {
"english" => Ok(Self::English),
"japanese" => Ok(Self::Japanese),
"pretty" => Ok(Self::Pretty),
_ => {
log::warn!("Invalid title type \"{s}\", defaulting to English");
Ok(Self::English)
}
}
}
}

/// # Summary
/// Collection of settings making up the configuration of the application.
Expand All @@ -41,7 +14,7 @@ pub struct Config
pub DEBUG: Option<bool>, // debug mode?
pub DONTDOWNLOADME_FILEPATH: Option<String>, // path to file containing hentai ID to not download, blacklist
pub DOWNLOADME_FILEPATH: Option<String>, // path to file containing hentai ID to download
pub FILENAME_TITLE_TYPE: Option<Title>, // which title to use for filenames: English,Japanese,Pretty
pub FILENAME_TITLE_TYPE: Option<TitleType>, // which title to use for filenames: English,Japanese,Pretty
pub LIBRARY_PATH: String, // path to download hentai to
pub LIBRARY_SPLIT: Option<u32>, // split library into subdirectories of maximum this many hentai, None or 0 to disable
pub NHENTAI_TAGS: Option<Vec<String>>, // keep creating downloadme.txt from these tags and keep downloading (server mode), normal tags are in format "tag:{tag}" for example "tag:ffm-threesome"; if None: don't generate downloadme.txt, download hentai once (client mode)
Expand All @@ -62,7 +35,7 @@ impl Default for Config
DEBUG: None, // no entry in default config, defaults to false
DONTDOWNLOADME_FILEPATH: Some("./config/dontdownloadme.txt".to_owned()),
DOWNLOADME_FILEPATH: Some("./config/downloadme.txt".to_owned()),
FILENAME_TITLE_TYPE: Some(Title::English), // Default to English title
FILENAME_TITLE_TYPE: None, // no entry in default config, defaults to English
LIBRARY_PATH: "./hentai/".to_owned(),
LIBRARY_SPLIT: None,
NHENTAI_TAGS: None,
Expand All @@ -71,3 +44,19 @@ impl Default for Config
}
}
}


/// # Summary
/// Title type to use for hentai filenames.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub enum TitleType
{
English,
Japanese,
Pretty,
}

impl Default for TitleType
{
fn default() -> Self {Self::English}
}
47 changes: 26 additions & 21 deletions src/hentai.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) 2024 구FS, all rights reserved. Subject to the MIT licence in `licence.md`.
use crate::api_response::*;
use crate::comicinfoxml::*;
use crate::config::*;
use crate::error::*;
use crate::search_api::*;
use std::io::Read;
Expand Down Expand Up @@ -44,12 +45,13 @@ impl Hentai
/// - `db`: database connection
/// - `http_client`: reqwest http client
/// - `nhentai_hentai_search_url`: nhentai.net hentai search API URL
/// - `filename_title_type`: which title to use for filenames
/// - `library_path`: path to local hentai library
/// - `library_split`: split library into subdirectories with maximum this number of hentai, 0 for no split
///
/// # Returns
/// - created hentai or error
pub async fn new(id: u32, db: &sqlx::sqlite::SqlitePool, http_client: &reqwest::Client, nhentai_hentai_search_url: &str, library_path: &str, library_split: u32, filename_title_type: &Option<Title>) -> Result<Self, HentaiNewError>
pub async fn new(id: u32, db: &sqlx::sqlite::SqlitePool, http_client: &reqwest::Client, nhentai_hentai_search_url: &str, filename_title_type: &TitleType, library_path: &str, library_split: u32) -> Result<Self, HentaiNewError>
{
const FILENAME_SIZE_MAX: u16 = 255; // maximum filename size [B]
const TITLE_CHARACTERS_FORBIDDEN: &str = "\\/:*?\"<>|\t\n"; // forbidden characters in Windows file names
Expand All @@ -60,7 +62,7 @@ impl Hentai
let tags: Vec<Tag>;


if let Ok(Some(s)) = sqlx::query_as("SELECT id, media_id, num_pages, page_types, scanlator, title_english, title_pretty, upload_date FROM Hentai WHERE id = ?")
if let Ok(Some(s)) = sqlx::query_as("SELECT id, media_id, num_pages, page_types, scanlator, title_english, title_japanese, title_pretty, upload_date FROM Hentai WHERE id = ?")
.bind(id)
.fetch_optional(db).await // load hentai metadata from database
{
Expand Down Expand Up @@ -90,30 +92,33 @@ impl Hentai
return Err(HentaiNewError::HentaiLengthInconsistency {page_types: hentai_table_row.page_types.len() as u16, num_pages: hentai_table_row.num_pages});
}

cbz_filename = match filename_title_type {
Some(Title::English) => hentai_table_row.title_english.clone().unwrap_or_default(), //not adding logging as english is default
Some(Title::Japanese) => {
match hentai_table_row.title_japanese.clone() {
Some(title) if !title.is_empty() => title,
_ => {
log::warn!("Japanese title not available for hentai {}, falling back to English title", id);
hentai_table_row.title_japanese.clone().unwrap_or_default()
cbz_filename = match filename_title_type // determine filename title depending on title type
{
TitleType::English => hentai_table_row.title_english.unwrap_or_default(), // english title or fallback to empty string
TitleType::Japanese => // non empty japanese title or fallback to english title
{
match hentai_table_row.title_japanese
{
Some(s) if !s.is_empty() => s,
_ =>
{
log::warn!("Japanese title is not available. Falling back to English title for hentai filename.");
hentai_table_row.title_english.unwrap_or_default() // fallback to english title or further to empty string
}
}
},
Some(Title::Pretty) => {
match hentai_table_row.title_pretty.clone() {
Some(title) if !title.is_empty() => title,
_ => {
log::warn!("Pretty title not available for hentai {}, falling back to English title", id);
hentai_table_row.title_pretty.clone().unwrap_or_default()
TitleType::Pretty => // non empty pretty title or fallback to english title
{
match hentai_table_row.title_pretty.clone()
{
Some(s) if !s.is_empty() => s,
_ =>
{
log::warn!("Pretty title is not available. Falling back to English title for hentai filename.");
hentai_table_row.title_english.unwrap_or_default() // fallback to english title or further to empty string
}
}
},
None => {
log::debug!("No title type specified for hentai {}, using English title", id);
hentai_table_row.title_english.clone().unwrap_or_default()
}
};

cbz_filename.retain(|c| !TITLE_CHARACTERS_FORBIDDEN.contains(c)); // remove forbidden characters
Expand Down Expand Up @@ -422,4 +427,4 @@ pub struct HentaiTableRow
pub title_japanese: Option<String>,
pub title_pretty: Option<String>,
pub upload_date: chrono::DateTime<chrono::Utc>,
}
}
11 changes: 10 additions & 1 deletion src/main_inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,16 @@ pub async fn main_inner(config: Config) -> Result<(), Error>
let hentai: Hentai; // hentai to download


match Hentai::new(*hentai_id, &db, &http_client, NHENTAI_HENTAI_SEARCH_URL, &config.LIBRARY_PATH, config.LIBRARY_SPLIT.unwrap_or_default(), &config.FILENAME_TITLE_TYPE ).await // create hentai, use u32 with 0 to disable library split and not Option<u32> with None, because that would make Some(0) an invalid state
match Hentai::new // create hentai
(
*hentai_id,
&db,
&http_client,
NHENTAI_HENTAI_SEARCH_URL,
&config.FILENAME_TITLE_TYPE.clone().unwrap_or_default(), // if not set: default to english title
&config.LIBRARY_PATH,
config.LIBRARY_SPLIT.unwrap_or_default() // use u32 with 0 to disable library split and not Option<u32> with None, because that would make Some(0) an invalid state
).await
{
Ok(o) => hentai = o, // hentai created successfully
Err(e) => // hentai creation failed
Expand Down
1 change: 1 addition & 0 deletions src/search_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub async fn search_by_id(http_client: &reqwest::Client, nhentai_hentai_search_u
page_types: r_serialised.images.pages.iter().map(|page| format!("{:?}", page.t)).collect::<Vec<String>>().join(""),
scanlator: r_serialised.scanlator,
title_english: r_serialised.title.english,
title_japanese: r_serialised.title.japanese,
title_pretty: r_serialised.title.pretty,
upload_date: r_serialised.upload_date,
});
Expand Down

0 comments on commit 186efc8

Please sign in to comment.