mirror of
https://github.com/lifegpc/pixiv_downloader.git
synced 2026-07-08 01:32:41 +08:00
Update
This commit is contained in:
9
Cargo.lock
generated
9
Cargo.lock
generated
@@ -316,6 +316,12 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb4a24b1aaf0fd0ce8b45161144d6f42cd91677fd5940fd431183eb023b3a2b8"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.3"
|
||||
@@ -359,7 +365,7 @@ version = "0.99.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"convert_case 0.4.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustc_version",
|
||||
@@ -1330,6 +1336,7 @@ dependencies = [
|
||||
name = "proc_macros"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"convert_case 0.5.0",
|
||||
"parse_duration",
|
||||
"quote",
|
||||
"syn",
|
||||
|
||||
@@ -11,6 +11,7 @@ path = "proc_macros.rs"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
convert_case = "0.5"
|
||||
parse_duration = "2"
|
||||
quote = "1"
|
||||
syn = { version = "1", features = ["full"] }
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use convert_case::Case;
|
||||
use convert_case::Casing;
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::bracketed;
|
||||
@@ -511,3 +513,70 @@ pub fn filter_http_methods(item: TokenStream) -> TokenStream {
|
||||
};
|
||||
stream.into()
|
||||
}
|
||||
|
||||
struct CheckJsonKeys {
|
||||
pub keys: Vec<(LitStr, bool)>,
|
||||
}
|
||||
|
||||
impl Parse for CheckJsonKeys {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
let mut keys = Vec::new();
|
||||
let first: LitStr = input.parse()?;
|
||||
match input.parse::<token::Add>() {
|
||||
Ok(_) => {
|
||||
keys.push((first, true));
|
||||
}
|
||||
Err(_) => {
|
||||
keys.push((first, false));
|
||||
}
|
||||
}
|
||||
while !input.is_empty() {
|
||||
let _: token::Comma = input.parse()?;
|
||||
if input.is_empty() {
|
||||
break;
|
||||
}
|
||||
let key: LitStr = input.parse()?;
|
||||
match input.parse::<token::Add>() {
|
||||
Ok(_) => {
|
||||
keys.push((key, true));
|
||||
}
|
||||
Err(_) => {
|
||||
keys.push((key, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Self { keys })
|
||||
}
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn check_json_keys(item: TokenStream) -> TokenStream {
|
||||
let CheckJsonKeys { keys } = parse_macro_input!(item as CheckJsonKeys);
|
||||
let mut streams = Vec::new();
|
||||
for (key, check) in keys {
|
||||
if check {
|
||||
let k = key.value();
|
||||
let k = k.to_case(Case::Snake);
|
||||
let fun = Ident::new(&k, key.span());
|
||||
streams.push(quote!(#key => {
|
||||
self.#fun().try_err(gettext("The value of the key <key> is missing.").replace("<key>", key))?;
|
||||
}));
|
||||
} else {
|
||||
streams.push(quote!(#key => {}));
|
||||
}
|
||||
}
|
||||
let stream = quote!(
|
||||
{
|
||||
use crate::ext::try_err::TryErr;
|
||||
use crate::gettext;
|
||||
self.data.is_object().try_err(gettext("Data is not a object."))?;
|
||||
for (key, _) in self.data.entries() {
|
||||
match key {
|
||||
#(#streams)*
|
||||
_ => { Err(format!("{} {}", gettext("Key <key> is handled:").replace("<key>", key).as_str(), self.data))?; }
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
stream.into()
|
||||
}
|
||||
|
||||
@@ -36,3 +36,13 @@ impl<T, E, E2> TryErr<T, E> for Result<T, E2> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> TryErr<(), E> for bool {
|
||||
fn try_err(self, err: E) -> Result<(), E> {
|
||||
if self {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
122
src/fanbox/article/block.rs
Normal file
122
src/fanbox/article/block.rs
Normal file
@@ -0,0 +1,122 @@
|
||||
use super::super::check::CheckUnkown;
|
||||
use json::JsonValue;
|
||||
use proc_macros::check_json_keys;
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub struct FanboxArticleParagraphBoldStyle {
|
||||
pub data: JsonValue,
|
||||
}
|
||||
|
||||
impl FanboxArticleParagraphBoldStyle {
|
||||
#[inline]
|
||||
pub fn length(&self) -> Option<u64> {
|
||||
self.data["length"].as_u64()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Create a new instance
|
||||
pub fn new(data: &JsonValue) -> Self {
|
||||
Self { data: data.clone() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn offset(&self) -> Option<u64> {
|
||||
self.data["offset"].as_u64()
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckUnkown for FanboxArticleParagraphBoldStyle {
|
||||
fn check_unknown(&self) -> Result<(), crate::fanbox::error::FanboxAPIError> {
|
||||
check_json_keys!("offset"+, "length"+,);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for FanboxArticleParagraphBoldStyle {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("FanboxArticleParagraphBoldStyle")
|
||||
.field("length", &self.length())
|
||||
.field("offset", &self.offset())
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum FanboxArticleParagraphStyle {
|
||||
Bold(FanboxArticleParagraphBoldStyle),
|
||||
Unknown(JsonValue),
|
||||
}
|
||||
|
||||
impl FanboxArticleParagraphStyle {
|
||||
#[inline]
|
||||
/// Create a new instance
|
||||
pub fn new(data: &JsonValue) -> Self {
|
||||
match data["type"].as_str() {
|
||||
Some(t) => match t {
|
||||
"bold" => Self::Bold(FanboxArticleParagraphBoldStyle::new(data)),
|
||||
_ => Self::Unknown(data.clone()),
|
||||
},
|
||||
None => Self::Unknown(data.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FanboxArticleParagraphBlock {
|
||||
pub data: JsonValue,
|
||||
}
|
||||
|
||||
impl FanboxArticleParagraphBlock {
|
||||
#[inline]
|
||||
/// Create a new instance
|
||||
pub fn new(data: &JsonValue) -> Self {
|
||||
Self { data: data.clone() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn styles(&self) -> Option<Vec<FanboxArticleParagraphStyle>> {
|
||||
let styles = &self.data["styles"];
|
||||
if styles.is_array() {
|
||||
let mut list = Vec::new();
|
||||
for i in styles.members() {
|
||||
list.push(FanboxArticleParagraphStyle::new(i))
|
||||
}
|
||||
Some(list)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn text(&self) -> Option<&str> {
|
||||
self.data["text"].as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for FanboxArticleParagraphBlock {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("FanboxArticleParagraphBlock")
|
||||
.field("styles", &self.styles())
|
||||
.field("text", &self.text())
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum FanboxArticleBlock {
|
||||
Paragraph(FanboxArticleParagraphBlock),
|
||||
Unknown(JsonValue),
|
||||
}
|
||||
|
||||
impl FanboxArticleBlock {
|
||||
#[inline]
|
||||
/// Create a new instance
|
||||
pub fn new(data: &JsonValue) -> Self {
|
||||
match data["type"].as_str() {
|
||||
Some(t) => match t {
|
||||
"p" => Self::Paragraph(FanboxArticleParagraphBlock::new(data)),
|
||||
_ => Self::Unknown(data.clone()),
|
||||
},
|
||||
None => Self::Unknown(data.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
45
src/fanbox/article/body.rs
Normal file
45
src/fanbox/article/body.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
use super::block::FanboxArticleBlock;
|
||||
use crate::fanbox_api::FanboxClientInternal;
|
||||
use json::JsonValue;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Article body
|
||||
pub struct FanboxArticleBody {
|
||||
/// Raw data
|
||||
pub data: JsonValue,
|
||||
client: Arc<FanboxClientInternal>,
|
||||
}
|
||||
|
||||
impl FanboxArticleBody {
|
||||
#[inline]
|
||||
pub fn blocks(&self) -> Option<Vec<FanboxArticleBlock>> {
|
||||
let blocks = &self.data["blocks"];
|
||||
if blocks.is_array() {
|
||||
let mut list = Vec::new();
|
||||
for i in blocks.members() {
|
||||
list.push(FanboxArticleBlock::new(i))
|
||||
}
|
||||
Some(list)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Create a new instance
|
||||
pub fn new(data: &JsonValue, client: Arc<FanboxClientInternal>) -> Self {
|
||||
Self {
|
||||
data: data.clone(),
|
||||
client,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for FanboxArticleBody {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("FanboxArticleBody")
|
||||
.field("blocks", &self.blocks())
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
2
src/fanbox/article/mod.rs
Normal file
2
src/fanbox/article/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod block;
|
||||
pub mod body;
|
||||
6
src/fanbox/check.rs
Normal file
6
src/fanbox/check.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
use super::error::FanboxAPIError;
|
||||
|
||||
/// Check if have data that we don't handle
|
||||
pub trait CheckUnkown {
|
||||
fn check_unknown(&self) -> Result<(), FanboxAPIError>;
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
pub mod article;
|
||||
pub mod check;
|
||||
pub mod comment;
|
||||
pub mod comment_list;
|
||||
pub mod creator;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use super::article::body::FanboxArticleBody;
|
||||
use super::comment_list::FanboxCommentList;
|
||||
use crate::fanbox_api::FanboxClientInternal;
|
||||
use crate::parser::json::parse_u64;
|
||||
@@ -16,6 +17,11 @@ pub struct FanboxPostArticle {
|
||||
}
|
||||
|
||||
impl FanboxPostArticle {
|
||||
#[inline]
|
||||
pub fn body(&self) -> FanboxArticleBody {
|
||||
FanboxArticleBody::new(&self.data["body"], Arc::clone(&self.client))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn comment_count(&self) -> Option<u64> {
|
||||
self.data["commentCount"].as_u64()
|
||||
@@ -161,6 +167,7 @@ impl Debug for FanboxPostArticle {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("FanboxPostArticle")
|
||||
.field("id", &self.id())
|
||||
.field("body", &self.body())
|
||||
.field("comment_count", &self.comment_count())
|
||||
.field("comment_list", &self.comment_list())
|
||||
.field("cover_image_url", &self.cover_image_url())
|
||||
|
||||
Reference in New Issue
Block a user