This commit is contained in:
2022-09-18 07:28:52 +00:00
committed by GitHub
parent e278815f75
commit 4a0bcf394e
9 changed files with 172 additions and 4 deletions

View File

@@ -1,7 +1,86 @@
pub struct PixivDownloaderDbConfig {}
use crate::ext::try_err::TryErr;
use crate::gettext;
use json::JsonValue;
#[cfg(feature = "db_sqlite")]
pub struct PixivDownloaderSqliteConfig {
/// The path of database file
pub path: String,
}
impl Default for PixivDownloaderSqliteConfig {
fn default() -> Self {
Self {
path: "pixiv_downloader.db".to_string(),
}
}
}
pub enum PixivDownloaderDbConfig {
#[cfg(feature = "db_sqlite")]
Sqlite(PixivDownloaderSqliteConfig),
#[allow(dead_code)]
/// No default config is provided
None,
}
#[derive(Debug)]
pub enum PixivDownloaderDbConfigError {
UnkonwnDbType,
MissingField(String),
}
impl std::fmt::Display for PixivDownloaderDbConfigError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::UnkonwnDbType => write!(f, "{}", gettext("Unknown database type.")),
Self::MissingField(s) => write!(f, "{} {}", gettext("Missing field:"), s),
}
}
}
impl PixivDownloaderDbConfig {
pub fn is_none(&self) -> bool {
matches!(self, Self::None)
}
pub fn new(value: &JsonValue) -> Result<Self, PixivDownloaderDbConfigError> {
let db_type = value["type"]
.as_str()
.try_err(PixivDownloaderDbConfigError::UnkonwnDbType)?;
match db_type {
#[cfg(feature = "db_sqlite")]
"sqlite" => {
let path =
value["path"]
.as_str()
.try_err(PixivDownloaderDbConfigError::MissingField(
"path".to_string(),
))?;
Ok(Self::Sqlite(PixivDownloaderSqliteConfig {
path: path.to_string(),
}))
}
_ => Err(PixivDownloaderDbConfigError::UnkonwnDbType),
}
}
}
impl AsRef<PixivDownloaderDbConfig> for PixivDownloaderDbConfig {
fn as_ref(&self) -> &PixivDownloaderDbConfig {
self
}
}
impl Default for PixivDownloaderDbConfig {
fn default() -> Self {
#[cfg(feature = "db_sqlite")]
return Self::Sqlite(PixivDownloaderSqliteConfig::default());
#[cfg(not(feature = "db_sqlite"))]
return Self::None;
}
}
pub fn check_db_config(value: &JsonValue) -> bool {
PixivDownloaderDbConfig::new(value).is_ok()
}

View File

