From 918ce0ecb462e21aa99f00bd01f413b13af0100e Mon Sep 17 00:00:00 2001 From: lifegpc Date: Sun, 23 Oct 2022 13:49:11 +0000 Subject: [PATCH] Update database --- Cargo.toml | 2 +- doc/db/files.md | 1 - doc/db/pixiv_artworks.md | 2 + src/db/mod.rs | 2 + src/db/pixiv_artworks.rs | 30 +++++++++++ src/db/sqlite/db.rs | 111 +++++++++++++++++++++++++++++++++++++-- src/db/traits.rs | 28 ++++++++++ 7 files changed, 169 insertions(+), 7 deletions(-) create mode 100644 src/db/pixiv_artworks.rs diff --git a/Cargo.toml b/Cargo.toml index d267a03..22d4695 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,7 @@ cmake = { version = "0.1", optional = true } [features] all = ["db", "db_sqlite", "exif", "ugoira", "server"] avdict = ["bindgen", "cmake", "flagset"] -db = ["anyhow", "async-trait", "bytes"] +db = ["anyhow", "async-trait", "bytes", "flagset"] db_all = ["db", "db_sqlite"] db_sqlite = ["rusqlite"] exif = ["bindgen", "c_fixed_string", "cmake", "link-cplusplus", "utf16string"] diff --git a/doc/db/files.md b/doc/db/files.md index 9c0eb22..98eb7ee 100644 --- a/doc/db/files.md +++ b/doc/db/files.md @@ -3,5 +3,4 @@ | id | File id | integer | | path | The path of the file | string | | last_modified | The last time the file was modified(HTTP Header) | timestamp | -| etag | The etag(HTTP Header) of the file | string | | url | The source url | string | diff --git a/doc/db/pixiv_artworks.md b/doc/db/pixiv_artworks.md index decc43b..22ed5f7 100644 --- a/doc/db/pixiv_artworks.md +++ b/doc/db/pixiv_artworks.md @@ -6,3 +6,5 @@ | uid | User id of the author | integer | | description | Description of artwork | string | | count | Number of pages | integer | +| is_nsfw | Whether the artwork is NSFW | boolean | +| lock | Specify which part should not be updated. | integer | diff --git a/src/db/mod.rs b/src/db/mod.rs index 32fedf7..8b7ddc0 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -1,4 +1,5 @@ pub mod config; +pub mod pixiv_artworks; #[cfg(feature = "db_sqlite")] pub mod sqlite; #[cfg(feature = "server")] @@ -11,6 +12,7 @@ pub use config::check_db_config; pub use config::PixivDownloaderDbConfig; #[cfg(feature = "db_sqlite")] pub use config::PixivDownloaderSqliteConfig; +pub use pixiv_artworks::{PixivArtwork, PixivArtworkLock}; #[cfg(feature = "db_sqlite")] pub use sqlite::{PixivDownloaderSqlite, SqliteError}; #[cfg(feature = "server")] diff --git a/src/db/pixiv_artworks.rs b/src/db/pixiv_artworks.rs new file mode 100644 index 0000000..854fee4 --- /dev/null +++ b/src/db/pixiv_artworks.rs @@ -0,0 +1,30 @@ +use flagset::FlagSet; + +flagset::flags! { + /// Speicfy which part should not be updated. + pub enum PixivArtworkLock: u8 { + Title = 1, + Author = 2, + Description = 4, + IsNsfw = 8, + } +} + +pub struct PixivArtwork { + /// The artwork ID + pub id: u64, + /// The artwork title + pub title: String, + /// The artwork author + pub author: String, + /// The author's UID + pub uid: u64, + /// The artwork description + pub description: String, + /// The artwork's page count + pub count: u64, + /// Whether the artwork is NSFW + pub is_nsfw: bool, + /// Specify which part should not be updated. + pub lock: FlagSet, +} diff --git a/src/db/sqlite/db.rs b/src/db/sqlite/db.rs index 18f0ab8..77d13d2 100644 --- a/src/db/sqlite/db.rs +++ b/src/db/sqlite/db.rs @@ -1,11 +1,12 @@ +#[cfg(feature = "server")] +use super::super::{PixivArtwork, PixivArtworkLock, Token, User}; use super::super::{ PixivDownloaderDb, PixivDownloaderDbConfig, PixivDownloaderDbError, PixivDownloaderSqliteConfig, }; -#[cfg(feature = "server")] -use super::super::{Token, User}; use super::SqliteError; use bytes::BytesMut; use chrono::{DateTime, Utc}; +use flagset::FlagSet; use futures_util::lock::Mutex; use rusqlite::{Connection, OpenFlags, OptionalExtension, Transaction}; use std::collections::HashMap; @@ -24,7 +25,6 @@ const FILES_TABLE: &'static str = "CREATE TABLE files ( id INTEGER PRIMARY KEY AUTOINCREMENT, path TEXT, last_modified DATETIME, -etag TEXT, url TEXT );"; const PIXIV_ARTWORK_TAGS_TABLE: &'static str = "CREATE TABLE pixiv_artwork_tags ( @@ -37,7 +37,9 @@ title TEXT, author TEXT, uid INT, description TEXT, -count INT +count INT, +is_nsfw BOOLEAN, +lock INT );"; const PIXIV_FILES_TABLE: &'static str = "CREATE TABLE pixiv_files ( id INT, @@ -75,13 +77,40 @@ v3 INT, v4 INT, PRIMARY KEY (id) );"; -const VERSION: [u8; 4] = [1, 0, 0, 4]; +const VERSION: [u8; 4] = [1, 0, 0, 5]; pub struct PixivDownloaderSqlite { db: Mutex, } impl PixivDownloaderSqlite { + fn _add_pixiv_artwork( + ts: &Transaction, + id: u64, + title: &str, + author: &str, + uid: u64, + description: &str, + count: u64, + is_nsfw: bool, + lock: &FlagSet, + ) -> Result<(), SqliteError> { + ts.execute( + "INSERT INTO pixiv_artworks (id, title, author, uid, description, count, is_nsfw, lock) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", + ( + id, + title, + author, + uid, + description, + count, + is_nsfw, + lock.bits(), + ), + )?; + Ok(()) + } + #[cfg(feature = "server")] async fn _add_root_user( &self, @@ -172,6 +201,12 @@ impl PixivDownloaderSqlite { tx.execute(TOKEN_TABLE, [])?; tx.execute(USERS_TABLE, [])?; } + if db_version < [1, 0, 0, 5] { + tx.execute("DROP TABLE files;", [])?; + tx.execute(FILES_TABLE, [])?; + tx.execute("ALTER TABLE pixiv_artworks ADD is_nsfw BOOLEAN;", [])?; + tx.execute("ALTER TABLE pixiv_artworks ADD lock INT;", [])?; + } self._write_version(&tx)?; tx.commit()?; } @@ -258,6 +293,35 @@ impl PixivDownloaderSqlite { Ok(tables) } + async fn get_pixiv_artwork(&self, id: u64) -> Result, SqliteError> { + let con = self.db.lock().await; + Ok(con + .query_row("SELECT * FROM pixiv_artworks WHERE id = ?;", [id], |row| { + let lock: u8 = row.get(7)?; + Ok(PixivArtwork { + id: row.get(0)?, + title: row.get(1)?, + author: row.get(2)?, + uid: row.get(3)?, + description: row.get(4)?, + count: row.get(5)?, + is_nsfw: row.get(6)?, + lock: match FlagSet::::new(lock) { + Ok(f) => f, + Err(_) => { + return Err(rusqlite::Error::FromSqlConversionFailure( + 7, + rusqlite::types::Type::Integer, + "Failed to parse lock bit.".into(), + ) + .into()) + } + }, + }) + }) + .optional()?) + } + #[cfg(feature = "server")] async fn get_token(&self, id: u64) -> Result, SqliteError> { let con = self.db.lock().await; @@ -555,6 +619,36 @@ impl PixivDownloaderDb for PixivDownloaderSqlite { } } + async fn add_pixiv_artwork( + &self, + id: u64, + title: &str, + author: &str, + uid: u64, + description: &str, + count: u64, + is_nsfw: bool, + lock: &FlagSet, + ) -> Result { + { + let mut con = self.db.lock().await; + let mut ts = con.transaction()?; + Self::_add_pixiv_artwork( + &mut ts, + id, + title, + author, + uid, + description, + count, + is_nsfw, + lock, + )?; + ts.commit()?; + } + Ok(self.get_pixiv_artwork(id).await?.expect("User not found:")) + } + #[cfg(feature = "server")] async fn add_root_user( &self, @@ -644,6 +738,13 @@ impl PixivDownloaderDb for PixivDownloaderSqlite { Ok(()) } + async fn get_pixiv_artwork( + &self, + id: u64, + ) -> Result, PixivDownloaderDbError> { + Ok(self.get_pixiv_artwork(id).await?) + } + #[cfg(feature = "server")] async fn get_token(&self, id: u64) -> Result, PixivDownloaderDbError> { Ok(self.get_token(id).await?) diff --git a/src/db/traits.rs b/src/db/traits.rs index 30d62e7..a5fd789 100644 --- a/src/db/traits.rs +++ b/src/db/traits.rs @@ -1,8 +1,10 @@ use super::PixivDownloaderDbConfig; use super::PixivDownloaderDbError; +use super::{PixivArtwork, PixivArtworkLock}; #[cfg(feature = "server")] use super::{Token, User}; use chrono::{DateTime, Utc}; +use flagset::FlagSet; #[async_trait] pub trait PixivDownloaderDb { @@ -13,6 +15,26 @@ pub trait PixivDownloaderDb { ) -> Result where Self: Sized + Send + Sync; + /// Add/Update an artwork to the database + /// * `id` - The artwork ID + /// * `title` - The artwork title + /// * `author` - The artwork author + /// * `uid` - The author's ID + /// * `description` - The artwork description + /// * `count` - The artwork's page count + /// * `is_nsfw` - Whether the artwork is NSFW + /// * `lock` - Specify which part should not be updated. + async fn add_pixiv_artwork( + &self, + id: u64, + title: &str, + author: &str, + uid: u64, + description: &str, + count: u64, + is_nsfw: bool, + lock: &FlagSet, + ) -> Result; #[cfg(feature = "server")] /// Add root user to database. /// * `name` - User name @@ -73,6 +95,12 @@ pub trait PixivDownloaderDb { id: u64, expired_at: &DateTime, ) -> Result<(), PixivDownloaderDbError>; + /// Get an artwork from database + /// * `id` - The artwork ID + async fn get_pixiv_artwork( + &self, + id: u64, + ) -> Result, PixivDownloaderDbError>; #[cfg(feature = "server")] /// Get token by ID /// * `id` - The token ID