Skip to content

Commit

Permalink
独立setting选项并初步增加qbittorrent插件
Browse files Browse the repository at this point in the history
  • Loading branch information
Chikage0o0 committed Oct 12, 2023
1 parent d7f66a6 commit bf408b3
Show file tree
Hide file tree
Showing 11 changed files with 526 additions and 122 deletions.
262 changes: 258 additions & 4 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ members = [
# plugins
"plugins/yande_popular",
"plugins/webhook",
"plugins/qbittorrent",
]
resolver = "2"

Expand Down
17 changes: 17 additions & 0 deletions plugins/qbittorrent/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "qbittorrent"
version = "0.1.0"
edition = "2021"


[dependencies]
anyhow = "1"
matrix_bot_core = { path = "../../matrix_bot_core" }
log = "0.4.14"
toml = "0.8.2"
serde = { version = "1.0.188", features = ["derive"] }
tokio = { version = "1.33.0", default-features = false, features = [] }
qbit-rs = { version = "0.3.7" }

[dev-dependencies]
env_logger = "0.10.0"
16 changes: 16 additions & 0 deletions plugins/qbittorrent/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use anyhow::Result;
use matrix_bot_core::matrix::client::Client;

mod qbit;
mod setting;

#[allow(unused_variables)]
pub async fn run(client: Client, plugin_folder: impl AsRef<std::path::Path>) -> Result<()> {
log::info!("start yande_popular");

let setting = setting::get_or_init(plugin_folder)?;

if setting.use_internal_qbit {}

Ok(())
}
21 changes: 21 additions & 0 deletions plugins/qbittorrent/src/qbit/binary.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use anyhow::Result;

#[allow(dead_code)]
fn get_download_link() -> Result<String> {
if !(cfg!(target_os = "linux")) {
return Err(anyhow::anyhow!("only support linux"));
}

let mut link =
"https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/".to_string();
if cfg!(target_arch = "x86_64") {
link.push_str("x86_64-qbittorrent-nox");
} else if cfg!(target_arch = "aarch64") {
link.push_str("aarch64-qbittorrent-nox");
} else if cfg!(target_arch = "x86") {
link.push_str("x86-qbittorrent-nox");
} else {
return Err(anyhow::anyhow!("only support x86_64 and aarch64"));
}
Ok(link)
}
1 change: 1 addition & 0 deletions plugins/qbittorrent/src/qbit/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod binary;
56 changes: 56 additions & 0 deletions plugins/qbittorrent/src/setting.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use std::path::{Path, PathBuf};

