unsafe which in context is safe implementation of update m3u8
This commit is contained in:
		
							
								
								
									
										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(); | ||||||
|         let file_name = Rc::new(cache.join(file_name)); |             if counter > MAX_TRIES { | ||||||
|         let iptv_url = Rc::new(iptv_url); |                 return; | ||||||
|         let watched_name = Rc::new(cache.join(watched_name)); |             } else if content.is_some() { | ||||||
|  |                 break content.unwrap(); | ||||||
|         Self { |  | ||||||
|             watched_name: watched_name.clone(), |  | ||||||
|             m3u8_items: Self::get_parsed_content(&iptv_url, &file_name, &watched_name), |  | ||||||
|         } |  | ||||||
|             } |             } | ||||||
|  |             println!("Retrying {}/{}", counter, MAX_TRIES); | ||||||
|  |         }; | ||||||
|  |  | ||||||
|     pub fn find(&self, name: &str) -> Vec<&M3u8> { |         let _ = fs::write(&*self.file_name, &content); | ||||||
|         let name = name.to_uppercase(); |         self.m3u8_items = Self::parse_m3u8(content, &self.watched_name.clone()); | ||||||
|         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 |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user