1+ use crate :: data:: increment_requests;
12use reqwest:: { header, Client } ;
23use serde_json:: Value ;
3- use crate :: data:: increment_requests;
4- use crate :: pair:: Pair ;
54
65// https://github.com/ShaheenJawadi/tiktok-video-downloader
7- pub async fn parse_tiktok_video ( url : & str , id : u64 ) -> Result < Pair < String , String > , String > {
6+ pub async fn parse_tiktok_content ( url : & str , id : u64 ) -> Result < Box < dyn Media > , String > {
87 let client = Client :: new ( ) ;
98 println ! ( "🔍 Fetching video metadata..." ) ;
109
@@ -19,42 +18,116 @@ pub async fn parse_tiktok_video(url: &str, id: u64) -> Result<Pair<String, Strin
1918 . await
2019 . map_err ( |_| "Failed to parse JSON response" . to_string ( ) ) ?;
2120
22- let video_url = json[ "data" ] [ "play" ]
23- . as_str ( )
24- . ok_or ( "❌ Video URL not found in API response" . to_string ( ) ) ?;
21+ let images_url: Vec < String > = json[ "data" ] [ "images" ]
22+ . as_array ( )
23+ . map ( |arr| {
24+ arr. iter ( )
25+ . filter_map ( |v| v. as_str ( ) . map ( |s| s. to_string ( ) ) )
26+ . collect :: < Vec < String > > ( )
27+ } )
28+ . unwrap_or_default ( ) ;
2529
2630 let video_title = json[ "data" ] [ "title" ]
2731 . as_str ( )
2832 . unwrap_or ( "tiktok_video" ) ;
2933
30- println ! ( "🔍 Fetching has been finished!" ) ;
34+ let audio_url = json[ "data" ] [ "music" ]
35+ . as_str ( )
36+ . unwrap_or ( "https://moosic.my.mail.ru/file/7aa9b68114dfa1a4581ce525a1e793b1.mp3" ) ;
3137
3238 // adding +1 to requests_amount on users.json
3339 increment_requests ( id) . await . unwrap ( ) ;
3440
35- Ok ( Pair :: new ( video_url. to_string ( ) , video_title. to_string ( ) ) )
41+ if !images_url. is_empty ( ) {
42+
43+ println ! ( "🔍 Fetching has been finished!" ) ;
44+ return Ok ( Box :: new (
45+ PhotoContent {
46+ title : video_title. to_string ( ) ,
47+ photo_urls : images_url,
48+ audio_url : audio_url. to_string ( ) ,
49+ }
50+ ) )
51+ }
52+
53+ let video_url = json[ "data" ] [ "play" ]
54+ . as_str ( )
55+ . ok_or ( "Video URL not found in API response" . to_string ( ) ) ?;
56+
57+ println ! ( "🔍 Fetching has been finished!" ) ;
58+
59+ Ok (
60+ Box :: from ( VideoContent {
61+ title : video_title. to_string ( ) ,
62+ video_url : video_url. to_string ( ) ,
63+ audio_url : audio_url. to_string ( ) ,
64+ } )
65+ )
3666}
3767
38- pub async fn parse_tiktok_audio ( url : & str ) -> Result < String , String > {
39- let client = Client :: new ( ) ;
40- println ! ( "🔍 Fetching audio metadata..." ) ;
68+ pub enum ContentType {
69+ Photo ,
70+ Video
71+ }
4172
42- let api_url = format ! ( "https://www.tikwm.com/api/?url={}" , url) ;
43- let response = client. get ( & api_url)
44- . header ( header:: USER_AGENT , "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" )
45- . send ( )
46- . await
47- . map_err ( |_| "Failed to send request" . to_string ( ) ) ?;
73+ impl PartialEq for ContentType {
74+ fn eq ( & self , other : & Self ) -> bool {
75+ match ( self , other) {
76+ ( ContentType :: Photo , ContentType :: Photo ) => true ,
77+ ( ContentType :: Video , ContentType :: Video ) => true ,
78+ _ => false ,
79+ }
80+ }
81+ }
4882
49- let json: Value = response. json ( )
50- . await
51- . map_err ( |_| "Failed to parse JSON response" . to_string ( ) ) ?;
83+ pub trait Media : Send + Sync {
84+ fn get_title ( & self ) -> String ;
85+ fn get_content_type ( & self ) -> ContentType ;
86+ fn get_content_urls ( & self ) -> Vec < String > ;
87+ fn get_audio_url ( & self ) -> String ;
88+ }
5289
53- let audio_url = json[ "data" ] [ "music" ]
54- . as_str ( )
55- . unwrap_or ( "https://moosic.my.mail.ru/file/7aa9b68114dfa1a4581ce525a1e793b1.mp3" ) ;
90+ struct VideoContent {
91+ title : String ,
92+ video_url : String ,
93+ audio_url : String ,
94+ }
5695
57- println ! ( "🔍 Fetching has been finished!" ) ;
96+ struct PhotoContent {
97+ title : String ,
98+ photo_urls : Vec < String > ,
99+ audio_url : String ,
100+ }
101+
102+ impl Media for VideoContent {
103+ fn get_title ( & self ) -> String {
104+ self . title . clone ( )
105+ }
106+ fn get_content_type ( & self ) -> ContentType {
107+ ContentType :: Video
108+ }
109+ fn get_content_urls ( & self ) -> Vec < String > {
110+ vec ! [ self . video_url. clone( ) ]
111+ }
112+
113+ fn get_audio_url ( & self ) -> String {
114+ self . audio_url . clone ( )
115+ }
116+ }
117+
118+ impl Media for PhotoContent {
119+ fn get_title ( & self ) -> String {
120+ self . title . clone ( )
121+ }
122+
123+ fn get_content_type ( & self ) -> ContentType {
124+ ContentType :: Photo
125+ }
126+ fn get_content_urls ( & self ) -> Vec < String > {
127+ self . photo_urls . iter ( ) . map ( |p| p. clone ( ) ) . collect ( )
128+ }
58129
59- Ok ( audio_url. to_string ( ) )
130+ fn get_audio_url ( & self ) -> String {
131+ self . audio_url . clone ( )
132+ }
60133}
0 commit comments