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