1use std::fmt::Display;
2use tokio::task::spawn_blocking;
3use tracing::{event, Level};
4
5use crate::{
6 category::Category, client::Client, error::Result, extractor::extract,
7 model::Torrent, query::Query,
8};
9
10#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
11pub enum SukebeiCategory {
12 All,
13 Art,
14 ArtAnime,
15 ArtDoujinshi,
16 ArtGames,
17 ArtManga,
18 ArtPictures,
19 RealLife,
20 RealLifePhotobooks,
21 RealLifeVideos,
22}
23
24impl Display for SukebeiCategory {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 match self {
27 Self::All => write!(f, "0_0"),
28 Self::Art => write!(f, "1_0"),
29 Self::ArtAnime => write!(f, "1_1"),
30 Self::ArtDoujinshi => write!(f, "1_2"),
31 Self::ArtGames => write!(f, "1_3"),
32 Self::ArtManga => write!(f, "1_4"),
33 Self::ArtPictures => write!(f, "1_5"),
34 Self::RealLife => write!(f, "2_0"),
35 Self::RealLifePhotobooks => write!(f, "2_1"),
36 Self::RealLifeVideos => write!(f, "2_2"),
37 }
38 }
39}
40
41impl Default for SukebeiCategory {
42 fn default() -> Self {
43 Self::All
44 }
45}
46
47impl Category for SukebeiCategory {}
48
49pub type SukebeiQuery = Query<SukebeiCategory>;
50
51#[derive(Debug, Default)]
52pub struct SukebeiClient {
53 inner: reqwest::Client,
54}
55
56impl SukebeiClient {
57 pub fn new() -> Self {
58 Self::default()
59 }
60}
61
62impl Client<SukebeiCategory> for SukebeiClient {
63 const BASE_URL: &'static str = "https://sukebei.nyaa.si";
64
65 #[tracing::instrument(skip(self))]
66 async fn get(
67 &self,
68 query: &Query<SukebeiCategory>,
69 ) -> Result<Vec<Torrent>> {
70 let url = format!("{}/?{}", Self::BASE_URL, query);
71
72 event!(Level::DEBUG, "url = {}", url);
73
74 let res = self.inner.get(url).send().await?.text().await?;
75
76 spawn_blocking(move || extract(&res, Self::BASE_URL)).await?
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83 use crate::query::QueryBuilder;
84 use crate::query::Sort;
85
86 #[tokio::test]
87 async fn test_get() {
88 let client = SukebeiClient::new();
89 let query = QueryBuilder::new()
90 .search("dl")
91 .sort(Sort::Downloads)
92 .build();
93 let res = client.get(&query).await.unwrap();
94
95 println!("{:#?}", res.get(0).unwrap());
96 }
97}