use async_trait::async_trait;
use reqwest::Client;
use serde::{Deserialize, Serialize};
use crate::{Magnet, MagneteaseError, MagneteaseResult, Provider, WhichProvider};
const API_URL: &str = "https://api.knaben.org/v1";
pub struct Knaben;
#[async_trait]
impl Provider for Knaben {
fn name(&self) -> &'static str {
"Knaben"
}
fn display_url(&self) -> &'static str {
"knaben.org"
}
async fn search(
&self,
client: &Client,
query: &str,
) -> Result<MagneteaseResult, MagneteaseError> {
let json_data = serde_json::json!({
"search_type": "100%",
"search_field": "title",
"query": query,
"order_by": "seeders",
"order_direction": "desc",
"size": 150
})
.to_string();
let res = client
.post(API_URL)
.body(json_data)
.header(reqwest::header::CONTENT_TYPE, "application/json")
.send()
.await
.map_err(|e| MagneteaseError {
kind: e.into(),
provider: WhichProvider::Knaben,
})?
.json::<KnabenAPIResult>()
.await
.map_err(|e| MagneteaseError {
kind: e.into(),
provider: WhichProvider::Knaben,
})?;
let magnets = res
.hits
.into_iter()
.filter_map(|x| Magnet::try_from(x).ok())
.collect();
Ok(MagneteaseResult {
provider: WhichProvider::Knaben,
magnets,
})
}
}
impl TryFrom<KnabenMagnet> for Magnet {
type Error = ();
fn try_from(value: KnabenMagnet) -> Result<Self, Self::Error> {
match value {
KnabenMagnet {
title,
magnet_url: Some(url),
seeders,
bytes,
} => Ok(Self {
title,
url,
seeders,
bytes,
}),
_ => Err(()),
}
}
}
#[derive(Debug, Serialize, Deserialize)]
struct KnabenAPIResult {
hits: Vec<KnabenMagnet>,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct KnabenMagnet {
magnet_url: Option<String>,
title: String,
seeders: u32,
bytes: u64,
}