unsafe which in context is safe implementation of update m3u8
This commit is contained in:
parent
e34243d7d8
commit
e12e26221f
14
src/main.rs
14
src/main.rs
@ -39,7 +39,7 @@ fn main() {
|
|||||||
for (idx, m3u8_item) in search_result.as_ref().unwrap().iter().enumerate().rev() {
|
for (idx, m3u8_item) in search_result.as_ref().unwrap().iter().enumerate().rev() {
|
||||||
println!(" {}: {}", idx + 1, m3u8_item);
|
println!(" {}: {}", idx + 1, m3u8_item);
|
||||||
}
|
}
|
||||||
print!("Which one do you wish to stream? [q | s]: ");
|
print!("Which one do you wish to stream? [q | s | r]: ");
|
||||||
stdout.flush().unwrap();
|
stdout.flush().unwrap();
|
||||||
buf = String::new();
|
buf = String::new();
|
||||||
stdin.read_line(&mut buf).unwrap();
|
stdin.read_line(&mut buf).unwrap();
|
||||||
@ -51,6 +51,18 @@ fn main() {
|
|||||||
} else if user_wish == "s" {
|
} else if user_wish == "s" {
|
||||||
search_result = None;
|
search_result = None;
|
||||||
continue;
|
continue;
|
||||||
|
} else if user_wish == "r" {
|
||||||
|
println!("Refreshing local m3u8-file");
|
||||||
|
search_result = None;
|
||||||
|
|
||||||
|
// I know that this is also frowned upon, but it is perfectly safe right here,
|
||||||
|
// even though the borrowchecker complains
|
||||||
|
{
|
||||||
|
let ptr = &parser as *const Parser as *mut Parser;
|
||||||
|
let p = unsafe { &mut *ptr };
|
||||||
|
p.forcefully_update();
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let choosen = user_wish.parse::<usize>();
|
let choosen = user_wish.parse::<usize>();
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use std::ops::Deref;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::{fs, process};
|
use std::{fs, process};
|
||||||
@ -12,9 +11,36 @@ const MAX_TRIES: usize = 4;
|
|||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
watched_name: Rc<PathBuf>,
|
watched_name: Rc<PathBuf>,
|
||||||
m3u8_items: Vec<M3u8>,
|
m3u8_items: Vec<M3u8>,
|
||||||
|
ilovetv_url: Rc<String>,
|
||||||
|
file_name: Rc<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parser {
|
impl Parser {
|
||||||
|
pub fn new(file_name: String, iptv_url: String, watched_name: String) -> Self {
|
||||||
|
let project_dirs = ProjectDirs::from("com", "billenius", "iptvnator_rs").unwrap();
|
||||||
|
let cache = project_dirs.cache_dir();
|
||||||
|
let _ = fs::create_dir_all(&cache);
|
||||||
|
|
||||||
|
let file_name = Rc::new(cache.join(file_name));
|
||||||
|
let ilovetv_url = Rc::new(iptv_url);
|
||||||
|
let watched_name = Rc::new(cache.join(watched_name));
|
||||||
|
|
||||||
|
Self {
|
||||||
|
watched_name: watched_name.clone(),
|
||||||
|
m3u8_items: Self::get_parsed_content(&ilovetv_url, &file_name, &watched_name),
|
||||||
|
ilovetv_url,
|
||||||
|
file_name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find(&self, name: &str) -> Vec<&M3u8> {
|
||||||
|
let name = name.to_uppercase();
|
||||||
|
self.m3u8_items
|
||||||
|
.iter()
|
||||||
|
.filter(|item| item.name.to_uppercase().contains(&name) || item.tvg_id.contains(&name))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
fn should_update(file_name: &PathBuf) -> bool {
|
fn should_update(file_name: &PathBuf) -> bool {
|
||||||
fs::metadata(&file_name)
|
fs::metadata(&file_name)
|
||||||
.and_then(|metadata| {
|
.and_then(|metadata| {
|
||||||
@ -36,34 +62,24 @@ impl Parser {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(file_name: String, iptv_url: String, watched_name: String) -> Self {
|
pub fn forcefully_update(&mut self) {
|
||||||
let project_dirs = ProjectDirs::from("com", "billenius", "iptvnator_rs").unwrap();
|
let mut counter = 0;
|
||||||
let cache = project_dirs.cache_dir();
|
let content = loop {
|
||||||
let _ = fs::create_dir_all(&cache);
|
counter += 1;
|
||||||
|
let content = Self::download(&self.ilovetv_url).ok();
|
||||||
|
if counter > MAX_TRIES {
|
||||||
|
return;
|
||||||
|
} else if content.is_some() {
|
||||||
|
break content.unwrap();
|
||||||
|
}
|
||||||
|
println!("Retrying {}/{}", counter, MAX_TRIES);
|
||||||
|
};
|
||||||
|
|
||||||
let file_name = Rc::new(cache.join(file_name));
|
let _ = fs::write(&*self.file_name, &content);
|
||||||
let iptv_url = Rc::new(iptv_url);
|
self.m3u8_items = Self::parse_m3u8(content, &self.watched_name.clone());
|
||||||
let watched_name = Rc::new(cache.join(watched_name));
|
|
||||||
|
|
||||||
Self {
|
|
||||||
watched_name: watched_name.clone(),
|
|
||||||
m3u8_items: Self::get_parsed_content(&iptv_url, &file_name, &watched_name),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find(&self, name: &str) -> Vec<&M3u8> {
|
|
||||||
let name = name.to_uppercase();
|
|
||||||
self.m3u8_items
|
|
||||||
.iter()
|
|
||||||
.filter(|item| item.name.to_uppercase().contains(&name) || item.tvg_id.contains(&name))
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_watched(&self) {
|
pub fn save_watched(&self) {
|
||||||
let project_dirs = ProjectDirs::from("com", "billenius", "iptvnator_rs").unwrap();
|
|
||||||
let cache_dir = project_dirs.cache_dir();
|
|
||||||
let watched_cache_file = cache_dir.join(&*self.watched_name);
|
|
||||||
|
|
||||||
let watched_items = self
|
let watched_items = self
|
||||||
.m3u8_items
|
.m3u8_items
|
||||||
.iter()
|
.iter()
|
||||||
@ -71,9 +87,9 @@ impl Parser {
|
|||||||
.map(|item| item.link.clone())
|
.map(|item| item.link.clone())
|
||||||
.collect::<Vec<String>>();
|
.collect::<Vec<String>>();
|
||||||
|
|
||||||
let _ = fs::create_dir_all(cache_dir);
|
let _ = fs::create_dir_all(&*self.watched_name.parent().unwrap());
|
||||||
|
|
||||||
match fs::write(watched_cache_file, watched_items.join("\n")) {
|
match fs::write(&*self.watched_name, watched_items.join("\n")) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
println!("Saved watched")
|
println!("Saved watched")
|
||||||
}
|
}
|
||||||
@ -84,6 +100,10 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_parsed_content(link: &String, file_name: &PathBuf, watched_name: &PathBuf) -> Vec<M3u8> {
|
fn get_parsed_content(link: &String, file_name: &PathBuf, watched_name: &PathBuf) -> Vec<M3u8> {
|
||||||
|
Self::parse_m3u8(Self::get_stringcontent(link, file_name, 0), watched_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_m3u8(content: String, watched_name: &PathBuf) -> Vec<M3u8> {
|
||||||
let saved_watches = fs::read_to_string(&watched_name);
|
let saved_watches = fs::read_to_string(&watched_name);
|
||||||
let saved_watches = if saved_watches.is_ok() {
|
let saved_watches = if saved_watches.is_ok() {
|
||||||
saved_watches.unwrap()
|
saved_watches.unwrap()
|
||||||
@ -94,7 +114,7 @@ impl Parser {
|
|||||||
let watched: Vec<String> = saved_watches.lines().map(String::from).collect();
|
let watched: Vec<String> = saved_watches.lines().map(String::from).collect();
|
||||||
|
|
||||||
let mut m3u8_items: Vec<M3u8> = Vec::new();
|
let mut m3u8_items: Vec<M3u8> = Vec::new();
|
||||||
let interesting_lines: Vec<String> = Self::get_stringcontent(link, file_name, 0)
|
let interesting_lines: Vec<String> = content
|
||||||
.replacen("#EXTM3U\n", "", 1)
|
.replacen("#EXTM3U\n", "", 1)
|
||||||
.lines()
|
.lines()
|
||||||
.map(str::trim)
|
.map(str::trim)
|
||||||
@ -160,11 +180,3 @@ impl Parser {
|
|||||||
.and_then(|resp| Ok(resp.text().expect("Could not get m3u8 from server")))
|
.and_then(|resp| Ok(resp.text().expect("Could not get m3u8 from server")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for Parser {
|
|
||||||
type Target = Vec<M3u8>;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.m3u8_items
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user