44using System . IO ;
55using System . Linq ;
66using System . Text . Json ;
7+ using System . Text . RegularExpressions ;
78using System . Threading ;
89using System . Threading . Tasks ;
910using Flurl . Http ;
@@ -28,7 +29,6 @@ public class UserDataViewModel : ObservableObject
2829
2930 private const string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 OPR/82.0.4227.43" ;
3031
31-
3232 public UserDataViewModel ( IAppConfiguration appConfiguration , IDownloadsManager downloadsManager )
3333 {
3434 _flurlClient = new FlurlClient ( )
@@ -44,7 +44,6 @@ public UserDataViewModel(IAppConfiguration appConfiguration, IDownloadsManager d
4444
4545 private UserData _userData ;
4646 public ObservableCollection < PostedVideo > FavoriteVideos { get ; } = new ObservableCollection < PostedVideo > ( ) ;
47-
4847 public ObservableCollection < string > Urls { get ; } = new ObservableCollection < string > ( ) ;
4948
5049 public IAsyncRelayCommand ImportUserDataFileCommand { get ; }
@@ -72,6 +71,12 @@ public int HistoryCount
7271 set { SetProperty ( ref historyCount , value ) ; }
7372 }
7473
74+ private int downloadedCount ;
75+ public int DownloadedCount
76+ {
77+ get { return downloadedCount ; }
78+ set { SetProperty ( ref downloadedCount , value ) ; }
79+ }
7580
7681 private string userName ;
7782 public string UserName
@@ -91,6 +96,7 @@ private async Task ImportUserDataFile()
9196
9297 Urls . Clear ( ) ;
9398 FavoriteVideos . Clear ( ) ;
99+ DownloadedCount = 0 ;
94100
95101 using FileStream openStream = File . OpenRead ( file . Path ) ;
96102 _userData = await JsonSerializer . DeserializeAsync < UserData > ( openStream ) ;
@@ -101,18 +107,56 @@ private async Task ImportUserDataFile()
101107 UserName = $ "@{ _userData . Profile . ProfileInformation . ProfileMap . UserName } ";
102108
103109 await GetUrlsAfterRedirects ( _userData . Activity . FavoriteVideos . FavoriteVideoList . Select ( x => x . Link ) . ToList ( ) , _cts . Token ) ;
104- await FindFavoriteVideos ( Urls . ToList ( ) , _cts . Token ) ;
110+ var urls = ExcludeAlreadyDownloadedVideos ( Urls ) ;
111+ await FindFavoriteVideos ( urls , _cts . Token ) ;
112+ }
113+ }
114+
115+ private List < string > ExcludeAlreadyDownloadedVideos ( IEnumerable < string > urls )
116+ {
117+ var folderPath = Path . Combine ( _appConfiguration . DownloadsFolder , UserName , DownloadType . Bookmarks . ToString ( ) ) ;
118+ var files = Directory . GetFiles ( folderPath ) ;
119+ var regexIdFile = new Regex ( @"\[(\d+)\]" , RegexOptions . Compiled ) ;
120+ var regexIdUrl = new Regex ( @"video\/(\d+)" , RegexOptions . Compiled ) ;
121+ //https://www.tiktok.com/@username/video/6935994246793006341
122+
123+ var idToUrl = new Dictionary < string , string > ( ) ;
124+ foreach ( var url in urls )
125+ {
126+ var match = regexIdUrl . Match ( url ) ;
127+ if ( TryGetCapture ( match , out var id ) )
128+ {
129+ idToUrl . Add ( id , url ) ;
130+ }
105131 }
132+
133+ foreach ( var file in files )
134+ {
135+ var match = regexIdFile . Match ( Path . GetFileName ( file ) ) ;
136+ if ( TryGetCapture ( match , out var videoId ) && idToUrl . ContainsKey ( videoId ) )
137+ {
138+ idToUrl . Remove ( videoId ) ;
139+ DownloadedCount ++ ;
140+ }
141+ }
142+ return idToUrl . Select ( kv => kv . Value ) . ToList ( ) ;
106143 }
107144
145+ private bool TryGetCapture ( Match match , out string data )
146+ {
147+ data = null ;
148+ if ( match . Success )
149+ {
150+ data = match . Groups . Values . LastOrDefault ( ) ? . Value ;
151+ }
152+ return data != null ;
153+ }
154+
155+
108156 private async Task FindFavoriteVideos ( List < string > urls , CancellationToken token )
109157 {
110158 FavoriteVideos . Clear ( ) ;
111159 var a = urls . ToList ( ) ;
112- //for (int i = 0; i < 50; i++)
113- //{
114- // urls.AddRange(a);
115- //}
116160
117161 foreach ( var chunk in urls . Chunk ( 4 ) )
118162 {
0 commit comments