1- use std:: sync:: LazyLock ;
1+ use std:: {
2+ io:: { self , Cursor } ,
3+ sync:: LazyLock ,
4+ } ;
5+
6+ use anyhow:: { Context , Error , Result , anyhow} ;
7+ use base64:: { engine:: general_purpose, read} ;
8+ use tokio:: fs;
29
310#[ macro_export]
411macro_rules! spawn_local {
@@ -12,3 +19,42 @@ pub static IS_DESKTOP_KDE: LazyLock<bool> = LazyLock::new(|| {
1219 . ok ( )
1320 . is_some_and ( |value| value == "KDE" )
1421} ) ;
22+
23+ pub fn decode_base64 ( data : & str ) -> Result < Vec < u8 > > {
24+ let mut input = Cursor :: new ( data) ;
25+ let mut output = Vec :: new ( ) ;
26+
27+ let engine = general_purpose:: STANDARD ;
28+ let mut decoder = read:: DecoderReader :: new ( & mut input, & engine) ;
29+
30+ if let Err ( e) = io:: copy ( & mut decoder, & mut output) {
31+ return Err ( Error :: msg ( format ! ( "Failed to decode base64: {e}" ) ) ) ;
32+ }
33+
34+ Ok ( output)
35+ }
36+
37+ pub async fn download_file ( file_name : & str , data : String ) -> Result < String > {
38+ let base_64 = data
39+ . strip_prefix ( "application/octet-stream;charset=utf-8;base64," )
40+ . ok_or_else ( || anyhow ! ( "Failed to parse data URL" ) ) ?;
41+ let bytes = decode_base64 ( base_64) ?;
42+
43+ let out_dir = dirs:: download_dir ( )
44+ . ok_or_else ( || anyhow ! ( "Failed to get download dir" ) ) ?
45+ . join ( "Stremio" ) ;
46+
47+ fs:: create_dir_all ( & out_dir)
48+ . await
49+ . context ( "Failed to create download dir" ) ?;
50+
51+ let file_name = out_dir. join ( file_name) ;
52+ fs:: write ( & file_name, bytes)
53+ . await
54+ . context ( "Failed to write file to download dir" ) ?;
55+
56+ file_name
57+ . into_os_string ( )
58+ . into_string ( )
59+ . map_err ( |os_str| anyhow ! ( "Failed to convert path to string: {:?}" , os_str) )
60+ }
0 commit comments