use anyhow::Result;
use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Serialize)]
pub struct Setting {
pub room_setting: Vec<RoomSetting>,
pub qbit_user: String,
pub qbit_pass: String,
pub qbit_url: String,
pub use_internal_qbit: bool,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct RoomSetting {
pub download_path: PathBuf,
pub file_size_limit: u128,
pub room_id: String,
pub db_path: PathBuf,
}

pub fn get_or_init(path: impl AsRef<Path>) -> Result<Setting> {
let setting_path = path.as_ref().join("qbittorrent.toml");
// load setting, if not exists, create it and exit
let setting = if !setting_path.exists() {
log::info!("create setting file: {}", setting_path.to_string_lossy());
let setting = Setting {
room_setting: vec![RoomSetting {
download_path: path.as_ref().join("qbittorrent").join("download"),
file_size_limit: 0,
room_id: "".to_string(),
db_path: path.as_ref().join("qbittorrent").join("db"),
}],
qbit_user: "admin".to_string(),
qbit_pass: "adminadmin".to_string(),
qbit_url: "http://127.0.0.1:8080".to_string(),
use_internal_qbit: true,
};
let toml = toml::to_string_pretty(&setting).unwrap();
std::fs::write(&setting_path, toml)?;
log::error!(
"please edit setting file: {}",
setting_path.to_string_lossy()
);
return Err(anyhow::anyhow!(
"please edit setting file: {}",
setting_path.to_string_lossy()
));
} else {
log::info!("load setting file: {}", setting_path.to_string_lossy());
let toml = std::fs::read_to_string(&setting_path)?;
toml::from_str(&toml)?
};
Ok(setting)
}
79 changes: 24 additions & 55 deletions plugins/webhook/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,71 +1,37 @@
use std::{collections::HashMap, net::SocketAddr, sync::OnceLock};
use std::{collections::HashMap, net::SocketAddr};

use anyhow::Result;
use axum::{extract::Path, http::StatusCode, routing::post, Json, Router};
use matrix_bot_core::matrix::{
client::Client,
room::{self, Room},
use axum::{
extract::{Path, State},
http::StatusCode,
routing::post,
Json, Router,
};
use serde::{Deserialize, Serialize};
use matrix_bot_core::matrix::{client::Client, room::Room};

#[derive(Debug, Deserialize, Serialize)]
struct Setting {
room_id: Vec<String>,
token: Option<String>,
port: u16,
}

static ROOM: OnceLock<HashMap<String, Room>> = OnceLock::new();
use crate::setting::Setting;
mod setting;

pub async fn run(client: Client, setting_folder: impl AsRef<std::path::Path>) -> Result<()> {
log::info!("start webhook");
let setting_path = setting_folder.as_ref().join("webhook.toml");

// load setting, if not exists, create it and exit
let setting: Setting = if !setting_path.exists() {
log::info!("create setting file: {}", setting_path.to_string_lossy());
let settings = Setting {
room_id: vec!["".to_string()],
token: Some("123456".to_string()),
port: 0,
};
let toml = toml::to_string_pretty(&settings).unwrap();
std::fs::write(&setting_path, toml)?;
log::error!(
"please edit setting file: {}",
setting_path.to_string_lossy()
);
return Err(anyhow::anyhow!(
"please edit setting file: {}",
setting_path.to_string_lossy()
));
} else {
log::info!("load setting file: {}", setting_path.to_string_lossy());
let toml = std::fs::read_to_string(&setting_path)?;
toml::from_str(&toml)?
};

// map to hashmap for easy access
// key: room_id Value: Room
let mut setting_map = HashMap::new();
for room_id in setting.room_id {
let room = room::Room::new(&client, &room_id).await?;
setting_map.insert(room_id, room);
}

ROOM.get_or_init(|| setting_map);
let setting = Setting::get_or_init(setting_folder)?;
let token = setting.token.clone();
let port = setting.port;
let setting = setting.to_hashmap(&client).await?;

let mut app: Router = Router::new()
let mut app = Router::new()
.route("/send/:room_id", post(send))
.fallback(not_found);
.fallback(not_found)
.with_state(setting);

if let Some(token) = &setting.token {
if let Some(token) = &token {
app = app.layer(tower_http::validate_request::ValidateRequestHeaderLayer::bearer(token));
}

log::info!("listen on {}", setting.port);
log::info!("listen on {}", port);

let addr = SocketAddr::from(([0, 0, 0, 0], setting.port));
let addr = SocketAddr::from(([0, 0, 0, 0], port));
let server = axum::Server::bind(&addr).serve(app.into_make_service());

server.await.unwrap();
Expand All @@ -77,8 +43,11 @@ pub async fn run(client: Client, setting_folder: impl AsRef<std::path::Path>) ->
struct Msg {
msg: String,
}
async fn send((Path(room_id), Json(msg)): (Path<String>, Json<Msg>)) -> StatusCode {
let room = ROOM.get().unwrap();
async fn send(
State(room): State<HashMap<String, Room>>,
Path(room_id): Path<String>,
Json(msg): Json<Msg>,
) -> StatusCode {
if let Some(room) = room.get(&room_id) {
log::info!("send msg: {}", msg.msg);
match room.send_msg(&msg.msg, true).await {
Expand Down
52 changes: 52 additions & 0 deletions plugins/webhook/src/setting.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use std::{collections::HashMap, path::Path};

use anyhow::Result;
use matrix_bot_core::matrix::{client::Client, room::Room};
use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Serialize)]
pub struct Setting {
pub room_id: Vec<String>,
pub token: Option<String>,
pub port: u16,
}

impl Setting {
pub async fn to_hashmap(self, client: &Client) -> Result<HashMap<String, Room>> {
let mut hashmap = HashMap::new();
for room_id in self.room_id {
let room = Room::new(&client, &room_id).await?;
hashmap.insert(room_id, room);
}
Ok(hashmap)
}

pub fn get_or_init(path: impl AsRef<Path>) -> Result<Self> {
let setting_path = path.as_ref().join("webhook.toml");

// load setting, if not exists, create it and exit
let setting: Setting = if !setting_path.exists() {
log::info!("create setting file: {}", setting_path.to_string_lossy());
let settings = Setting {
room_id: vec!["".to_string()],
token: Some("123456".to_string()),
port: 0,
};
let toml = toml::to_string_pretty(&settings).unwrap();
std::fs::write(&setting_path, toml)?;
log::error!(
"please edit setting file: {}",
setting_path.to_string_lossy()
);
return Err(anyhow::anyhow!(
"please edit setting file: {}",
setting_path.to_string_lossy()
));
} else {
log::info!("load setting file: {}", setting_path.to_string_lossy());
let toml = std::fs::read_to_string(&setting_path)?;
toml::from_str(&toml)?
};
Ok(setting)
}
}
73 changes: 10 additions & 63 deletions plugins/yande_popular/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,78 +1,25 @@
use std::{
collections::HashMap,
hash::Hash,
path::{self, Path, PathBuf},
};
use std::path::Path;

use anyhow::Result;
use matrix_bot_core::matrix::{client::Client, room};
use serde::{Deserialize, Serialize};
use matrix_bot_core::matrix::client::Client;

use crate::setting::Setting;

mod db;
mod resize;
mod setting;
mod yande;

#[derive(Debug, Deserialize, Serialize)]
struct Settings {
setting: Vec<Setting>,
}

#[derive(Debug, Deserialize, Serialize, Clone, Hash, Eq, PartialEq)]
struct Setting {
tmp_path: PathBuf,
db_path: PathBuf,
room_id: String,
resize: Option<usize>,
yande_url: Vec<String>,
}

pub async fn run(client: Client, setting_folder: impl AsRef<Path>) -> Result<()> {
pub async fn run(client: Client, plugin_folder: impl AsRef<Path>) -> Result<()> {
log::info!("start yande_popular");
let setting_path = setting_folder.as_ref().join("yande_popular.toml");

// load setting, if not exists, create it and exit
let settings: Settings = if !setting_path.exists() {
log::info!("create setting file: {}", setting_path.to_string_lossy());
let settings = Settings {
setting: vec![Setting {
tmp_path: setting_folder.as_ref().join("yande_popular").join("tmp"),
db_path: setting_folder.as_ref().join("yande_popular").join("db"),
room_id: "".to_string(),
resize: Some(1920),
yande_url: vec!["https://yande.re/post/popular_recent".to_string()],
}],
};
let toml = toml::to_string_pretty(&settings).unwrap();
std::fs::write(&setting_path, toml)?;
log::error!(
"please edit setting file: {}",
setting_path.to_string_lossy()
);
return Err(anyhow::anyhow!(
"please edit setting file: {}",
setting_path.to_string_lossy()
));
} else {
log::info!("load setting file: {}", setting_path.to_string_lossy());
let toml = std::fs::read_to_string(&setting_path)?;
toml::from_str(&toml)?
};

// map to hashmap for easy access
// key: Setting Value: (DB, Room)
let mut settings_hash = HashMap::new();
for setting in settings.setting {
let db = db::DB::open(&setting.db_path);
std::fs::create_dir_all(path::Path::new(&setting.tmp_path)).unwrap_or_else(|e| {
log::error!("create tmp dir failed: {}", e);
});
let room = room::Room::new(&client, &setting.room_id).await?;
settings_hash.insert(setting.clone(), (db, room));
}
let setting_hashmap = Setting::get_or_init(plugin_folder)?
.to_hashmap(&client)
.await?;

loop {
log::info!("start scan");
for (setting, (db, room)) in settings_hash.iter() {
for (setting, (db, room)) in setting_hashmap.iter() {
log::info!("scan: {}", setting.room_id);
let mut image_list = Vec::new();

Expand Down
Loading

0 comments on commit bf408b3

Please sign in to comment.