mirror of
https://github.com/lifegpc/pixiv_downloader.git
synced 2026-07-08 01:32:41 +08:00
Update push
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1576,6 +1576,7 @@ dependencies = [
|
||||
"multipart",
|
||||
"openssl",
|
||||
"parse-size",
|
||||
"percent-encoding",
|
||||
"proc_macros",
|
||||
"rand",
|
||||
"regex",
|
||||
|
||||
@@ -39,6 +39,7 @@ modular-bitfield = "0.11"
|
||||
multipart = { features = ["server"], git = 'https://github.com/lifegpc/multipart', optional = true, default-features = false }
|
||||
openssl = { version = "0.10", optional = true }
|
||||
parse-size = "1"
|
||||
percent-encoding = { version = "*", optional = true }
|
||||
proc_macros = { path = "proc_macros" }
|
||||
rand = { version = "0", optional = true }
|
||||
regex = "1"
|
||||
@@ -65,7 +66,7 @@ db_all = ["db", "db_sqlite"]
|
||||
db_sqlite = ["rusqlite"]
|
||||
docker = []
|
||||
exif = ["bindgen", "c_fixed_string", "cmake", "link-cplusplus", "utf16string"]
|
||||
server = ["async-trait", "base64", "db", "hex", "hyper", "multipart", "openssl", "serde_json", "rand", "serde_urlencoded"]
|
||||
server = ["async-trait", "base64", "db", "hex", "hyper", "multipart", "openssl", "serde_json", "rand", "serde_urlencoded", "percent-encoding"]
|
||||
ugoira = ["avdict", "bindgen", "cmake", "link-cplusplus"]
|
||||
|
||||
[patch.crates-io]
|
||||
|
||||
@@ -996,7 +996,7 @@ pub fn pushdeer_api_quick_test(item: TokenStream) -> TokenStream {
|
||||
match std::env::var("PUSHDEER_SERVER") {
|
||||
Ok(server) => match std::env::var("PUSHDEER_TOKEN") {
|
||||
Ok(token) => {
|
||||
let client = PushdeerClient::new(server);
|
||||
let client = PushdeerClient::new(&server);
|
||||
match #expr.await {
|
||||
Ok(_) => {},
|
||||
Err(e) => {
|
||||
|
||||
@@ -93,10 +93,48 @@ pub struct EveryPushConfig {
|
||||
pub add_translated_tag: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PushDeerConfig {
|
||||
/// Push server
|
||||
pub push_server: String,
|
||||
/// Push key
|
||||
pub pushkey: String,
|
||||
/// Push type
|
||||
pub typ: EveryPushTextType,
|
||||
#[serde(default = "defualt_author_locations")]
|
||||
/// Author locations
|
||||
/// Not supported when type is `Image`.
|
||||
pub author_locations: Vec<AuthorLocation>,
|
||||
#[serde(default = "default_true")]
|
||||
/// Whether to filter author name
|
||||
pub filter_author: bool,
|
||||
#[serde(default = "default_true")]
|
||||
/// Whether to add artwork link
|
||||
pub add_link: bool,
|
||||
#[serde(default = "default_true")]
|
||||
/// Whether to add artwork link to title
|
||||
/// Supported when type is `Text`.
|
||||
pub add_link_to_title: bool,
|
||||
#[serde(default = "default_true")]
|
||||
/// Whether to add image link to image
|
||||
pub add_link_to_image: bool,
|
||||
#[serde(default = "default_true")]
|
||||
/// Whether to add tags
|
||||
pub add_tags: bool,
|
||||
#[serde(default = "default_true")]
|
||||
/// Whether to add AI tag
|
||||
pub add_ai_tag: bool,
|
||||
#[serde(default = "default_true")]
|
||||
/// Whether to add translated tag
|
||||
pub add_translated_tag: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
pub enum PushConfig {
|
||||
EveryPush(EveryPushConfig),
|
||||
PushDeer(PushDeerConfig),
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
||||
@@ -9,10 +9,10 @@ pub struct PushdeerClient {
|
||||
}
|
||||
|
||||
impl PushdeerClient {
|
||||
pub fn new(server: String) -> Self {
|
||||
pub fn new<S: AsRef<str> + ?Sized>(server: &S) -> Self {
|
||||
Self {
|
||||
client: WebClient::default(),
|
||||
server,
|
||||
server: server.as_ref().to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ use crate::get_helper;
|
||||
use crate::gettext;
|
||||
use crate::pixiv_app::PixivAppClient;
|
||||
use crate::pixiv_web::PixivWebClient;
|
||||
use crate::utils::get_file_name_from_url;
|
||||
use futures_util::lock::Mutex;
|
||||
use hyper::{http::response::Builder, Body, Request, Response};
|
||||
use json::JsonValue;
|
||||
@@ -63,7 +64,15 @@ impl ServerContext {
|
||||
sha512.update(u.as_str().as_bytes());
|
||||
let sign = hex::encode(sha512.finish());
|
||||
map.insert("sign", &sign);
|
||||
let url = format!("{}/proxy/pixiv?{}", base, serde_urlencoded::to_string(map)?);
|
||||
let name = get_file_name_from_url(u.as_str())
|
||||
.map(|v| format!("/{}", v))
|
||||
.unwrap_or_default();
|
||||
let url = format!(
|
||||
"{}/proxy/pixiv{}?{}",
|
||||
base,
|
||||
name,
|
||||
serde_urlencoded::to_string(map)?
|
||||
);
|
||||
Ok(url)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
use super::super::super::preclude::*;
|
||||
use crate::db::push_task::{AuthorLocation, EveryPushConfig, PushConfig};
|
||||
use crate::db::push_task::{AuthorLocation, EveryPushConfig, PushConfig, PushDeerConfig};
|
||||
use crate::error::PixivDownloaderError;
|
||||
use crate::opt::author_name_filter::AuthorFiler;
|
||||
use crate::parser::description::DescriptionParser;
|
||||
use crate::pixivapp::illust::PixivAppIllust;
|
||||
use crate::push::every_push::{EveryPushClient, EveryPushTextType};
|
||||
use crate::push::pushdeer::PushdeerClient;
|
||||
use crate::{get_helper, gettext};
|
||||
use json::JsonValue;
|
||||
use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
|
||||
|
||||
struct RunContext<'a> {
|
||||
ctx: Arc<ServerContext>,
|
||||
@@ -99,6 +101,7 @@ impl<'a> RunContext<'a> {
|
||||
pub fn filter_author(&self) -> bool {
|
||||
match self.cfg {
|
||||
PushConfig::EveryPush(e) => e.filter_author,
|
||||
PushConfig::PushDeer(e) => e.filter_author,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,9 +347,190 @@ impl<'a> RunContext<'a> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn send_push_deer(&self, cfg: &PushDeerConfig) -> Result<(), PixivDownloaderError> {
|
||||
let client = PushdeerClient::new(&cfg.push_server);
|
||||
match &cfg.typ {
|
||||
EveryPushTextType::Text => {
|
||||
let mut title = self.title().map(|s| {
|
||||
if cfg.add_link_to_title {
|
||||
if let Some(id) = self.id() {
|
||||
format!("[{}](https://www.pixiv.net/artworks/{})", s, id)
|
||||
} else {
|
||||
s.to_owned()
|
||||
}
|
||||
} else {
|
||||
s.to_owned()
|
||||
}
|
||||
});
|
||||
let author = self.author();
|
||||
if cfg.author_locations.contains(&AuthorLocation::Title) {
|
||||
if let Some(t) = &title {
|
||||
if let Some(a) = &author {
|
||||
let au = if let Some(uid) = self.user_id() {
|
||||
format!("[{}](https://www.pixiv.net/users/{})", a, uid)
|
||||
} else {
|
||||
a.to_owned()
|
||||
};
|
||||
title = Some(format!("{} - {}", t, au));
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut text = String::new();
|
||||
if let Some(t) = &title {
|
||||
text.push_str(t);
|
||||
text.push_str("\n\n");
|
||||
}
|
||||
if cfg.author_locations.contains(&AuthorLocation::Top) {
|
||||
if let Some(a) = &author {
|
||||
self.add_author(&mut text, a);
|
||||
}
|
||||
}
|
||||
if cfg.add_link {
|
||||
if let Some(id) = self.id() {
|
||||
let link = format!("https://www.pixiv.net/artworks/{}", id);
|
||||
text.push_str(&format!("[{}]({}) \n", link, link));
|
||||
}
|
||||
}
|
||||
if let Some(desc) = self.desc() {
|
||||
let mut p = DescriptionParser::new(true);
|
||||
p.parse(desc)?;
|
||||
while !text.ends_with("\n\n") {
|
||||
text.push_str("\n");
|
||||
}
|
||||
text.push_str(&p.data);
|
||||
if !p.data.ends_with("\n\n") {
|
||||
text.push_str("\n\n");
|
||||
}
|
||||
}
|
||||
if cfg.add_tags {
|
||||
if cfg.add_ai_tag && self.is_ai() {
|
||||
text.push_str("#");
|
||||
text.push_str(gettext("AI generated"));
|
||||
text.push_str(" ");
|
||||
}
|
||||
if let Some(i) = self.illust {
|
||||
for tag in i.tags() {
|
||||
if let Some(name) = tag.name() {
|
||||
let encoded = percent_encode(name.as_bytes(), NON_ALPHANUMERIC);
|
||||
text.push_str(&format!(
|
||||
"[#{}](https://www.pixiv.net/tags/{}) ",
|
||||
name, &encoded
|
||||
));
|
||||
if cfg.add_translated_tag {
|
||||
if let Some(t) = tag.translated_name() {
|
||||
text.push_str(&format!(
|
||||
"[#{}](https://www.pixiv.net/tags/{}) ",
|
||||
t, &encoded
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
text.push_str(" \n");
|
||||
}
|
||||
if cfg.author_locations.contains(&AuthorLocation::Bottom) {
|
||||
if let Some(a) = &author {
|
||||
self.add_author(&mut text, a);
|
||||
}
|
||||
}
|
||||
client.push_text_message(&cfg.pushkey, &text).await?;
|
||||
}
|
||||
EveryPushTextType::Markdown => {
|
||||
let mut title = self.title().map(|s| s.to_owned());
|
||||
let author = self.author();
|
||||
if cfg.author_locations.contains(&AuthorLocation::Title) {
|
||||
if let Some(t) = &title {
|
||||
if let Some(a) = &author {
|
||||
title = Some(format!("{} - {}", t, a));
|
||||
}
|
||||
}
|
||||
}
|
||||
let title = title.ok_or("title not found.")?;
|
||||
let mut text = String::new();
|
||||
let len = self.len().unwrap_or(1);
|
||||
for i in 0..len {
|
||||
if let Some(url) = self.get_image_url(i).await? {
|
||||
if cfg.add_link_to_image {
|
||||
text.push_str("[");
|
||||
}
|
||||
text.push_str(&format!("", url));
|
||||
if cfg.add_link_to_image {
|
||||
text.push_str(&format!("]({})", url));
|
||||
}
|
||||
}
|
||||
}
|
||||
if cfg.author_locations.contains(&AuthorLocation::Top) {
|
||||
if let Some(a) = &author {
|
||||
self.add_author(&mut text, a);
|
||||
}
|
||||
}
|
||||
if cfg.add_link {
|
||||
if let Some(id) = self.id() {
|
||||
let link = format!("https://www.pixiv.net/artworks/{}", id);
|
||||
text.push_str(&format!("[{}]({}) \n", link, link));
|
||||
}
|
||||
}
|
||||
if let Some(desc) = self.desc() {
|
||||
let mut p = DescriptionParser::new(true);
|
||||
p.parse(desc)?;
|
||||
while !text.ends_with("\n\n") {
|
||||
text.push_str("\n");
|
||||
}
|
||||
text.push_str(&p.data);
|
||||
if !p.data.ends_with("\n\n") {
|
||||
text.push_str("\n\n");
|
||||
}
|
||||
}
|
||||
if cfg.add_tags {
|
||||
if cfg.add_ai_tag && self.is_ai() {
|
||||
text.push_str("#");
|
||||
text.push_str(gettext("AI generated"));
|
||||
text.push_str(" ");
|
||||
}
|
||||
if let Some(i) = self.illust {
|
||||
for tag in i.tags() {
|
||||
if let Some(name) = tag.name() {
|
||||
let encoded = percent_encode(name.as_bytes(), NON_ALPHANUMERIC);
|
||||
text.push_str(&format!(
|
||||
"[#{}](https://www.pixiv.net/tags/{}) ",
|
||||
name, &encoded
|
||||
));
|
||||
if cfg.add_translated_tag {
|
||||
if let Some(t) = tag.translated_name() {
|
||||
text.push_str(&format!(
|
||||
"[#{}](https://www.pixiv.net/tags/{}) ",
|
||||
t, &encoded
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
text.push_str(" \n");
|
||||
}
|
||||
if cfg.author_locations.contains(&AuthorLocation::Bottom) {
|
||||
if let Some(a) = &author {
|
||||
self.add_author(&mut text, a);
|
||||
}
|
||||
}
|
||||
client
|
||||
.push_markdown_message(&cfg.pushkey, &title, &text)
|
||||
.await?;
|
||||
}
|
||||
EveryPushTextType::Image => {
|
||||
let url = self.get_image_url(0).await?.ok_or("image url not found.")?;
|
||||
client.push_image(&cfg.pushkey, &url).await?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn run(&self) -> Result<(), PixivDownloaderError> {
|
||||
match self.cfg {
|
||||
PushConfig::EveryPush(e) => self.send_every_push(e).await,
|
||||
PushConfig::PushDeer(e) => self.send_push_deer(e).await,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user