Skip to content

Commit

Permalink
Merge pull request #10 from 0xSSOMPW/streaming-links
Browse files Browse the repository at this point in the history
Hianime streamtape server
  • Loading branch information
falcon71181 authored Sep 16, 2024
2 parents 82ea773 + ae582ab commit 8b52994
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 29 deletions.
36 changes: 27 additions & 9 deletions src/hianime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
env::{self, EnvVar, SecretConfig},
error::AniRustError,
proxy::{load_proxies, Proxy},
servers::{AnimeServer, EpisodeType, MegaCloudServer},
servers::{AnimeServer, EpisodeType, MegaCloudServer, ServerExtractedInfo, StreamTapeServer},
utils::{anirust_error_vec_to_string, get_ajax_curl, get_curl},
};

Expand Down Expand Up @@ -576,19 +576,24 @@ impl HiAnimeRust {
id: &str,
episode_type: EpisodeType,
anime_server: Option<AnimeServer>,
) -> Result<(), AniRustError> {
) -> Result<ServerExtractedInfo, 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;
let mut data_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),
EpisodeType::Dub => {
update_server_id(&mut server_id, &mut data_id, server_list.dub, anime_server)
}
_ => update_server_id(&mut server_id, &mut data_id, server_list.sub, anime_server),
}

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

match get_ajax_curl(&url, "link").await {
Ok(curl_string) => {
Expand All @@ -605,9 +610,16 @@ impl HiAnimeRust {
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(())
let server_info = match server_id {
3 => StreamTapeServer::extract(&link, &self.proxies).await?,
4 => MegaCloudServer::extract(&link, &self.proxies).await?,
5 => MegaCloudServer::extract(&link, &self.proxies).await?,
1 => MegaCloudServer::extract(&link, &self.proxies).await?,
_ => MegaCloudServer::extract(&link, &self.proxies).await?,
};

Ok(server_info)
}
}

Expand Down Expand Up @@ -1393,14 +1405,20 @@ fn initialize_secret(secret: Option<SecretConfig>) -> Option<SecretConfig> {
secret_clone
}

fn update_server_id(server_id: &mut u32, servers: Vec<Server>, anime_server: Option<AnimeServer>) {
fn update_server_id(
server_id: &mut u32,
data_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;
*data_id = server.data_id;
return;
}
}
}
}
93 changes: 73 additions & 20 deletions src/servers.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use regex::Regex;
use scraper::Html;
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::{
error::AniRustError,
proxy::Proxy,
utils::{decrypt_aes_256_cbc, get_curl},
utils::{anirust_error_vec_to_string, decrypt_aes_256_cbc, get_curl},
};
use std::time::{SystemTime, UNIX_EPOCH};

Expand All @@ -30,27 +31,23 @@ impl Default for IntroOutro {
}

#[derive(Debug, Serialize, Deserialize)]
pub struct UnencryptedSrc {
pub struct MegaCloudUnencryptedSrc {
pub file: String,
pub src_type: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ExtractedSrc {
pub sources: Vec<UnencryptedSrc>,
pub tracks: Vec<Track>,
pub encrypted: bool,
pub struct MegaCloudExtractedData {
pub intro: IntroOutro,
pub outro: IntroOutro,
pub server: u32,
pub tracks: Vec<Track>,
pub sources: Vec<Source>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ExtractedData {
pub intro: IntroOutro,
pub outro: IntroOutro,
pub tracks: Vec<Track>,
pub sources: Vec<Source>,
pub struct StreamTapeExtractedData {
pub url: String,
pub is_m3u8: bool,
}

#[derive(Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -127,15 +124,22 @@ impl EpisodeType {
}
}

#[derive(Debug, Serialize, Deserialize)]
pub enum ServerExtractedInfo {
MegaCloud(MegaCloudExtractedData),
StreamTape(StreamTapeExtractedData),
}

pub struct MegaCloudServer;

impl MegaCloudServer {
pub async fn extract(
video_url: &str,
proxies: &[Proxy],
) -> Result<ExtractedData, AniRustError> {
) -> Result<ServerExtractedInfo, AniRustError> {
let video_id = extract_video_id(video_url);
let json_data = fetch_initial_data(&video_id, proxies).await?;
let url = format!("{}{}", MEGACLOUD.sources, video_id);
let json_data = fetch_initial_data(&url, proxies).await?;

let is_encrypted = json_data["encrypted"].as_bool().unwrap_or(false);
let intro: IntroOutro = parse_json_field(&json_data, "intro").unwrap_or_default();
Expand All @@ -150,12 +154,62 @@ impl MegaCloudServer {
parse_json_field(&json_data, "sources")?
};

Ok(ExtractedData {
Ok(ServerExtractedInfo::MegaCloud(MegaCloudExtractedData {
intro,
outro,
tracks,
sources,
})
}))
}
}

pub struct StreamTapeServer;

impl StreamTapeServer {
pub async fn extract(
video_url: &str,
proxies: &[Proxy],
) -> Result<ServerExtractedInfo, AniRustError> {
let mut error_vec = vec![];
let mut curl = String::new();

match get_curl(video_url, proxies).await {
Ok(curl_string) => {
curl = curl_string;
}
Err(e) => {
error_vec.push(Some(e));
}
}

if curl.is_empty() {
let error_string = anirust_error_vec_to_string(error_vec);
return Err(AniRustError::UnknownError(error_string));
}

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

let re = Regex::new(r"robotlink'\).innerHTML = (.*)'").unwrap();
let html = document.root_element().html();

if let Some(captures) = re.captures(&html) {
if let Some(matched) = captures.get(1) {
let parts: Vec<&str> = matched.as_str().split("+ ('").collect();
if parts.len() == 2 {
let fh = parts[0].replace('\'', "");
let mut sh = parts[1].to_string();
sh = sh[3..].to_string();

let url = format!("https:{}{}", fh, sh);
return Ok(ServerExtractedInfo::StreamTape(StreamTapeExtractedData {
url: url.clone(),
is_m3u8: url.contains(".m3u8"),
}));
}
}
}

Err(AniRustError::FailedToFetchAfterRetries)
}
}

Expand Down Expand Up @@ -270,9 +324,8 @@ fn extract_video_id(video_url: &str) -> String {
.to_string()
}

async fn fetch_initial_data(video_id: &str, proxies: &[Proxy]) -> Result<Value, AniRustError> {
let url = format!("{}{}", MEGACLOUD.sources, video_id);
let response = get_curl(&url, proxies).await?;
async fn fetch_initial_data(url: &str, proxies: &[Proxy]) -> Result<Value, AniRustError> {
let response = get_curl(url, proxies).await?;
serde_json::from_str(&response).map_err(|e| AniRustError::UnknownError(e.to_string()))
}

Expand Down Expand Up @@ -322,4 +375,4 @@ async fn decrypt_sources(
fn parse_sources(decrypted: &str) -> Result<Vec<Source>, AniRustError> {
serde_json::from_str(decrypted)
.map_err(|e| AniRustError::UnknownError(format!("Failed to parse sources: {}", e)))
}
}

0 comments on commit 8b52994

Please sign in to comment.