@@ -3,12 +3,17 @@ pub mod config;
pub mod sqlite;
pub mod traits;
pub use config::check_db_config;
pub use config::PixivDownloaderDbConfig;
#[cfg(feature = "db_sqlite")]
pub use sqlite::SqliteError;
pub use config::PixivDownloaderSqliteConfig;
#[cfg(feature = "db_sqlite")]
pub use sqlite::{PixivDownloaderSqlite, SqliteError};
pub use traits::PixivDownloaderDb;
pub type PixivDownloaderDbError = Box<dyn std::fmt::Display + Send + Sync>;
use crate::{get_helper, gettext};
#[cfg(feature = "db_sqlite")]
impl From<SqliteError> for PixivDownloaderDbError {
fn from(e: SqliteError) -> Self {
@@ -18,3 +23,20 @@ impl From<SqliteError> for PixivDownloaderDbError {
#[cfg(not(feature = "db_sqlite"))]
compile_error!("No database backend is enabled.");
/// Open the database
pub fn open_database() -> Result<Box<dyn PixivDownloaderDb + Send + Sync>, PixivDownloaderDbError> {
let cfg = get_helper().db();
if cfg.is_none() {
return Err(Box::new(String::from(gettext(
"No database configuration provided.",
))));
}
#[cfg(feature = "db_sqlite")]
{
if matches!(cfg, PixivDownloaderDbConfig::Sqlite(_)) {
return Ok(Box::new(PixivDownloaderSqlite::new(&cfg)?));
}
}
Err(Box::new(String::from(gettext("Unknown database type."))))
}

40
src/db/sqlite/db.rs Normal file
View File

@@ -0,0 +1,40 @@
use super::super::{
PixivDownloaderDb, PixivDownloaderDbConfig, PixivDownloaderDbError, PixivDownloaderSqliteConfig,
};
use super::SqliteError;
use rusqlite::{Connection, OpenFlags};
use std::sync::Mutex;
pub struct PixivDownloaderSqlite {
db: Mutex<Connection>,
}
impl PixivDownloaderSqlite {
fn _new(cfg: &PixivDownloaderSqliteConfig) -> Result<Self, SqliteError> {
let con = Connection::open_with_flags(
&cfg.path,
OpenFlags::SQLITE_OPEN_READ_WRITE
| OpenFlags::SQLITE_OPEN_FULL_MUTEX
| OpenFlags::SQLITE_OPEN_CREATE
| OpenFlags::SQLITE_OPEN_URI,
)?;
Ok(Self {
db: Mutex::new(con),
})
}
}
impl PixivDownloaderDb for PixivDownloaderSqlite {
#[allow(unreachable_patterns)]
fn new<R: AsRef<PixivDownloaderDbConfig> + ?Sized>(
cfg: &R,
) -> Result<Self, PixivDownloaderDbError> {
match cfg.as_ref() {
PixivDownloaderDbConfig::Sqlite(cfg) => {
let db = Self::_new(cfg)?;
Ok(db)
}
_ => panic!("Config mismatched."),
}
}
}

View File

@@ -1,2 +1,4 @@
#[derive(derive_more::Display, derive_more::From)]
pub enum SqliteError {}
pub enum SqliteError {
DbError(rusqlite::Error),
}

View File

@@ -1,3 +1,5 @@
pub mod db;
pub mod error;
pub use db::PixivDownloaderSqlite;
pub use error::SqliteError;

View File

@@ -7,5 +7,5 @@ pub trait PixivDownloaderDb {
cfg: &R,
) -> Result<Self, PixivDownloaderDbError>
where
Self: Sized;
Self: Sized + Send + Sync;
}

View File

@@ -1,3 +1,5 @@
#[cfg(feature = "db")]
use crate::db::PixivDownloaderDbConfig;
use crate::ext::json::FromJson;
use crate::ext::replace::ReplaceWith2;
use crate::ext::rw_lock::GetRwLock;
@@ -73,6 +75,16 @@ impl OptHelper {
self._cors_entries.get_ref().clone()
}
#[cfg(feature = "db")]
/// Return the config of the database
pub fn db(&self) -> PixivDownloaderDbConfig {
if self.settings.get_ref().have("db") {
PixivDownloaderDbConfig::new(&self.settings.get_ref().get("db").unwrap()).unwrap()
} else {
PixivDownloaderDbConfig::default()
}
}
/// Whether to download multiple posts/artworks at the same time.
pub fn download_multiple_posts(&self) -> bool {
match self.opt.get_ref().download_multiple_posts {

View File

@@ -1,14 +1,21 @@
use super::cors::CorsContext;
use crate::db::{open_database, PixivDownloaderDb};
use crate::gettext;
use std::default::Default;
pub struct ServerContext {
pub cors: CorsContext,
pub db: Box<dyn PixivDownloaderDb + Send + Sync>,
}
impl Default for ServerContext {
fn default() -> Self {
Self {
cors: CorsContext::default(),
db: match open_database() {
Ok(db) => db,
Err(e) => panic!("{} {}", gettext("Failed to open database:"), e),
},
}
}
}

View File

@@ -1,3 +1,5 @@
#[cfg(feature = "db")]
use crate::db::check_db_config;
use crate::ext::json::FromJson;
use crate::ext::use_or_not::UseOrNot;
use crate::gettext;
@@ -49,6 +51,8 @@ pub fn get_settings_list() -> Vec<SettingDes> {
SettingDes::new("force-yuv420p", gettext("Force yuv420p as output pixel format when converting ugoira(GIF) to video."), JsonValueType::Boolean, None).unwrap(),
#[cfg(feature = "ugoira")]
SettingDes::new("x264-profile", gettext("The x264 profile when converting ugoira(GIF) to video."), JsonValueType::Str, Some(check_x264_profile)).unwrap(),
#[cfg(feature = "db")]
SettingDes::new("db", gettext("Database settings."), JsonValueType::Object, Some(check_db_config)).unwrap(),
]
}