From f39deb53213653b4239a5c6741cbdf3862ec3c26 Mon Sep 17 00:00:00 2001 From: Zastian Pretorius Date: Sat, 7 Jan 2023 02:56:52 +0000 Subject: [PATCH] she be working again --- src/anime/anime.rs | 34 ++++++--- src/anime/scraper.rs | 174 ++++++++++++++----------------------------- src/main.rs | 6 +- 3 files changed, 79 insertions(+), 135 deletions(-) diff --git a/src/anime/anime.rs b/src/anime/anime.rs index 53908ee..1f34c10 100644 --- a/src/anime/anime.rs +++ b/src/anime/anime.rs @@ -1,8 +1,8 @@ -use crate::{anime_link, anime_names}; use crate::{ get_an_progress, get_anime_id, get_user_anime_progress, update_anime_progress, write_an_progress, }; +use crate::{get_anime_link, get_animes}; use crate::{open_cast, open_video}; use crossterm::{ @@ -83,11 +83,13 @@ impl StatefulList { struct App { /// Current value of the input box input: String, + animes: (Vec, Vec), /// Current input mode input_mode: InputMode, /// History of recorded messages messages: StatefulList, title: String, + link: String, ep: u64, progress: i32, anime_id: i32, @@ -100,9 +102,11 @@ impl<'a> App { fn default() -> App { App { input: String::new(), + animes: (Vec::new(), Vec::new()), input_mode: InputMode::Normal, messages: StatefulList::with_items(Vec::new()), title: String::new(), + link: String::new(), ep: 0, progress: 0, anime_id: 0, @@ -174,7 +178,8 @@ fn run_app(terminal: &mut Terminal, mut app: App) -> io::Result<( app.progress = 0; let selected = app.messages.state.selected(); app.title = app.messages.items[selected.unwrap()].clone(); - let anime_info = get_anime_info(&app.title); + app.link = app.animes.0[selected.unwrap()].clone(); + let anime_info = get_anime_info(&app.animes.0[selected.unwrap()]); app.anime_id = get_anime_id(anime_info.0); app.messages.items.clear(); if app.token == "local" || app.anime_id == 0 { @@ -186,11 +191,14 @@ fn run_app(terminal: &mut Terminal, mut app: App) -> io::Result<( app.messages.state.select(Some(app.progress as usize)); } if anime_info.1 == 1 { - let link = anime_link(&app.title, 1, &app.provider); + let link = get_anime_link(&app.link, 1); if !app.cast.0 { - open_video((link.0, link.1)); + open_video((link, format!("{} Episode 1", &app.title))); } else { - open_cast((link.0, link.1), &app.cast.1) + open_cast( + (link, format!("{} Episode 1", &app.title)), + &app.cast.1, + ) } if app.token == "local" || app.anime_id == 0 { write_an_progress(&app.title, &1); @@ -213,11 +221,14 @@ fn run_app(terminal: &mut Terminal, mut app: App) -> io::Result<( .replace("Episode ", "") .parse::() .unwrap(); - let link = anime_link(&app.title, app.ep, &app.provider); + let link = get_anime_link(&app.link, app.ep); if !app.cast.0 { - open_video((link.0, link.1)); + open_video((link, format!("{} Episode {}", &app.title, app.ep))); } else { - open_cast((link.0, link.1), &app.cast.1) + open_cast( + (link, format!("{} Episode {}", &app.title, app.ep)), + &app.cast.1, + ) } if app.ep > app.progress as u64 { if app.token == "local" || app.anime_id == 0 { @@ -237,13 +248,12 @@ fn run_app(terminal: &mut Terminal, mut app: App) -> io::Result<( }, InputMode::Editing => match key.code { KeyCode::Enter => { - //push app.input into app.messages with '1 - let anime_list = anime_names(app.input.drain(..).collect()); + //push app.input into app.messages with ' + app.animes = get_animes(app.input.drain(..).collect()); app.messages.items.clear(); - for anime in anime_list { + for anime in &app.animes.1 { app.messages.push(anime.to_string()); } - ep_select = false; app.input_mode = InputMode::Normal; } diff --git a/src/anime/scraper.rs b/src/anime/scraper.rs index 240c7c6..f5b4acb 100644 --- a/src/anime/scraper.rs +++ b/src/anime/scraper.rs @@ -1,7 +1,7 @@ -use base64::{decode, encode}; use isahc::config::Configurable; use isahc::{ReadResponseExt, Request, RequestExt}; use regex::Regex; +//use serde_json::json; pub fn get_anime_html(url: &str) -> String { let req = Request::builder() @@ -16,126 +16,64 @@ pub fn get_anime_html(url: &str) -> String { req.send().unwrap().text().unwrap() } -pub fn get_ep_location(url: &str) -> String { - let request = Request::builder() - .method("HEAD") - .uri(url) - .header( - "user-agent", - "Mozilla/5.0 (X11; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/100.0", - ) - .body(()) - .unwrap(); - let response = request.send().unwrap(); - let headers = response.headers(); - let location = headers.get("location").unwrap(); - location.to_str().unwrap().to_string() +pub fn get_post(id: &str) -> String { + let resp = Request::builder() + .method("POST") + .uri("https://yugen.to/api/embed/") + .header("x-requested-with", "XMLHttpRequest") + .body(id) + .unwrap() + .send() + .unwrap() + .text(); + let resp: String = resp.as_ref().unwrap().to_string(); + resp } -pub fn anime_names(query: String) -> Vec { - let url = format!("https://gogoanime.dk//search.html?keyword={}", query); - //relpace all spaces with %20 - let url = url.replace(' ', "%20"); - let html = get_anime_html(&url); - let re = Regex::new(r#"(?m)/category/([^"]*)"#).unwrap(); - let mut anime_list: Vec = Vec::new(); +pub fn get_animes(query: String) -> (Vec, Vec) { + let query = query.replace(" ", "+"); + let html = get_anime_html(&format!("https://yugen.to/search/?q={}", query)); + let re = Regex::new(r#"href="(/anime[^"]*)""#).unwrap(); + let mut animes_links = Vec::new(); for cap in re.captures_iter(&html) { - anime_list.push(cap.get(1).unwrap().as_str().trim().to_string()); + animes_links.push(cap[1].to_string()); } - anime_list.dedup(); - - anime_list -} - -pub fn get_anime_info(title: &str) -> (i32, u16) { - let url = format!("https://animixplay.to/v1/{}", title); - let html = get_anime_html(&url); - let re = Regex::new(r#"(?m)var malid = '([0-9]*)'"#).unwrap(); - let mal_id = re - .captures_iter(&html) - .next() - .unwrap() - .get(1) - .unwrap() - .as_str() - .trim() - .to_string(); - - let re = Regex::new(r#"(?m)"eptotal":([\d]+)"#).unwrap(); - let episodes = re - .captures_iter(&html) - .next() - .unwrap() - .get(1) - .unwrap() - .as_str() - .trim() - .to_string(); - ( - mal_id.parse::().unwrap_or(0), - episodes.parse::().unwrap_or(0), - ) -} - -pub fn anime_link(title: &str, ep: u64, provider: &str) -> (String, String) { - let url = format!("https://animixplay.to/v1/{}", title); - let html = get_anime_html(&url); - let re = Regex::new(r#"(?m)\?id=([^&]+)"#).unwrap(); - let id1 = match re.captures_iter(&html).nth(ep as usize - 1) { - Some(cap) => cap.get(1).unwrap().as_str().trim().to_string(), - None => "".to_string(), - }; - if id1 != "" { - if provider == "vrv" { - let title = format!("{} Episode {}", title.replace('-', " "), ep); - let encoded_id1 = encode(&id1); - let encoded_id2 = encode(&encoded_id1); - let mut last_byte = encoded_id1.as_bytes()[encoded_id1.len() - 2]; - last_byte += 1; - let mut new_encoded_id1 = encoded_id1.as_bytes().to_vec(); - new_encoded_id1.pop(); - new_encoded_id1.pop(); - new_encoded_id1.push(last_byte); - let new_encoded_id1 = String::from_utf8(new_encoded_id1).unwrap(); - let ani_id = format!("cW9{}MVFhzM0dyVTh3ZTlP{}", new_encoded_id1, encoded_id2); - let result = get_ep_location(format!("https://animixplay.to/api/{}", ani_id).as_str()); - //split the result into at # and return the second part - let result: String = std::str::from_utf8( - decode(result.split('#').nth(1).unwrap()) - .unwrap() - .as_slice(), - ) - .unwrap() - .to_string(); - return (result, title); - } else if provider == "gogo" { - let title = format!("{} Episode {}", title.replace('-', " "), ep); - let encoded_id1 = encode(&id1); - let anime_id = encode(format!("{}LTXs3GrU8we9O{}", id1, encoded_id1)); - let html = format!("https://animixplay.to/api/cW9{}", anime_id); - let url = get_ep_location(&html); - let url = url.split('#').nth(1).unwrap(); - let url = std::str::from_utf8(&decode(url).unwrap()) - .unwrap() - .to_string(); - return (url, title); - } else { - panic!("Invalid provider"); - } - } else { - let re = Regex::new(r#"(?m)r\.html#(.*)""#).unwrap(); - let id2 = re - .captures_iter(&html) - .next() - .unwrap() - .get(1) - .unwrap() - .as_str() - .trim() - .to_string(); - let url = decode(id2).unwrap(); - let url = std::str::from_utf8(&url).unwrap().to_string(); - let title = format!("{} Episode {}", title.replace('-', " "), ep); - return (url, title); + let re = Regex::new(r#"/" title="([^"]*)""#).unwrap(); + let mut animes_names = Vec::new(); + for cap in re.captures_iter(&html) { + animes_names.push(cap[1].to_string()); } + (animes_links, animes_names) +} + +pub fn get_anime_info(url: &str) -> (i32, u16) { + let url = format!("https://yugen.to{}watch", url); + let html = get_anime_html(&url); + //print html and exit + let re = Regex::new(r#""mal_id":(\d*)"#).unwrap(); + let mal_id = re.captures(&html).unwrap()[1].parse().unwrap(); + let re = + Regex::new(r#"Episodes(\d*)"#) + .unwrap(); + let episodes = re.captures(&html).unwrap()[1].parse().unwrap(); + (mal_id, episodes) +} + +pub fn get_anime_link(url: &str, episode: u64) -> String { + let url = &format!( + "https://yugen.to/watch{}{}/", + url.replace("/anime", ""), + episode + ); + let html = get_anime_html(url); + let re = Regex::new(r#"iframe id="main-embed" src="https://yugen.to/e/(.*)=="#).unwrap(); + let capture = re.captures(&html).unwrap(); + let id = &capture[1]; + let id = format!("id={}%3D%3D&ac=0", id); + let json = get_post(&id); + let re = Regex::new(r#"hls": \["(.*)","#).unwrap(); + let capture = re.captures(&json).unwrap(); + let link = &capture[1]; + //return the link + link.to_string() } diff --git a/src/main.rs b/src/main.rs index 819acc9..d53215f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,11 +7,7 @@ use colored::Colorize; //use ln::ui::ln_ui; use ln::ln::ln_ui; -use crate::anime::{ - player::{open_cast, open_video}, - scraper::{anime_link, anime_names}, - trackers::*, -}; +use crate::anime::{player::*, scraper::*, trackers::*}; use crate::get_token; use crate::helpers::take_input::{int_input, string_input}; fn main() {