Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hianime Streaming links : MegaCloud #9

Merged
merged 9 commits into from
Sep 15, 2024
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,19 @@ name = "aniscraper" # The name of the target.
path = "src/lib.rs" # The source file of the target.

[dependencies]
base64 = "0.22.1"
brotli = "6.0.0"
chrono = "0.4.38"
dotenvy = "0.15.7"
flate2 = "1.0.33"
hex = "0.4.3"
http-body-util = "0.1.2"
hyper = "1.4.1"
hyper-tls = "0.6.0"
hyper-util = { version = "0.1.8", features = ["full"] }
lazy_static = "1.5.0"
md5 = "0.7.0"
openssl = "0.10.66"
rand = "0.8.5"
regex = "1.10.6"
reqwest = { version = "0.12.7", features = ["json", "blocking"] }
Expand Down
1 change: 1 addition & 0 deletions src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ impl SecretConfig {
match error {
AniRustError::ReqwestError(_) => self.reqwest_error_webhook.clone(),
AniRustError::HyperError(_) => self.reqwest_error_webhook.clone(),
AniRustError::RegexError(_) => self.utils_error_webhook.clone(),
AniRustError::NoProxiesAvailable => self.no_proxies_available_error_webhook.clone(),
AniRustError::FailedToFetchAfterRetries => {
self.failed_to_fetch_after_retries_error_webhook.clone()
Expand Down
19 changes: 17 additions & 2 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use crate::env::EnvVar;
pub enum AniRustError {
/// Reqwest error
ReqwestError(reqwest::Error),
/// Hyper error
HyperError(hyper::Error),
/// Regex error
RegexError(regex::Error),
/// No Proxies available error
NoProxiesAvailable,
/// Failed to fetch even after multiple tries error
Expand All @@ -29,7 +32,8 @@ impl fmt::Display for AniRustError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AniRustError::ReqwestError(err) => write!(f, "Reqwest error: {}", err),
AniRustError::HyperError(err) => write!(f, "Reqwest error: {}", err),
AniRustError::HyperError(err) => write!(f, "Hyper error: {}", err),
AniRustError::RegexError(err) => write!(f, "Regex error: {}", err),
AniRustError::NoProxiesAvailable => write!(f, "No proxies available"),
AniRustError::FailedToFetchAfterRetries => write!(f, "Failed to fetch after retries"),
AniRustError::ParseIntError(err) => write!(f, "Failed to parse int error: {}", err),
Expand All @@ -46,12 +50,20 @@ impl From<reqwest::Error> for AniRustError {
}
}

// Implement From trait to convert hyper::Error to AniRustError
impl From<hyper::Error> for AniRustError {
fn from(err: hyper::Error) -> Self {
AniRustError::HyperError(err)
}
}

// Implement From trait to convert regex::Error to AniRustError
impl From<regex::Error> for AniRustError {
fn from(err: regex::Error) -> Self {
AniRustError::RegexError(err)
}
}

// Implement `From<Box<dyn StdError>>` for `CustomError`
impl From<Box<dyn StdError>> for AniRustError {
fn from(err: Box<dyn StdError>) -> Self {
Expand All @@ -65,6 +77,7 @@ impl StdError for AniRustError {
match self {
AniRustError::ReqwestError(err) => Some(err),
AniRustError::HyperError(err) => Some(err),
AniRustError::RegexError(err) => Some(err),
AniRustError::NoProxiesAvailable => None,
AniRustError::FailedToFetchAfterRetries => None,
AniRustError::ParseIntError(err) => Some(err),
Expand All @@ -85,7 +98,9 @@ impl AniRustError {
AniRustError::FailedToFetchAfterRetries => {
EnvVar::FAILED_TO_FETCH_AFTER_RETRIES_ERROR_WEBHOOK.get_config()
}
AniRustError::ParseIntError(_) => EnvVar::UTILS_ERROR_WEBHOOK.get_config(),
AniRustError::ParseIntError(_) | AniRustError::RegexError(_) => {
EnvVar::UTILS_ERROR_WEBHOOK.get_config()
}
AniRustError::NoDomainExists(_) => String::new(),
AniRustError::UnknownError(_) => EnvVar::UNKNOWN_ERROR_WEBHOOK.get_config(),
}
Expand Down
71 changes: 66 additions & 5 deletions src/hianime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::{
env::{self, EnvVar, SecretConfig},
error::AniRustError,
proxy::{load_proxies, Proxy},
servers::{AnimeServer, EpisodeType, MegaCloudServer},
utils::{anirust_error_vec_to_string, get_ajax_curl, get_curl},
};

Expand Down Expand Up @@ -223,6 +224,7 @@ pub struct AboutAnime {
pub struct Server {
pub server_name: String,
pub server_id: u32,
pub data_id: u32,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
Expand Down Expand Up @@ -487,7 +489,6 @@ impl HiAnimeRust {
})
}

// BUG: Not working, find another way to do it
pub async fn scrape_episodes(&self, id: &str) -> Result<EpisodesInfo, AniRustError> {
let mut error_vec = vec![];
let mut curl = String::new();
Expand All @@ -496,7 +497,7 @@ impl HiAnimeRust {
for domain in &self.domains {
let url = format!("{}/ajax/v2/episode/list/{}", domain, anime_id);

match get_ajax_curl(&url).await {
match get_ajax_curl(&url, "html").await {
Ok(curl_string) => {
curl = curl_string;
break;
Expand Down Expand Up @@ -534,7 +535,7 @@ impl HiAnimeRust {
domain, episode_id
);

match get_ajax_curl(&url).await {
match get_ajax_curl(&url, "html").await {
Ok(curl_string) => {
curl = curl_string;
break;
Expand All @@ -552,11 +553,14 @@ impl HiAnimeRust {

let document = Html::parse_document(&curl);

let episode_no = document
let episode_str = document
.select(&EPISODE_NO_SELECTOR)
.next()
.and_then(|e| e.text().collect::<String>().parse::<u32>().ok())
.map(|e| e.text().collect::<String>().trim().to_string())
.unwrap_or_default();
let last_part = episode_str.split_whitespace().last().unwrap_or_default();

let episode_no = last_part.parse::<u32>().unwrap_or_default();
let sub = extract_episode_servers(&document, &EPISODE_DUB_SELECTOR);
let dub = extract_episode_servers(&document, &EPISODE_SUB_SELECTOR);

Expand All @@ -566,6 +570,45 @@ impl HiAnimeRust {
dub,
})
}

pub async fn scrape_episode_server_source(
&self,
id: &str,
episode_type: EpisodeType,
anime_server: Option<AnimeServer>,
) -> Result<(), AniRustError> {
let server_list = self.scrape_servers(id).await?;
let mut error_vec = vec![];
let mut link = String::new();
let mut server_id: u32 = 0;

match episode_type {
EpisodeType::Dub => update_server_id(&mut server_id, server_list.dub, anime_server),
_ => update_server_id(&mut server_id, server_list.sub, anime_server),
}

for domain in &self.domains {
let url = format!("{}/ajax/v2/episode/sources?id={}", domain, server_id);

match get_ajax_curl(&url, "link").await {
Ok(curl_string) => {
link = curl_string;
break;
}
Err(e) => {
error_vec.push(Some(e));
}
}
}

if link.is_empty() {
let error_string: String = anirust_error_vec_to_string(error_vec);
return Err(AniRustError::UnknownError(error_string));
}
println!("{:?}", MegaCloudServer::extract(&link, &self.proxies).await);

Ok(())
}
}

fn extract_anime_data(document: &Html, selector: &Selector) -> Vec<Anime> {
Expand Down Expand Up @@ -1297,6 +1340,11 @@ fn extract_episode_servers(document: &Html, selector: &Selector) -> Vec<Server>
})
.unwrap_or_default();

let data_id = element
.attr("data-id")
.and_then(|id| id.trim().parse::<u32>().ok())
.unwrap_or_default();

let server_id = element
.attr("data-server-id")
.and_then(|id| id.trim().parse::<u32>().ok())
Expand All @@ -1305,6 +1353,7 @@ fn extract_episode_servers(document: &Html, selector: &Selector) -> Vec<Server>
Server {
server_name,
server_id,
data_id,
}
})
.collect()
Expand Down Expand Up @@ -1343,3 +1392,15 @@ fn initialize_secret(secret: Option<SecretConfig>) -> Option<SecretConfig> {
drop(secret_lock);
secret_clone
}

fn update_server_id(server_id: &mut u32, servers: Vec<Server>, anime_server: Option<AnimeServer>) {
let anime_server = anime_server.unwrap_or(AnimeServer::Vidstreaming);

for server in servers {
println!("{} - {}", server.server_name, anime_server.as_str());
if server.server_name == anime_server.as_str() {
*server_id = server.server_id;
return;
}
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pub mod env;
pub mod error;
mod proxy;
pub mod servers;
mod utils;

pub mod hianime;
Loading