Skip to main content

shinden_pl_api/
search.rs

1use crate::{client::ShindenAPI, models::Anime};
2use anyhow::Result;
3use scraper::{Html, Selector};
4
5impl ShindenAPI {
6    pub async fn search_anime(&self, name: &str) -> Result<Vec<Anime>> {
7        let search_url = format!(
8            "https://shinden.pl/series?search={}",
9            name.replace(' ', "+")
10        );
11        let html = self.get_html(&search_url).await?;
12
13        let doc = Html::parse_document(&html);
14        let div_row = Selector::parse(".div-row").unwrap();
15        let h3 = Selector::parse("h3").unwrap();
16        let a = Selector::parse("a").unwrap();
17        let cover = Selector::parse(".cover-col a").unwrap();
18        let kind = Selector::parse(".title-kind-col").unwrap();
19        let episodes = Selector::parse(".episodes-col").unwrap();
20        let rating = Selector::parse(".rate-top").unwrap();
21
22        let mut result = Vec::new();
23
24        for div in doc.select(&div_row) {
25            let name_elem = div.select(&h3).next().and_then(|h| h.select(&a).next());
26            let name = name_elem
27                .map(|el| el.text().collect::<String>())
28                .unwrap_or_default();
29            let url = name_elem
30                .and_then(|el| el.value().attr("href"))
31                .unwrap_or("")
32                .to_string();
33            let img_href = div
34                .select(&cover)
35                .next()
36                .and_then(|el| el.value().attr("href"))
37                .unwrap_or("/res/other/placeholders/title/100x100.jpg");
38
39            let full_url = format!("https://shinden.pl{}", url);
40            let img_url = format!("https://shinden.pl{}", img_href);
41            let anime_type = div
42                .select(&kind)
43                .next()
44                .map(|k| k.text().collect::<String>())
45                .unwrap_or_default();
46            let ep_count = div
47                .select(&episodes)
48                .next()
49                .map(|e| e.text().collect::<String>())
50                .unwrap_or_default()
51                .trim()
52                .to_string();
53            let rate = div
54                .select(&rating)
55                .next()
56                .map(|r| r.text().collect::<String>())
57                .unwrap_or_default();
58
59            if !name.is_empty() {
60                result.push(Anime {
61                    name,
62                    url: full_url,
63                    image_url: img_url,
64                    anime_type,
65                    rating: rate,
66                    episodes: ep_count,
67                    description: String::new(),
68                });
69            }
70        }
71
72        Ok(result)
73    }
74}
75
76