mirror of
https://github.com/euzu/tuliprox.git
synced 2026-10-26 00:32:30 +01:00
removed raw epg access when no url given.
This commit is contained in:
+6
-57
@@ -2,9 +2,8 @@ use std::fs::File;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use actix_web::{HttpRequest, HttpResponse, web, http::header};
|
||||
use log::{debug, info};
|
||||
use log::{info};
|
||||
use quick_xml::{Reader, Writer};
|
||||
use url::{ParseError};
|
||||
use flate2::write::GzEncoder;
|
||||
use flate2::Compression;
|
||||
use quick_xml::events::{BytesStart, Event};
|
||||
@@ -13,13 +12,13 @@ use chrono::{Duration, NaiveDateTime, TimeDelta};
|
||||
|
||||
use crate::api::api_model::{AppState, UserApiRequest};
|
||||
use crate::api::api_utils::{get_user_target, serve_file};
|
||||
use crate::model::api_proxy::{ProxyType, ProxyUserCredentials};
|
||||
use crate::model::config::{Config, ConfigInput, ConfigTarget};
|
||||
use crate::model::api_proxy::{ProxyUserCredentials};
|
||||
use crate::model::config::{Config, ConfigTarget};
|
||||
use crate::model::config::TargetType;
|
||||
use crate::repository::m3u_repository::m3u_get_epg_file_path;
|
||||
use crate::repository::storage::get_target_storage_path;
|
||||
use crate::repository::xtream_repository::{xtream_get_epg_file_path, xtream_get_storage_path};
|
||||
use crate::utils::{file_utils, request_utils};
|
||||
use crate::utils::{file_utils};
|
||||
|
||||
fn time_correct(date_time: &str, correction: &TimeDelta) -> String {
|
||||
// Split the dateTime string into date and time parts
|
||||
@@ -194,11 +193,8 @@ async fn xmltv_api(
|
||||
if let Some((user, target)) = get_user_target(&api_req, &app_state) {
|
||||
match get_epg_path_for_target(&app_state.config, target) {
|
||||
None => {
|
||||
// No epg configured, we try to figure out an epg url and redirect.
|
||||
// No processing or timeshift
|
||||
if let Some(value) = get_xmltv_raw_epg(&app_state.config, &user, &target.name).await {
|
||||
return value;
|
||||
}
|
||||
// No epg configured, No processing or timeshift, epg can't be mapped to the channels.
|
||||
// we do not deliver epg
|
||||
}
|
||||
Some(epg_path) => return serve_epg(&epg_path, &req, &user).await
|
||||
}
|
||||
@@ -207,53 +203,6 @@ async fn xmltv_api(
|
||||
r#"<?xml version="1.0" encoding="utf-8" ?><!DOCTYPE tv SYSTEM "xmltv.dtd"><tv generator-info-name="Xtream Codes" generator-info-url=""></tv>"#)
|
||||
}
|
||||
|
||||
fn get_xmltv_epg_url(input: &ConfigInput) -> Result<String, ParseError> {
|
||||
let epg_url = input.epg_url.as_ref().map_or(String::new(), std::borrow::ToOwned::to_owned);
|
||||
if epg_url.is_empty() {
|
||||
if let Some(user_info) = input.get_user_info() {
|
||||
let url = user_info.base_url.as_str();
|
||||
let username = user_info.username.as_str();
|
||||
let password = user_info.password.as_str();
|
||||
Ok(format!("{url}/xmltv.php?username={username}&password={password}"))
|
||||
} else {
|
||||
Err(ParseError::EmptyHost)
|
||||
}
|
||||
} else {
|
||||
Ok(epg_url)
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_xmltv_raw_epg(config: &Config, user: &ProxyUserCredentials, target_name: &str) -> Option<HttpResponse> {
|
||||
// If no epg_url is provided for input, we did not process the xmltv for our channels.
|
||||
// We are now delivering the original untouched xmltv.
|
||||
// If you want to use xmltv then provide the url in the config to filter unnecessary content.
|
||||
// If you have multiple xtream sources, no response because of mapped ids
|
||||
// if you want epg for multi xtream input, then provide epg_url.
|
||||
if let Some(inputs) = config.get_inputs_for_target(target_name) {
|
||||
if inputs.len() == 1 {
|
||||
if let Some(&input) = inputs.first() {
|
||||
if let Ok(url) = get_xmltv_epg_url(input) {
|
||||
if user.proxy == ProxyType::Redirect {
|
||||
debug!("Redirecting epg request to {}", url.as_str());
|
||||
return Some(HttpResponse::Found().insert_header(("Location", url.as_str())).finish());
|
||||
}
|
||||
match request_utils::download_text_content(input, url.as_str(), None).await {
|
||||
Ok(content) => return Some(HttpResponse::Ok().content_type(mime::TEXT_XML).body(content)),
|
||||
Err(err) => {
|
||||
debug!("Could not generate epg url for {target_name} {err}");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debug!("Could not generate epg url for {target_name}");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debug!("No epg_url is provided for target {target_name}, multi input requires epg_url");
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub(crate) fn xmltv_api_register(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(web::resource("/xmltv.php").route(web::get().to(xmltv_api)))
|
||||
.service(web::resource("/epg").route(web::get().to(xmltv_api)));
|
||||
|
||||
+19
-19
@@ -437,17 +437,17 @@ impl ConfigSource {
|
||||
Ok(index + (self.inputs.len() as u16))
|
||||
}
|
||||
|
||||
pub(crate) fn get_inputs_for_target(&self, target_name: &str) -> Option<Vec<&ConfigInput>> {
|
||||
for target in &self.targets {
|
||||
if target.name.eq(target_name) {
|
||||
let inputs = self.inputs.iter().filter(|&i| i.enabled).collect::<Vec<&ConfigInput>>();
|
||||
if !inputs.is_empty() {
|
||||
return Some(inputs);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
// pub(crate) fn get_inputs_for_target(&self, target_name: &str) -> Option<Vec<&ConfigInput>> {
|
||||
// for target in &self.targets {
|
||||
// if target.name.eq(target_name) {
|
||||
// let inputs = self.inputs.iter().filter(|&i| i.enabled).collect::<Vec<&ConfigInput>>();
|
||||
// if !inputs.is_empty() {
|
||||
// return Some(inputs);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// None
|
||||
// }
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
@@ -840,14 +840,14 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_inputs_for_target(&self, target_name: &str) -> Option<Vec<&ConfigInput>> {
|
||||
for source in &self.sources {
|
||||
if let Some(cfg) = source.get_inputs_for_target(target_name) {
|
||||
return Some(cfg);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
// pub(crate) fn get_inputs_for_target(&self, target_name: &str) -> Option<Vec<&ConfigInput>> {
|
||||
// for source in &self.sources {
|
||||
// if let Some(cfg) = source.get_inputs_for_target(target_name) {
|
||||
// return Some(cfg);
|
||||
// }
|
||||
// }
|
||||
// None
|
||||
// }
|
||||
|
||||
pub fn get_target_for_user(&self, username: &str, password: &str) -> Option<(ProxyUserCredentials, &ConfigTarget)> {
|
||||
match self.t_api_proxy.read().unwrap().as_ref() {
|
||||
|
||||
@@ -14,6 +14,9 @@ use crate::m3u_filter_error::{M3uFilterError, M3uFilterErrorKind};
|
||||
use crate::model::config::ConfigInput;
|
||||
use crate::utils::file_utils::{get_file_path, persist_file};
|
||||
|
||||
const ENCODING_GZIP: &str = "gzip";
|
||||
const ENCODING_DEFLATE: &str = "deflate";
|
||||
|
||||
fn is_gzip(bytes: &[u8]) -> bool {
|
||||
// Gzip files start with the bytes 0x1F 0x8B
|
||||
bytes.len() >= 2 && bytes[0] == 0x1F && bytes[1] == 0x8B
|
||||
@@ -144,19 +147,19 @@ async fn get_remote_content(input: &ConfigInput, url: &Url) -> Result<String, Er
|
||||
match response.bytes().await {
|
||||
Ok(bytes) => {
|
||||
if bytes.len() >= 2 && is_gzip(&bytes[0..2]) {
|
||||
encoding = Some("gzip".to_string());
|
||||
encoding = Some(ENCODING_GZIP.to_string());
|
||||
}
|
||||
let mut decode_buffer = String::new();
|
||||
if let Some(encoding_type) = encoding {
|
||||
match encoding_type.as_str() {
|
||||
"gzip" => {
|
||||
ENCODING_GZIP => {
|
||||
let mut decoder = GzDecoder::new(&bytes[..]);
|
||||
match decoder.read_to_string(&mut decode_buffer) {
|
||||
Ok(_) => {}
|
||||
Err(err) => return Err(std::io::Error::new(ErrorKind::Other, format!("failed to decode gzip content {err}")))
|
||||
};
|
||||
}
|
||||
"deflate" => {
|
||||
ENCODING_DEFLATE => {
|
||||
let mut decoder = ZlibDecoder::new(&bytes[..]);
|
||||
match decoder.read_to_string(&mut decode_buffer) {
|
||||
Ok(_) => {}
|
||||
|
||||
Reference in New Issue
Block a user