[\r\n\s]*?\<[^\>]*?alt=""([^""]*)"""
+ albumName = StringTrim(RegexReplace(r, albumRegex))
+ If albumName.IsEmptyString Then albumName = block.AlbumID
+ Using j As EContainer = JsonDocument.Parse("{" & block.Data & "}", jErr)
+ If Not j Is Nothing Then
+ If If(j("urls")?.Count, 0) > 0 Then
+ _TempMediaList.ListAddList(j("urls").Select(Function(jj) _
+ New UserMedia(jj.ItemF({0}).XmlIfNothingValue, UTypes.Picture) With {
+ .SpecialFolder = $"Albums\{albumName}\"}), LNC)
+ End If
+ End If
+ End Using
+ Next
+ l.Clear()
+ End If
+ End If
+ End If
+ Return True
+ Catch ex As Exception
+ ThrowAny(Token)
+ Return False
+ End Try
+ End Function
+ Private Overloads Function DownloadUserPhotos_PornHub(ByVal Token As CancellationToken) As Boolean
+ Try
+ Dim albumName$
+ Dim page%
+ Dim r$ = Responser.GetResponse(String.Format(PhotoUrlPattern_PornHub, PersonType, NameTrue))
+ If Not r.IsEmptyString Then
+ Dim l As List(Of PhotoBlock) = RegexFields(Of PhotoBlock)(r, {Regex_Photo_PornHub_PhotoBlocks}, {2, 1})
+ If l.ListExists Then l.RemoveAll(Function(ll) ll.AlbumID.IsEmptyString)
+ If l.ListExists Then
+ For Each block As PhotoBlock In l
+ If Not _TempPostsList.Contains(block.AlbumID) Then _TempPostsList.Add(block.AlbumID) Else Continue For
+ albumName = block.Data
+ If albumName.IsEmptyString Then
+ albumName = block.AlbumID.Split("/").LastOrDefault.StringTrim
+ Else
+ albumName = HtmlConverter(albumName).StringRemoveWinForbiddenSymbols.StringTrim
+ End If
+ page = 1
+ Do While DownloadUserPhotos_PornHub(page, block.AlbumID, albumName, Token) : page += 1 : Loop
+ Next
+ l.Clear()
+ End If
+ End If
+ Return True
+ Catch ex As Exception
+ ThrowAny(Token)
+ Return False
+ End Try
+ End Function
+ Private Overloads Function DownloadUserPhotos_PornHub(ByVal Page As Integer, ByVal AlbumID As String, ByVal AlbumName As String,
+ ByVal Token As CancellationToken) As Boolean
+ Try
+ Dim r$ = Responser.GetResponse($"https://www.pornhub.com{AlbumID}{IIf(Page = 1, String.Empty, $"?page={Page}")}")
+ If Not r.IsEmptyString Then
+ Dim l As List(Of String) = RegexReplace(r, Regex_Photo_PornHub_AlbumPhotoArr)
+ If l.ListExists Then l.RemoveAll(Function(_url) _url.IsEmptyString)
+ If l.ListExists Then
+ For Each url$ In l
+ ThrowAny(Token)
+ Try
+ r = Responser.GetResponse(url)
+ If Not r.IsEmptyString Then
+ url = RegexReplace(r, Regex_Photo_PornHub_SinglePhoto)
+ If Not url.IsEmptyString Then _
+ _TempMediaList.ListAddValue(New UserMedia(url, UTypes.Picture) With {.SpecialFolder = $"Albums\{AlbumName}\"}, LNC)
+ End If
+ Catch
+ End Try
+ Next
+ l.Clear()
+ Return True
+ End If
+ End If
+ Return False
+ Catch ex As Exception
+ ThrowAny(Token)
+ Return False
+ End Try
+ End Function
+ Private Function DownloadUserPhotos_SavedPosts(ByVal Token As CancellationToken) As Boolean
+ Const HtmlPageNotFoundPhoto$ = "Page Not Found"
+ Dim URL$ = $"https://www.pornhub.com/{PersonType}/{NameTrue}/photos/favorites"
+ Try
+ Dim r$ = Responser.GetResponse(URL)
+ If Not r.IsEmptyString Then
+ If r.Contains(HtmlPageNotFoundPhoto) Then Return False
+ Dim urls As List(Of String) = RegexReplace(r, Regex_Photo_PornHub_AlbumPhotoArr)
+ If urls.ListExists Then
+ Dim NewUrl$
+ Dim m As UserMedia
+ Dim l2 As List(Of UserMedia) = urls.Select(Function(__url) New UserMedia(__url, UTypes.Picture) With {
+ .Post = __url.Split("/").LastOrDefault}).ToList
+ urls.Clear()
+ If l2.ListExists Then l2.RemoveAll(Function(media) media.URL.IsEmptyString)
+ If l2.ListExists Then
+ Dim lBefore% = l2.Count
+ If _TempPostsList.Count > 0 Then l2.RemoveAll(Function(media) _TempPostsList.Contains(media.Post.ID))
+ If l2.Count > 0 Then
+ For i% = 0 To l2.Count - 1
+ m = l2(i)
+ ThrowAny(Token)
+ Try
+ r = Responser.GetResponse(m.URL)
+ If Not r.IsEmptyString Then
+ NewUrl = RegexReplace(r, Regex_Photo_PornHub_SinglePhoto)
+ If Not NewUrl.IsEmptyString Then
+ m.URL = NewUrl
+ m.File = NewUrl
+ _TempPostsList.ListAddValue(m.Post.ID, LNC)
+ Else
+ Throw New Exception
+ End If
+ End If
+ Catch
+ m.State = UserMedia.States.Missing
+ End Try
+ _TempMediaList.ListAddValue(m, LNC)
+ Next
+ End If
+ Return l2.Count = lBefore
+ End If
+ End If
+ End If
+ Return False
+ Catch ex As Exception
+ Return ProcessException(ex, Token, $"photos downloading error [{URL}]")
+ End Try
+ End Function
+#End Region
+#End Region
+#Region "ReparseVideo"
+ Protected Overrides Sub ReparseVideo(ByVal Token As CancellationToken)
+ Const ERR_NEW_URL$ = "ERR_NEW_URL"
+ Dim URL$ = String.Empty
+ Try
+ If _TempMediaList.Count > 0 AndAlso _TempMediaList.Exists(Function(tm) tm.Type = UTypes.VideoPre) Then
+ Dim m As UserMedia
+ Dim r$, NewUrl$
+ For i% = _TempMediaList.Count - 1 To 0 Step -1
+ If _TempMediaList(i).Type = UTypes.VideoPre Then
+ m = _TempMediaList(i)
+ ThrowAny(Token)
+ Try
+ URL = m.URL
+ r = Responser.Curl(URL)
+ If Not r.IsEmptyString Then
+ NewUrl = CreateVideoURL(r)
+ If NewUrl.IsEmptyString Then
+ Throw New Exception With {.HelpLink = ERR_NEW_URL}
+ Else
+ m.URL = NewUrl
+ m.Type = UTypes.m3u8
+ _TempMediaList(i) = m
+ End If
+ Else
+ _TempMediaList.RemoveAt(i)
+ End If
+ Catch mid_ex As Exception
+ If mid_ex.HelpLink = ERR_NEW_URL OrElse DownloadingException(mid_ex, "") = 1 Then
+ m.State = UserMedia.States.Missing
+ _TempMediaList(i) = m
+ Else
+ _TempMediaList.RemoveAt(i)
+ End If
+ End Try
+ End If
+ Next
+ End If
+ Catch ex As Exception
+ ProcessException(ex, Token, "video reparsing error", False)
+ End Try
+ End Sub
+#End Region
+#Region "ReparseMissing"
+ Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken)
+ Dim rList As New List(Of Integer)
+ Try
+ If ContentMissingExists Then
+ Dim m As UserMedia
+ Dim r$
+ Dim eCurl As New ErrorsDescriber(EDP.ReturnValue)
+ For i% = 0 To _ContentList.Count - 1
+ m = _ContentList(i)
+ If m.State = UserMedia.States.Missing AndAlso Not m.URL_BASE.IsEmptyString Then
+ ThrowAny(Token)
+ r = Responser.Curl(m.URL_BASE, eCurl)
+ If Not r.IsEmptyString Then
+ Dim NewUrl$ = CreateVideoURL(r)
+ If Not NewUrl.IsEmptyString Then
+ m.URL = NewUrl
+ _TempMediaList.ListAddValue(m, LNC)
+ rList.Add(i)
+ End If
+ End If
+ End If
+ Next
+ End If
+ Catch ex As Exception
+ ProcessException(ex, Token, "missing data downloading error")
+ Finally
+ If rList.Count > 0 Then
+ For i% = rList.Count - 1 To 0 Step -1 : _ContentList.RemoveAt(rList(i)) : Next
+ rList.Clear()
+ End If
+ End Try
+ End Sub
+#End Region
+#Region "Download content"
+ Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
+ DownloadContentDefault(Token)
+ End Sub
+ Protected Overrides Function DownloadM3U8(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile) As SFile
+ Return M3U8.Download(URL, Responser, DestinationFile)
+ End Function
+#End Region
+#Region "CreateVideoURL"
+ Private Shared Function CreateVideoURL(ByVal r As String) As String
+ Try
+ Dim OutStr$ = String.Empty
+ If Not r.IsEmptyString Then
+ Dim _VarBlock$ = RegexReplace(r, RegexVideo_FlashVarsBlock)
+ If Not _VarBlock.IsEmptyString Then
+ Dim vars As List(Of FlashVar) = RegexFields(Of FlashVar)(_VarBlock, {RegexVideo_FlashVars_Vars}, {1, 2})
+ Dim compiler As List(Of String) = RegexReplace(_VarBlock, RegexVideo_FlashVars_Compiler)
+ If vars.ListExists And compiler.ListExists Then
+ Dim v$
+ Dim i%
+ For Each var$ In compiler
+ i = vars.IndexOf(var)
+ If i >= 0 Then
+ v = vars(i).Value
+ If Not v.IsEmptyString Then OutStr &= v
+ End If
+ Next
+ End If
+ End If
+ End If
+ Return OutStr
+ Catch ex As Exception
+ Return ErrorsDescriber.Execute(EDP.SendInLog, ex, "[API.PornHub.UserData.CreateVideoURL]", String.Empty)
+ End Try
+ End Function
+#End Region
+#Region "Standalone downloader"
+ Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal Responser As Response, ByVal Destination As SFile) As UserMedia
+ Try
+ Dim r$ = Responser.Curl(URL)
+ If Not r.IsEmptyString Then
+ Dim NewUrl$ = CreateVideoURL(r)
+ If Not NewUrl.IsEmptyString Then
+ Dim f As SFile = M3U8.Download(NewUrl, Responser, Destination)
+ If Not f.IsEmptyString Then Return New UserMedia With {.State = UserMedia.States.Downloaded}
+ End If
+ End If
+ Return Nothing
+ Catch ex As Exception
+ Return ErrorsDescriber.Execute(EDP.SendInLog + EDP.ReturnValue, ex, $"PornHub standalone download error: [{URL}]", New UserMedia)
+ End Try
+ End Function
+#End Region
+#Region "Exceptions"
+ Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String,
+ Optional ByVal FromPE As Boolean = False, Optional ByVal EObj As Object = Nothing) As Integer
+ If Responser.Status = Net.WebExceptionStatus.ConnectionClosed Then
+ Return 1
+ ElseIf Responser.StatusCode = Net.HttpStatusCode.ServiceUnavailable Then
+ Return 2
+ Else
+ Return 0
+ End If
+ End Function
+#End Region
+ End Class
+End Namespace
\ No newline at end of file
diff --git a/SCrawler/API/PornHub/UserExchangeOptions.vb b/SCrawler/API/PornHub/UserExchangeOptions.vb
new file mode 100644
index 0000000..9ccc4b4
--- /dev/null
+++ b/SCrawler/API/PornHub/UserExchangeOptions.vb
@@ -0,0 +1,23 @@
+' Copyright (C) 2023 Andy https://github.com/AAndyProgram
+' This program is free software: you can redistribute it and/or modify
+' it under the terms of the GNU General Public License as published by
+' the Free Software Foundation, either version 3 of the License, or
+' (at your option) any later version.
+'
+' This program is distributed in the hope that it will be useful,
+' but WITHOUT ANY WARRANTY
+Namespace API.PornHub
+ Friend Class UserExchangeOptions
+ Friend Property DownloadGifs As Boolean
+ Friend Property DownloadPhotoOnlyFromModelHub As Boolean
+ Friend Sub New(ByVal u As UserData)
+ DownloadGifs = u.DownloadGifs
+ DownloadPhotoOnlyFromModelHub = u.DownloadPhotoOnlyFromModelHub
+ End Sub
+ Friend Sub New(ByVal s As SiteSettings)
+ Dim v As CheckState = CInt(s.DownloadGifs.Value)
+ DownloadGifs = Not v = CheckState.Unchecked
+ DownloadPhotoOnlyFromModelHub = s.DownloadPhotoOnlyFromModelHub.Value
+ End Sub
+ End Class
+End Namespace
\ No newline at end of file
diff --git a/SCrawler/API/Reddit/M3U8.vb b/SCrawler/API/Reddit/M3U8.vb
index 4307d1a..7578d65 100644
--- a/SCrawler/API/Reddit/M3U8.vb
+++ b/SCrawler/API/Reddit/M3U8.vb
@@ -8,7 +8,7 @@
' but WITHOUT ANY WARRANTY
Imports System.Net
Imports SCrawler.API.Reddit.M3U8_Declarations
-Imports PersonalUtilities.Tools.WEB
+Imports PersonalUtilities.Tools.Web
Imports PersonalUtilities.Functions.RegularExpressions
Namespace API.Reddit
Namespace M3U8_Declarations
diff --git a/SCrawler/API/Reddit/SiteSettings.vb b/SCrawler/API/Reddit/SiteSettings.vb
index a2bea8c..e16387c 100644
--- a/SCrawler/API/Reddit/SiteSettings.vb
+++ b/SCrawler/API/Reddit/SiteSettings.vb
@@ -25,7 +25,7 @@ Namespace API.Reddit
Return My.Resources.SiteResources.RedditPic_512
End Get
End Property
-
+
Friend ReadOnly Property SavedPostsUserName As PropertyValue
Friend ReadOnly Property UseM3U8 As PropertyValue
@@ -40,6 +40,7 @@ Namespace API.Reddit
UrlPatternUser = "https://www.reddit.com/user/{0}/"
UrlPatternChannel = "https://www.reddit.com/r/{0}/"
ImageVideoContains = "reddit.com"
+ UserRegex = RParams.DM("[htps:/]{7,8}.*?reddit.com/([user]{1,4})/([^/]+)", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
End Sub
Friend Overrides Function GetInstance(ByVal What As Download) As IPluginContentProvider
Select Case What
@@ -55,19 +56,9 @@ Namespace API.Reddit
End Select
Return Nothing
End Function
- Private ReadOnly RedditRegEx1 As RParams = RParams.DMS("[htps:/]{7,8}.*?reddit.com/user/([^/]+)", 1)
- Private ReadOnly RedditRegEx2 As RParams = RParams.DMS(".?u/([^/]+)", 1)
- Private ReadOnly RedditChannelRegEx1 As RParams = RParams.DMS("[htps:/]{7,8}.*?reddit.com/r/([^/]+)", 1)
- Private ReadOnly RedditChannelRegEx2 As RParams = RParams.DMS(".?r/([^/]+)", 1)
Friend Overrides Function IsMyUser(ByVal UserURL As String) As ExchangeOptions
- Dim s$
- Dim c% = 0
- For Each r As RParams In {RedditRegEx1, RedditRegEx2, RedditChannelRegEx1, RedditChannelRegEx2}
- s = RegexReplace(UserURL, r)
- If Not s.IsEmptyString Then Return New ExchangeOptions(Site, s, c > 1)
- c += 1
- Next
- Return Nothing
+ Dim l As List(Of String) = RegexReplace(UserURL, UserRegex)
+ If l.ListExists(3) Then Return New ExchangeOptions(Site, l(2), l(1) = "r") Else Return Nothing
End Function
Friend Overrides Function Available(ByVal What As Download, ByVal Silent As Boolean) As Boolean
Try
@@ -83,7 +74,7 @@ Namespace API.Reddit
avg.NumToString(New ANumbers With {.FormatOptions = ANumbers.Options.GroupIntegral}) & " outage reports:" & vbCr &
dl.ListToString(vbCr) & vbCr & vbCr &
"Do you want to continue parsing Reddit data?", "There are outage reports on Reddit"}, vbYesNo) = vbYes Then
- DirectCast(Settings(RedGifs.RedGifsSiteKey).Source, RedGifs.SiteSettings).UpdateTokenIfRequired()
+ UpdateRedGifsToken()
Return True
Else
Return False
@@ -91,11 +82,15 @@ Namespace API.Reddit
End If
End If
End If
+ UpdateRedGifsToken()
Return True
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.SendInLog + EDP.ReturnValue, ex, "[API.Reddit.SiteSettings.Available]", True)
End Try
End Function
+ Private Sub UpdateRedGifsToken()
+ DirectCast(Settings(RedGifs.RedGifsSiteKey).Source, RedGifs.SiteSettings).UpdateTokenIfRequired()
+ End Sub
Friend Overrides Function GetSpecialData(ByVal URL As String, ByVal Path As String, ByVal AskForPath As Boolean) As IEnumerable
Dim spf$ = String.Empty
Dim f As SFile = GetSpecialDataFile(Path, AskForPath, spf)
@@ -108,8 +103,8 @@ Namespace API.Reddit
Using f As New RedditViewSettingsForm(Options) : f.ShowDialog() : End Using
End If
End Sub
- Friend Overrides Function GetUserPostUrl(ByVal UserID As String, ByVal PostID As String) As String
- Return $"https://www.reddit.com/comments/{PostID.Split("_").LastOrDefault}/"
+ Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
+ Return $"https://www.reddit.com/comments/{Media.Post.ID.Split("_").LastOrDefault}/"
End Function
End Class
End Namespace
\ No newline at end of file
diff --git a/SCrawler/API/Reddit/UserData.vb b/SCrawler/API/Reddit/UserData.vb
index dc1284e..cb84692 100644
--- a/SCrawler/API/Reddit/UserData.vb
+++ b/SCrawler/API/Reddit/UserData.vb
@@ -14,8 +14,8 @@ Imports SCrawler.Plugin.Hosts
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.RegularExpressions
Imports PersonalUtilities.Tools.ImageRenderer
-Imports PersonalUtilities.Tools.WEB
-Imports PersonalUtilities.Tools.WebDocuments.JSON
+Imports PersonalUtilities.Tools.Web.Clients
+Imports PersonalUtilities.Tools.Web.Documents.JSON
Imports UStates = SCrawler.API.Base.UserMedia.States
Imports UTypes = SCrawler.API.Base.UserMedia.Types
Imports CView = SCrawler.API.Reddit.IRedditView.View
@@ -152,6 +152,8 @@ Namespace API.Reddit
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
_TotalPostsDownloaded = 0
If IsSavedPosts Then
+ 'TODO: Reddit saved posts: remove Unicode converter?
+ Responser.DecodersError = EDP.ReturnValue
DownloadDataChannel(String.Empty, Token)
ElseIf IsChannel Then
If ChannelInfo Is Nothing Then
diff --git a/SCrawler/API/Redgifs/Declarations.vb b/SCrawler/API/Redgifs/Declarations.vb
index 1deff2c..3fd01e6 100644
--- a/SCrawler/API/Redgifs/Declarations.vb
+++ b/SCrawler/API/Redgifs/Declarations.vb
@@ -14,6 +14,6 @@ Namespace API.RedGifs
Friend ReadOnly DateProvider As New CustomProvider(Function(v, d, p, n, e) ADateTime.ParseUnicode(v, n, e))
Friend ReadOnly WatchIDRegex As RParams = RParams.DMS(".+?watch/([^\?&""/]+)", 1, EDP.ReturnValue)
Friend ReadOnly ThumbsIDRegex As RParams = RParams.DMS("([^/\?&""]+?)(-\w+?|)\.(mp4|jpg)", 1, EDP.ReturnValue,
- Function(v) If(CStr(v).IsEmptyString, String.Empty, CStr(v).ToLower.Trim))
+ CType(Function(Input$) Input.StringToLower.StringTrim, Func(Of String, String)))
End Module
End Namespace
\ No newline at end of file
diff --git a/SCrawler/API/Redgifs/SiteSettings.vb b/SCrawler/API/Redgifs/SiteSettings.vb
index a963252..fc71a92 100644
--- a/SCrawler/API/Redgifs/SiteSettings.vb
+++ b/SCrawler/API/Redgifs/SiteSettings.vb
@@ -11,8 +11,9 @@ Imports SCrawler.Plugin
Imports SCrawler.Plugin.Attributes
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.RegularExpressions
-Imports PersonalUtilities.Tools.WEB
-Imports PersonalUtilities.Tools.WebDocuments.JSON
+Imports PersonalUtilities.Tools.Web.Clients
+Imports PersonalUtilities.Tools.Web.Cookies
+Imports PersonalUtilities.Tools.Web.Documents.JSON
Imports UTypes = SCrawler.API.Base.UserMedia.Types
Imports UStates = SCrawler.API.Base.UserMedia.States
Namespace API.RedGifs
@@ -40,11 +41,9 @@ Namespace API.RedGifs
MyBase.New(RedGifsSite, "redgifs.com")
Dim t$ = String.Empty
With Responser
- Dim b As Boolean = Not .UseWebClient Or Not .UseWebClientCookies Or Not .UseWebClientAdditionalHeaders
- .UseWebClient = True
- .UseWebClientCookies = True
- .UseWebClientAdditionalHeaders = True
- If .Headers.Count > 0 AndAlso .Headers.ContainsKey(TokenName) Then t = .Headers(TokenName)
+ Dim b As Boolean = Not .Mode = Response.Modes.WebClient
+ .Mode = Response.Modes.WebClient
+ t = .HeadersValue(TokenName)
If b Then .SaveSettings()
End With
NoCredentialsResponser = New Response($"{SettingsFolderName}\Responser_{RedGifsSite}_NC.xml") With {
@@ -68,10 +67,8 @@ Namespace API.RedGifs
#End Region
#Region "Response updater"
Private Sub UpdateResponse(ByVal Value As String)
- With Responser.Headers
- If .Count = 0 OrElse Not .ContainsKey(TokenName) Then .Add(TokenName, Value) Else .Item(TokenName) = Value
- Responser.SaveSettings()
- End With
+ Responser.HeadersAdd(TokenName, Value)
+ Responser.SaveSettings()
End Sub
#End Region
#Region "Token updaters"
@@ -153,8 +150,8 @@ Namespace API.RedGifs
End If
Return Nothing
End Function
- Friend Overrides Function GetUserPostUrl(ByVal UserID As String, ByVal PostID As String) As String
- Return $"https://www.redgifs.com/watch/{PostID}"
+ Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
+ Return $"https://www.redgifs.com/watch/{Media.Post.ID}"
End Function
Friend Overrides Function BaseAuthExists() As Boolean
Return UpdateTokenIfRequired() AndAlso ACheck(Token.Value)
diff --git a/SCrawler/API/Redgifs/UserData.vb b/SCrawler/API/Redgifs/UserData.vb
index 1042d77..02a2f61 100644
--- a/SCrawler/API/Redgifs/UserData.vb
+++ b/SCrawler/API/Redgifs/UserData.vb
@@ -11,8 +11,8 @@ Imports System.Threading
Imports SCrawler.API.Base
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.RegularExpressions
-Imports PersonalUtilities.Tools.WEB
-Imports PersonalUtilities.Tools.WebDocuments.JSON
+Imports PersonalUtilities.Tools.Web.Clients
+Imports PersonalUtilities.Tools.Web.Documents.JSON
Imports UTypes = SCrawler.API.Base.UserMedia.Types
Imports UStates = SCrawler.API.Base.UserMedia.States
Namespace API.RedGifs
@@ -62,7 +62,7 @@ Namespace API.RedGifs
Case DateResult.Exit : Exit Sub
End Select
postID = g.Value("id")
- If Not _TempPostsList.Contains(postID) Then _TempPostsList.Add(postID) Else Exit For
+ If Not _TempPostsList.Contains(postID) Then _TempPostsList.Add(postID) Else Exit Sub
ObtainMedia(g, postID, postDate)
Next
End If
@@ -179,7 +179,7 @@ Namespace API.RedGifs
If Host.Source.Available(Plugin.ISiteSettings.Download.Main, True) Then
If Responser Is Nothing Then Responser = Host.Responser.Copy
URL = String.Format(PostDataUrl, Obj.ToLower)
- Dim r$ = Responser.DownloadString(URL, EDP.ThrowException)
+ Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException)
If Not r.IsEmptyString Then
Using j As EContainer = JsonDocument.Parse(r)
If Not j Is Nothing Then
@@ -206,8 +206,15 @@ Namespace API.RedGifs
If Not Responser Is Nothing AndAlso (Responser.Client.StatusCode = DataGone Or Responser.Client.StatusCode = HttpStatusCode.NotFound) Then
Return New UserMedia With {.State = DataGone}
Else
- Return ErrorsDescriber.Execute(EDP.SendInLog, ex, $"[API.RedGifs.UserData.GetDataFromUrlId({URL})]",
- New UserMedia With {.State = UStates.Missing})
+ Dim m As New UserMedia With {.State = UStates.Missing}
+ Dim _errText$ = "API.RedGifs.UserData.GetDataFromUrlId({0})"
+ If Responser.Client.StatusCode = HttpStatusCode.Unauthorized Then
+ _errText = $"RedGifs credentials have expired [{CInt(Responser.Client.StatusCode)}]: {_errText}"
+ MyMainLOG = String.Format(_errText, URL)
+ Return m
+ Else
+ Return ErrorsDescriber.Execute(EDP.SendInLog, ex, String.Format(_errText, URL), m)
+ End If
End If
End Try
End Function
diff --git a/SCrawler/API/TikTok/UserData.vb b/SCrawler/API/TikTok/UserData.vb
index a75048b..6f858bf 100644
--- a/SCrawler/API/TikTok/UserData.vb
+++ b/SCrawler/API/TikTok/UserData.vb
@@ -10,7 +10,7 @@ Imports System.Threading
Imports SCrawler.API.Base
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.RegularExpressions
-Imports PersonalUtilities.Tools.WEB
+Imports PersonalUtilities.Tools.Web.Clients
Namespace API.TikTok
Friend Class UserData : Inherits UserDataBase
Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean)
diff --git a/SCrawler/API/Twitter/Declarations.vb b/SCrawler/API/Twitter/Declarations.vb
index 5febb24..a1a055c 100644
--- a/SCrawler/API/Twitter/Declarations.vb
+++ b/SCrawler/API/Twitter/Declarations.vb
@@ -6,14 +6,21 @@
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
+Imports System.Globalization
Imports PersonalUtilities.Functions.XML.Base
Imports PersonalUtilities.Functions.RegularExpressions
Namespace API.Twitter
Friend Module Declarations
Friend Const TwitterSite As String = "Twitter"
- Friend DateProvider As New ADateTime(ADateTime.Formats.BaseDateTime)
+ Friend ReadOnly DateProvider As ADateTime = GetDateProvider()
Friend ReadOnly VideoNode As NodeParams() = {New NodeParams("video_info", True, True, True, True, 10)}
Friend ReadOnly VideoSizeRegEx As RParams = RParams.DMS("\d+x(\d+)", 1, EDP.ReturnValue)
Friend ReadOnly UserIdRegEx As RParams = RParams.DMS("user_id.:.(\d+)", 1, EDP.ReturnValue)
+ Private Function GetDateProvider() As ADateTime
+ Dim n As DateTimeFormatInfo = CultureInfo.GetCultureInfo("en-us").DateTimeFormat.Clone
+ n.FullDateTimePattern = "ddd MMM dd HH:mm:ss +ffff yyyy"
+ n.TimeSeparator = String.Empty
+ Return New ADateTime(DirectCast(n.Clone, DateTimeFormatInfo)) With {.DateTimeStyle = DateTimeStyles.AssumeUniversal}
+ End Function
End Module
End Namespace
\ No newline at end of file
diff --git a/SCrawler/API/Twitter/SiteSettings.vb b/SCrawler/API/Twitter/SiteSettings.vb
index cf2899d..6040603 100644
--- a/SCrawler/API/Twitter/SiteSettings.vb
+++ b/SCrawler/API/Twitter/SiteSettings.vb
@@ -9,8 +9,9 @@
Imports SCrawler.API.Base
Imports SCrawler.Plugin
Imports SCrawler.Plugin.Attributes
-Imports PersonalUtilities.Tools.WEB
Imports PersonalUtilities.Functions.RegularExpressions
+Imports PersonalUtilities.Tools.Web.Clients
+Imports PersonalUtilities.Tools.Web.Cookies
Namespace API.Twitter
Friend Class SiteSettings : Inherits SiteSettingsBase
@@ -31,7 +32,7 @@ Namespace API.Twitter
Private ReadOnly Property Auth As PropertyValue
Private ReadOnly Property Token As PropertyValue
-
+
Friend ReadOnly Property SavedPostsUserName As PropertyValue
Friend Overrides ReadOnly Property Responser As Response
Friend Sub New()
@@ -45,10 +46,8 @@ Namespace API.Twitter
If .File.Exists Then
If EncryptCookies.CookiesEncrypted Then .CookiesEncryptKey = SettingsCLS.CookieEncryptKey
.LoadSettings()
- With .Headers
- If .ContainsKey(Header_Authorization) Then a = .Item(Header_Authorization)
- If .ContainsKey(Header_Token) Then t = .Item(Header_Token)
- End With
+ a = .HeadersValue(Header_Authorization)
+ t = .HeadersValue(Header_Token)
Else
.ContentType = "application/json"
.Accept = "*/*"
@@ -56,17 +55,15 @@ Namespace API.Twitter
.Cookies = New CookieKeeper(.CookiesDomain) With {.EncryptKey = SettingsCLS.CookieEncryptKey}
.CookiesEncryptKey = SettingsCLS.CookieEncryptKey
.Decoders.Add(SymbolsConverter.Converters.Unicode)
- With .Headers
- .Add("sec-ch-ua", " Not;A Brand"";v=""99"", ""Google Chrome"";v=""91"", ""Chromium"";v=""91""")
- .Add("sec-ch-ua-mobile", "?0")
- .Add("sec-fetch-dest", "empty")
- .Add("sec-fetch-mode", "cors")
- .Add("sec-fetch-site", "same-origin")
- .Add(Header_Token, String.Empty)
- .Add("x-twitter-active-user", "yes")
- .Add("x-twitter-auth-type", "OAuth2Session")
- .Add(Header_Authorization, String.Empty)
- End With
+ .HeadersAdd("sec-ch-ua", " Not;A Brand"";v=""99"", ""Google Chrome"";v=""91"", ""Chromium"";v=""91""")
+ .HeadersAdd("sec-ch-ua-mobile", "?0")
+ .HeadersAdd("sec-fetch-dest", "empty")
+ .HeadersAdd("sec-fetch-mode", "cors")
+ .HeadersAdd("sec-fetch-site", "same-origin")
+ .HeadersAdd(Header_Token, String.Empty)
+ .HeadersAdd("x-twitter-active-user", "yes")
+ .HeadersAdd("x-twitter-auth-type", "OAuth2Session")
+ .HeadersAdd(Header_Authorization, String.Empty)
.SaveSettings()
End If
End With
@@ -87,8 +84,8 @@ Namespace API.Twitter
Case NameOf(Token) : f = Header_Token
End Select
If Not f.IsEmptyString Then
- If Responser.Headers.Count > 0 AndAlso Responser.Headers.ContainsKey(f) Then Responser.Headers.Remove(f)
- If Not CStr(Value).IsEmptyString Then Responser.Headers.Add(f, CStr(Value))
+ Responser.HeadersRemove(f)
+ If Not CStr(Value).IsEmptyString Then Responser.HeadersAdd(f, CStr(Value))
Responser.SaveSettings()
End If
End If
@@ -103,8 +100,8 @@ Namespace API.Twitter
Friend Overrides Function GetSpecialData(ByVal URL As String, ByVal Path As String, ByVal AskForPath As Boolean) As IEnumerable
Return UserData.GetVideoInfo(URL, Responser)
End Function
- Friend Overrides Function GetUserPostUrl(ByVal UserID As String, ByVal PostID As String) As String
- Return $"https://twitter.com/{UserID}/status/{PostID}"
+ Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
+ Return $"https://twitter.com/{User.Name}/status/{Media.Post.ID}"
End Function
Friend Overrides Function BaseAuthExists() As Boolean
Return If(Responser.Cookies?.Count, 0) > 0 And ACheck(Token.Value) And ACheck(Auth.Value)
diff --git a/SCrawler/API/Twitter/UserData.vb b/SCrawler/API/Twitter/UserData.vb
index 605de2e..3da25eb 100644
--- a/SCrawler/API/Twitter/UserData.vb
+++ b/SCrawler/API/Twitter/UserData.vb
@@ -11,8 +11,8 @@ Imports System.Threading
Imports SCrawler.API.Base
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.RegularExpressions
-Imports PersonalUtilities.Tools.WEB
-Imports PersonalUtilities.Tools.WebDocuments.JSON
+Imports PersonalUtilities.Tools.Web.Clients
+Imports PersonalUtilities.Tools.Web.Documents.JSON
Imports UStates = SCrawler.API.Base.UserMedia.States
Namespace API.Twitter
Friend Class UserData : Inherits UserDataBase
diff --git a/SCrawler/API/UserDataBind.vb b/SCrawler/API/UserDataBind.vb
index 8c4058a..4541b06 100644
--- a/SCrawler/API/UserDataBind.vb
+++ b/SCrawler/API/UserDataBind.vb
@@ -8,9 +8,10 @@
' but WITHOUT ANY WARRANTY
Imports System.Threading
Imports SCrawler.API.Base
-Imports PersonalUtilities.Tools
+Imports PersonalUtilities.Forms
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.Messaging
+Imports PersonalUtilities.Tools
Namespace API
Friend Class UserDataBind : Inherits UserDataBase : Implements ICollection(Of IUserData), IMyEnumerator(Of IUserData)
#Region "Events"
@@ -20,6 +21,17 @@ Namespace API
#Region "Declarations"
Friend ReadOnly Property Collections As List(Of IUserData)
#Region "Base class overrides"
+ Friend Overrides ReadOnly Property IsVirtual As Boolean
+ Get
+ Return CollectionModel = UsageModel.Virtual
+ End Get
+ End Property
+ Friend Overrides ReadOnly Property CollectionModel As UsageModel
+ Get
+ If Count > 0 Then Return Item(0).CollectionModel Else Return UsageModel.Default
+ End Get
+ End Property
+ Friend Property CurrentlyEdited As Boolean = False
Private _CollectionName As String = String.Empty
Friend Overrides Property CollectionName As String
Get
@@ -80,10 +92,13 @@ Namespace API
End Sub
Friend Overrides Function GetUserPicture() As Image
If Count > 0 Then
- Return Collections(0).GetPicture
- Else
- Return GetNullPicture(Settings.MaxLargeImageHeight)
+ Dim img As Image
+ For Each u As UserDataBase In Collections
+ img = u.GetPicture(Of Image)(False)
+ If Not img Is Nothing Then Return img
+ Next
End If
+ Return GetNullPicture(Settings.MaxLargeImageHeight)
End Function
#End Region
Friend Overrides ReadOnly Property DownloadedTotal(Optional ByVal Total As Boolean = True) As Integer
@@ -102,7 +117,15 @@ Namespace API
End Property
Friend Overrides Property MyFile As SFile
Get
- If Count > 0 Then Return Collections(0).File Else Return Nothing
+ If Count > 0 Then
+ If IsVirtual Then
+ Return GetRealUserFile.IfNullOrEmpty(Collections(0).File)
+ Else
+ Return Collections(0).File
+ End If
+ Else
+ Return Nothing
+ End If
End Get
Set(ByVal NewFile As SFile)
End Set
@@ -120,8 +143,8 @@ Namespace API
End Property
Friend Overrides Property DataMerging As Boolean
Get
- If Count > 0 Then
- Return DirectCast(Collections(0), UserDataBase).DataMerging
+ If Count > 0 AndAlso Collections.Exists(RealUser) Then
+ Return DirectCast(Collections.Find(RealUser), UserDataBase).DataMerging
Else
Return False
End If
@@ -184,6 +207,7 @@ Namespace API
End Property
Friend Overrides Function GetUserInformation() As String
Dim OutStr$ = String.Empty
+ If IsVirtual Then OutStr = "This is a virtual collection."
If Count > 0 Then Collections.ForEach(Sub(c) OutStr.StringAppendLine(DirectCast(c, UserDataBase).GetUserInformation(), vbNewLine.StringDup(2)))
Return OutStr
End Function
@@ -346,12 +370,36 @@ Namespace API
If Not e.Exists Then e = New ErrorsDescriber(EDP.SendInLog)
If Count > 0 Then Collections.ForEach(Sub(c) c.OpenSite(e))
End Sub
+ Private ReadOnly RealUser As Predicate(Of IUserData) = Function(u) u.UserModel = UsageModel.Default
Friend Overrides Sub OpenFolder()
Try
- If Count > 0 Then GlobalOpenPath(Collections(0).File.CutPath(2))
+ If Count > 0 Then
+ Dim i% = Collections.FindIndex(RealUser)
+ If i = -1 Then i = 0
+ If i >= 0 Then
+ If IsVirtual Or Collections(i).UserModel = UsageModel.Virtual Then
+ Collections(i).OpenFolder()
+ Else
+ GlobalOpenPath(Collections(i).File.CutPath(2))
+ End If
+ End If
+ End If
Catch
End Try
End Sub
+ Friend Function GetRealUserFile() As SFile
+ Dim i% = -1
+ If Count > 0 Then i = Collections.FindIndex(RealUser)
+ If i >= 0 Then Return Collections(i).File Else Return Nothing
+ End Function
+ Friend Function GetRealUserSpecialCollectionPath()
+ Dim _SpecialCollectionPath As SFile = Nothing
+ If Count > 0 And Not IsVirtual Then
+ Dim _RealUser As UserDataBase = Collections.Find(RealUser)
+ If Not _RealUser Is Nothing Then _SpecialCollectionPath = _RealUser.User.SpecialCollectionPath
+ End If
+ Return _SpecialCollectionPath
+ End Function
#End Region
#Region "ICollection Support"
Private ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of IUserData).IsReadOnly
@@ -386,8 +434,8 @@ Namespace API
'''
Friend Overloads Sub Add(ByVal _Item As IUserData) Implements ICollection(Of IUserData).Add
With _Item
- If .MoveFiles(CollectionName) Then
- If DataMerging Then DirectCast(.Self, UserDataBase).MergeData()
+ If .MoveFiles(CollectionName, GetRealUserSpecialCollectionPath()) Then
+ If Not _Item.IsVirtual And DataMerging Then DirectCast(.Self, UserDataBase).MergeData()
Collections.Add(_Item)
With Collections.Last
If Count > 1 Then
@@ -445,14 +493,9 @@ Namespace API
Private Sub ConsolidateScripts()
If Count > 1 AndAlso ScriptUse Then Collections.ForEach(Sub(c) c.ScriptUse = True)
End Sub
- Friend Sub AddRange(ByVal _Items As IEnumerable(Of IUserData))
- If _Items.ListExists Then
- For i% = 0 To _Items.Count - 1 : Add(_Items(i)) : Next
- End If
- End Sub
#End Region
#Region "Move, Merge"
- Friend Overrides Function MoveFiles(ByVal __CollectionName As String) As Boolean
+ Friend Overrides Function MoveFiles(ByVal __CollectionName As String, ByVal __SpecialCollectionPath As SFile) As Boolean
Throw New NotImplementedException("Move files is not available in the collection context")
End Function
Friend Overloads Sub MergeData(ByVal Merging As Boolean)
@@ -488,52 +531,69 @@ Namespace API
"Operation canceled", MsgBoxStyle.Critical)
Return False
Else
- DirectCast(_Item, UserDataBase).MoveFiles(String.Empty)
+ _Item.MoveFiles(String.Empty, Nothing)
MainFrameObj.ImageHandler(_Item)
AddRemoveBttDeleteHandler(_Item, False)
RaiseEvent OnUserRemoved(_Item)
Return Collections.Remove(_Item)
End If
End Function
- Friend Overrides Function Delete(Optional ByVal Multiple As Boolean = False) As Integer
+ Friend Overrides Function Delete(Optional ByVal Multiple As Boolean = False, Optional ByVal CollectionValue As Integer = -1) As Integer
If Count > 0 Then
Const MsgTitle$ = "Deleting a collection"
- Dim f As SFile
+ Dim f As SFile = Nothing
+ If Not IsVirtual Then
+ f = GetRealUserFile()
+ If Not f.IsEmptyString Then f = f.CutPath(IIf(DataMerging, 1, 2))
+ End If
Dim m As New MMessage($"Collection [{CollectionName} (number of profiles: {Count})] may contain data" & vbCr &
"Are you sure you want to delete the collection and all of its files?", MsgTitle,
- {New MsgBoxButton("Delete") With {.ToolTip = "Delete the collection and all files"},
+ {New MsgBoxButton("Delete") With {.ToolTip = "Delete the collection and all files", .KeyCode = Keys.Enter},
New MsgBoxButton("Split") With {
.ToolTip = "Users will be removed from the collection and will be displayed in the program as separate users." & vbCr &
- "All user data will remain."},
+ "All user data will remain.",
+ .KeyCode = New ButtonKey(Keys.Enter, True)},
"Cancel"}, vbExclamation)
- Select Case If(Multiple, 0, MsgBoxE(m).Index)
+ Dim v%
+ If CollectionValue >= 0 Then
+ v = CollectionValue
+ ElseIf Multiple Then
+ v = 0
+ Else
+ v = MsgBoxE(m)
+ End If
+ Select Case v
Case 0
- f = Collections(0).File.CutPath(IIf(DataMerging, 1, 2)).PathWithSeparator
- Settings.Users.Remove(Me)
Collections.ForEach(Sub(c) c.Delete())
- Downloader.UserRemove(Me)
- MainFrameObj.ImageHandler(Me, False)
- Collections.ListClearDispose
- Dispose(False)
- f.Delete(SFO.Path, SFODelete.EmptyOnly + Settings.DeleteMode, EDP.SendInLog)
- Return 2
+ If Collections.All(Function(c As UserDataBase) c.Disposed) Then
+ Settings.Users.Remove(Me)
+ Downloader.UserRemove(Me)
+ MainFrameObj.ImageHandler(Me, False)
+ Collections.ListClearDispose
+ Dispose(False)
+ If Not f.IsEmptyString Then f.Delete(SFO.Path, SFODelete.EmptyOnly + Settings.DeleteMode, EDP.SendInLog)
+ Return 2
+ End If
Case 1
If DataMerging Then
MsgBoxE({$"Collection [{CollectionName}] data merged{vbCr}Unable to split merged collection{vbCr}Operation canceled", MsgTitle}, vbExclamation)
Return 0
Else
- f = Collections(0).File.CutPath(2)
- Settings.Users.Remove(Me)
- Collections.ForEach(Sub(c)
- c.MoveFiles(String.Empty)
- MainFrameObj.ImageHandler(c)
+ Collections.ForEach(Sub(ByVal c As IUserData)
+ If c.MoveFiles(String.Empty, Nothing) Then
+ UserListLoader.UpdateUser(Settings.GetUser(c), True)
+ MainFrameObj.ImageHandler(c)
+ End If
End Sub)
- Collections.Clear()
- f.Delete(SFO.Path, SFODelete.Default + Settings.DeleteMode, EDP.SendInLog)
- Downloader.UserRemove(Me)
- MainFrameObj.ImageHandler(Me, False)
- Dispose(False)
- Return 3
+ If Collections.All(Function(c) c.CollectionName.IsEmptyString) Then
+ Settings.Users.Remove(Me)
+ Collections.Clear()
+ If Not f.IsEmptyString Then f.Delete(SFO.Path, SFODelete.Default + Settings.DeleteMode, EDP.SendInLog)
+ Downloader.UserRemove(Me)
+ MainFrameObj.ImageHandler(Me, False)
+ Dispose(False)
+ Return 3
+ End If
End If
Case Else : If Not Multiple Then MsgBoxE({"Operation canceled", MsgTitle})
End Select
@@ -562,9 +622,11 @@ Namespace API
"Deleting a user"}, vbExclamation,,,
{
New MsgBoxButton("Remove") With {
- .ToolTip = "Remove a user from the collection only. All its data will remain. The user will appear in the program."},
+ .ToolTip = "Remove a user from the collection only. All its data will remain. The user will appear in the program.",
+ .KeyCode = Keys.Enter},
New MsgBoxButton("Delete") With {
- .ToolTip = "Delete a user from the collection and erase their data."},
+ .ToolTip = "Delete a user from the collection and erase their data.",
+ .KeyCode = New ButtonKey(Keys.Enter, True)},
"Cancel"
}).Index
Case 0
diff --git a/SCrawler/API/XVIDEOS/Declarations.vb b/SCrawler/API/XVIDEOS/Declarations.vb
index cbd310f..dcbdc58 100644
--- a/SCrawler/API/XVIDEOS/Declarations.vb
+++ b/SCrawler/API/XVIDEOS/Declarations.vb
@@ -10,10 +10,13 @@ Imports PersonalUtilities.Functions.RegularExpressions
Namespace API.XVIDEOS
Friend Module Declarations
Friend Const XvideosSiteKey As String = "AndyProgram_XVIDEOS"
- Friend ReadOnly Property M3U8Regex As RParams = RParams.DM("http.+?.m3u8.*?(?=')", 0)
- Friend ReadOnly Property VideoTitleRegex As RParams = RParams.DMS("html5player.setVideoTitle\('(.+)(?='\);)", 1)
- Friend ReadOnly Property VideoID As RParams = RParams.DMS(".*?www.xvideos.com/(video\d+).*", 1)
- Friend ReadOnly Property M3U8Reparse As RParams = RParams.DM("NAME=""(\d+).*?""[\r\n]*?(.+)(?=(|[\r\n]+?))", 0, RegexReturn.List)
- Friend ReadOnly Property M3U8Appender As RParams = RParams.DM("(.+)(?=/.+?\.m3u8.*?)", 0)
+ Private ReadOnly HtmlConverter As Func(Of String, String) = Function(Input) SymbolsConverter.HTML.Decode(Input, EDP.ReturnValue)
+ Friend ReadOnly Regex_M3U8 As RParams = RParams.DM("http.+?.m3u8.*?(?=')", 0)
+ Friend ReadOnly Regex_VideoTitle As RParams = RParams.DMS("html5player.setVideoTitle\('(.+)(?='\);)", 1, EDP.ReturnValue, HtmlConverter)
+ Friend ReadOnly Regex_VideoID As RParams = RParams.DMS(".*?www.xvideos.com/(video\d+).*", 1)
+ Friend ReadOnly Regex_M3U8_Reparse As RParams = RParams.DM("NAME=""(\d+).*?""[\r\n]*?(.+)(?=(|[\r\n]+?))", 0, RegexReturn.List)
+ Friend ReadOnly Regex_M3U8_Appender As RParams = RParams.DM("(.+)(?=/.+?\.m3u8.*?)", 0)
+ Friend ReadOnly Regex_SavedVideosPlaylist As RParams = RParams.DM("
- Partial Friend Class SettingsForm : Inherits System.Windows.Forms.Form
-
- Protected Overrides Sub Dispose(ByVal disposing As Boolean)
- Try
- If disposing AndAlso components IsNot Nothing Then
- components.Dispose()
- End If
- Finally
- MyBase.Dispose(disposing)
- End Try
- End Sub
- Private components As System.ComponentModel.IContainer
-
- Private Sub InitializeComponent()
- Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
- Me.LIST_DOMAINS = New System.Windows.Forms.ListBox()
- CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
- CONTAINER_MAIN.ContentPanel.SuspendLayout()
- CONTAINER_MAIN.SuspendLayout()
- Me.SuspendLayout()
- '
- 'CONTAINER_MAIN
- '
- '
- 'CONTAINER_MAIN.ContentPanel
- '
- CONTAINER_MAIN.ContentPanel.Controls.Add(Me.LIST_DOMAINS)
- CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(384, 241)
- CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
- CONTAINER_MAIN.LeftToolStripPanelVisible = False
- CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
- CONTAINER_MAIN.Name = "CONTAINER_MAIN"
- CONTAINER_MAIN.RightToolStripPanelVisible = False
- CONTAINER_MAIN.Size = New System.Drawing.Size(384, 291)
- CONTAINER_MAIN.TabIndex = 0
- '
- 'LIST_DOMAINS
- '
- Me.LIST_DOMAINS.Dock = System.Windows.Forms.DockStyle.Fill
- Me.LIST_DOMAINS.FormattingEnabled = True
- Me.LIST_DOMAINS.Location = New System.Drawing.Point(0, 0)
- Me.LIST_DOMAINS.Name = "LIST_DOMAINS"
- Me.LIST_DOMAINS.Size = New System.Drawing.Size(384, 241)
- Me.LIST_DOMAINS.TabIndex = 0
- '
- 'SettingsForm
- '
- Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
- Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
- Me.ClientSize = New System.Drawing.Size(384, 291)
- Me.Controls.Add(CONTAINER_MAIN)
- Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
- Me.Icon = Global.SCrawler.My.Resources.SiteResources.XvideosIcon_48
- Me.KeyPreview = True
- Me.MaximizeBox = False
- Me.MaximumSize = New System.Drawing.Size(400, 330)
- Me.MinimizeBox = False
- Me.MinimumSize = New System.Drawing.Size(400, 330)
- Me.Name = "SettingsForm"
- Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
- Me.Text = "Settings"
- CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
- CONTAINER_MAIN.ResumeLayout(False)
- CONTAINER_MAIN.PerformLayout()
- Me.ResumeLayout(False)
-
- End Sub
- Private WithEvents LIST_DOMAINS As Windows.Forms.ListBox
- End Class
-End Namespace
\ No newline at end of file
diff --git a/SCrawler/API/XVIDEOS/SettingsForm.vb b/SCrawler/API/XVIDEOS/SettingsForm.vb
deleted file mode 100644
index be8ed58..0000000
--- a/SCrawler/API/XVIDEOS/SettingsForm.vb
+++ /dev/null
@@ -1,70 +0,0 @@
-' Copyright (C) 2023 Andy https://github.com/AAndyProgram
-' This program is free software: you can redistribute it and/or modify
-' it under the terms of the GNU General Public License as published by
-' the Free Software Foundation, either version 3 of the License, or
-' (at your option) any later version.
-'
-' This program is distributed in the hope that it will be useful,
-' but WITHOUT ANY WARRANTY
-Imports PersonalUtilities.Forms
-Imports PersonalUtilities.Forms.Toolbars
-Namespace API.XVIDEOS
- Friend Class SettingsForm
- Private Const SettingsDesignXmlNode As String = "XvideosSettingsForm"
- Private WithEvents MyDefs As DefaultFormOptions
- Private ReadOnly Property Source As SiteSettings
- Friend Sub New(ByRef s As SiteSettings)
- InitializeComponent()
- Source = s
- MyDefs = New DefaultFormOptions(Me, Settings.Design)
- End Sub
- Private Sub SettingsForm_Load(sender As Object, e As EventArgs) Handles Me.Load
- With MyDefs
- If Not Settings.Design.Contains(SettingsDesignXmlNode) Then Settings.Design.Add(SettingsDesignXmlNode, String.Empty)
- .MyViewInitialize(Me, Settings.Design(SettingsDesignXmlNode), True)
- .AddEditToolbar()
- .AddOkCancelToolbar()
- If Source.Domains.Count > 0 Then Source.Domains.ForEach(Sub(d) LIST_DOMAINS.Items.Add(d))
- .EndLoaderOperations()
- End With
- End Sub
- Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
- Source.Domains.Clear()
- With LIST_DOMAINS
- If .Items.Count > 0 Then
- For Each i In .Items : Source.Domains.Add(i.ToString) : Next
- End If
- End With
- Source.UpdateDomains()
- MyDefs.CloseForm()
- End Sub
- Private Sub MyDefs_ButtonAddClick(ByVal Sender As Object, ByVal e As EditToolbarEventArgs) Handles MyDefs.ButtonAddClick
- Dim nd$ = InputBoxE("Enter a new domain using the pattern [xvideos.com]:", "New domain")
- If Not nd.IsEmptyString Then
- If Not LIST_DOMAINS.Items.Contains(nd) Then
- LIST_DOMAINS.Items.Add(nd)
- Else
- MsgBoxE($"The domain [{nd}] already added")
- End If
- End If
- End Sub
- Private Sub MyDefs_ButtonDeleteClickE(ByVal Sender As Object, ByVal e As EditToolbarEventArgs) Handles MyDefs.ButtonDeleteClickE
- Const MsgTitle$ = "Removing domains"
- If _LatestSelected.ValueBetween(0, LIST_DOMAINS.Items.Count - 1) Then
- Dim n$ = LIST_DOMAINS.Items(_LatestSelected)
- If MsgBoxE({$"Are you sure you want to delete the [{n}] domain?", MsgTitle}, MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
- LIST_DOMAINS.Items.RemoveAt(_LatestSelected)
- MsgBoxE({$"Domain [{n}] removed", MsgTitle})
- Else
- MsgBoxE({"Operation canceled", MsgTitle})
- End If
- Else
- MsgBoxE({"No domain selected", MsgTitle}, vbExclamation)
- End If
- End Sub
- Private _LatestSelected As Integer = -1
- Private Sub LIST_DOMENS_SelectedIndexChanged(sender As Object, e As EventArgs) Handles LIST_DOMAINS.SelectedIndexChanged
- _LatestSelected = LIST_DOMAINS.SelectedIndex
- End Sub
- End Class
-End Namespace
\ No newline at end of file
diff --git a/SCrawler/API/XVIDEOS/SiteSettings.vb b/SCrawler/API/XVIDEOS/SiteSettings.vb
index 0c1103a..cbd691e 100644
--- a/SCrawler/API/XVIDEOS/SiteSettings.vb
+++ b/SCrawler/API/XVIDEOS/SiteSettings.vb
@@ -7,15 +7,16 @@
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports SCrawler.API.Base
+Imports SCrawler.API.BaseObjects
Imports SCrawler.Plugin
Imports SCrawler.Plugin.Attributes
Imports PersonalUtilities.Functions.RegularExpressions
-Imports PersonalUtilities.Tools.WEB
+Imports PersonalUtilities.Tools.Web.Clients
Namespace API.XVIDEOS
-
- Friend Class SiteSettings : Inherits SiteSettingsBase
-#Region "Images"
- Friend Overrides ReadOnly Property Icon As Icon
+
+ Friend Class SiteSettings : Inherits SiteSettingsBase : Implements IDomainContainer
+#Region "Declarations"
+ Friend Overrides ReadOnly Property Icon As Icon Implements IDomainContainer.Icon
Get
Return My.Resources.SiteResources.XvideosIcon_48
End Get
@@ -25,58 +26,87 @@ Namespace API.XVIDEOS
Return My.Resources.SiteResources.XvideosPic_32
End Get
End Property
+#Region "Domains"
+ Private ReadOnly Property IDomainContainer_Site As String Implements IDomainContainer.Site
+ Get
+ Return Site
+ End Get
+ End Property
+ Private ReadOnly Property SiteDomains As PropertyValue Implements IDomainContainer.DomainsSettingProp
+ Friend ReadOnly Property Domains As List(Of String) Implements IDomainContainer.Domains
+ Private ReadOnly Property DomainsTemp As List(Of String) Implements IDomainContainer.DomainsTemp
+ Private Property DomainsChanged As Boolean = False Implements IDomainContainer.DomainsChanged
+ Private ReadOnly Property DomainsDefault As String = "xvideos.com|xnxx.com" Implements IDomainContainer.DomainsDefault
#End Region
-#Region "Declarations"
- Private Property SiteDomains As PropertyValue
- Public Property DownloadUHD As PropertyValue
- Friend ReadOnly Property Domains As List(Of String)
- Private Const DomainsDefault As String = "xvideos.com|xnxx.com"
- Private _Initialized As Boolean = False
+ Friend Property DownloadUHD As PropertyValue
+ Private Property Initialized As Boolean = False Implements IDomainContainer.Initialized
+
+ Friend ReadOnly Property SavedVideosPlaylist As PropertyValue
#End Region
#Region "Initializer"
Friend Sub New()
MyBase.New("XVIDEOS", "www.xvideos.com")
+ Responser.DeclaredError = EDP.ThrowException
Domains = New List(Of String)
+ DomainsTemp = New List(Of String)
SiteDomains = New PropertyValue(DomainsDefault, GetType(String), Sub(s) UpdateDomains())
DownloadUHD = New PropertyValue(False)
+ SavedVideosPlaylist = New PropertyValue(String.Empty, GetType(String))
End Sub
Friend Overrides Sub EndInit()
- _Initialized = True
- UpdateDomains()
+ Initialized = True
+ DomainContainer.EndInit(Me)
+ DomainsTemp.ListAddList(Domains)
End Sub
#End Region
-#Region "Update"
- Private _DomainsUpdateInProgress As Boolean = False
- Friend Sub UpdateDomains()
- If Not _Initialized Then Exit Sub
- If Not _DomainsUpdateInProgress Then
- _DomainsUpdateInProgress = True
- If Not ACheck(SiteDomains.Value) Then SiteDomains.Value = DomainsDefault
- Domains.ListAddList(CStr(SiteDomains.Value).Split("|"), LAP.NotContainsOnly, LAP.ClearBeforeAdd)
- Domains.ListAddList(DomainsDefault.Split("|"), LAP.NotContainsOnly)
- SiteDomains.Value = Domains.ListToString("|")
- _DomainsUpdateInProgress = False
- End If
+#Region "Edit"
+ Private Property DomainsUpdateInProgress As Boolean = False Implements IDomainContainer.DomainsUpdateInProgress
+ Private Property DomainsUpdatedBySite As Boolean = False Implements IDomainContainer.DomainsUpdatedBySite
+ Friend Sub UpdateDomains() Implements IDomainContainer.UpdateDomains
+ DomainContainer.UpdateDomains(Me)
End Sub
Friend Overrides Sub Update()
- UpdateDomains()
+ DomainContainer.Update(Me)
Responser.SaveSettings()
End Sub
+ Friend Overrides Sub EndEdit()
+ DomainContainer.EndEdit(Me)
+ MyBase.EndEdit()
+ End Sub
+ Friend Overrides Sub OpenSettingsForm()
+ DomainContainer.OpenSettingsForm(Me)
+ End Sub
#End Region
#Region "Download"
Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider
- Return New UserData
+ If What = ISiteSettings.Download.SavedPosts Then
+ Return New UserData With {.IsSavedPosts = True, .User = New UserInfo With {.Name = "XVIDEOS"}}
+ Else
+ Return New UserData
+ End If
End Function
Friend Overrides Function Available(ByVal What As ISiteSettings.Download, ByVal Silent As Boolean) As Boolean
- Return Settings.UseM3U8
+ If Settings.UseM3U8 Then
+ If What = ISiteSettings.Download.SavedPosts Then
+ Return ACheck(SavedVideosPlaylist.Value) And If(Responser.Cookies?.Count, 0) > 0
+ Else
+ Return True
+ End If
+ Else
+ Return False
+ End If
End Function
#End Region
#Region "User: get, check"
- Friend Overrides Function GetUserUrl(ByVal UserName As String, ByVal Channel As Boolean) As String
- Dim user$ = UserName.Split("_").FirstOrDefault
- user &= $"/{UserName.Replace($"{user}_", String.Empty)}"
- Return user
+ Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider, ByVal Channel As Boolean) As String
+ Dim __user$ = User.Name.Split("_").FirstOrDefault
+ __user &= $"/{User.Name.Replace($"{User}_", String.Empty)}"
+ Return __user
End Function
Private Const UserRegexDefault As String = "/(profiles|[\w]*?[-]{0,1}channels)/([^/]+)(\Z|.*?)"
Private Const URD As String = ".*?{0}{1}"
@@ -84,9 +114,10 @@ Namespace API.XVIDEOS
If Not UserURL.IsEmptyString Then
If Domains.Count > 0 Then
Dim uName$, uOpt$, fStr$
+ Dim uErr As New ErrorsDescriber(EDP.ReturnValue)
For i% = 0 To Domains.Count - 1
fStr = String.Format(URD, Domains(i), UserRegexDefault)
- uName = RegexReplace(UserURL, RParams.DMS(fStr, 2))
+ uName = RegexReplace(UserURL, RParams.DMS(fStr, 2, uErr))
If Not uName.IsEmptyString Then
uOpt = RegexReplace(UserURL, RParams.DMS(fStr, 1))
If Not uOpt.IsEmptyString Then Return New ExchangeOptions(Site, $"{uOpt}_{uName}")
@@ -97,11 +128,6 @@ Namespace API.XVIDEOS
Return Nothing
End Function
#End Region
-#Region "Settings"
- Friend Overrides Sub OpenSettingsForm()
- Using f As New SettingsForm(Me) : f.ShowDialog() : End Using
- End Sub
-#End Region
#Region "Get special data"
Friend Overrides Function IsMyImageVideo(ByVal URL As String) As ExchangeOptions
If Not URL.IsEmptyString And Domains.Count > 0 Then
diff --git a/SCrawler/API/XVIDEOS/UserData.vb b/SCrawler/API/XVIDEOS/UserData.vb
index 93260f5..cf4c952 100644
--- a/SCrawler/API/XVIDEOS/UserData.vb
+++ b/SCrawler/API/XVIDEOS/UserData.vb
@@ -10,12 +10,29 @@ Imports System.Threading
Imports SCrawler.API.Base
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.RegularExpressions
-Imports PersonalUtilities.Tools.WEB
-Imports PersonalUtilities.Tools.WebDocuments.JSON
+Imports PersonalUtilities.Tools.Web.Clients
+Imports PersonalUtilities.Tools.Web.Documents.JSON
Imports UStates = SCrawler.API.Base.UserMedia.States
Imports UTypes = SCrawler.API.Base.UserMedia.Types
Namespace API.XVIDEOS
Friend Class UserData : Inherits UserDataBase
+ Private Structure PlayListVideo : Implements IRegExCreator
+ Friend ID As String
+ Friend URL As String
+ Friend Title As String
+ Private Function CreateFromArray(ByVal ParamsArray() As String) As Object Implements IRegExCreator.CreateFromArray
+ If ParamsArray.ListExists(3) Then
+ ID = ParamsArray(0)
+ URL = ParamsArray(1)
+ If Not URL.IsEmptyString Then URL = $"https://www.xvideos.com/{URL.StringTrimStart("/")}"
+ Title = ParamsArray(2).StringRemoveWinForbiddenSymbols.StringTrim
+ End If
+ Return Me
+ End Function
+ Friend Function ToUserMedia() As UserMedia
+ Return New UserMedia(URL, UTypes.VideoPre) With {.Object = Me, .PictureOption = Title, .Post = ID}
+ End Function
+ End Structure
Private ReadOnly Property MySettings As SiteSettings
Get
Return DirectCast(HOST.Source, SiteSettings)
@@ -28,71 +45,74 @@ Namespace API.XVIDEOS
UseInternalM3U8Function = True
End Sub
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
+ If Not Settings.UseM3U8 Then
+ If Not Settings.OS64 Then
+ MyMainLOG = $"XVIDEOS [{ToStringForLog()}]: The plugin only works with x64 OS."
+ Else
+ MyMainLOG = $"{ToStringForLog()}: File [ffmpeg.exe] not found"
+ End If
+ Exit Sub
+ End If
+ If IsSavedPosts Then
+ If Not ACheck(MySettings.SavedVideosPlaylist.Value) Then Throw New ArgumentNullException("SavedVideosPlaylist", "Playlist of saved videos cannot be null")
+ DownloadSavedVideos(Token)
+ Else
+ DownloadUserVideo(Token)
+ End If
+ End Sub
+ Private Sub DownloadUserVideo(ByVal Token As CancellationToken)
Dim URL$ = String.Empty
Try
- If Not Settings.UseM3U8 Then
- If Not Settings.OS64 Then
- MyMainLOG = $"XVIDEOS [{ToStringForLog()}]: The plugin only works with x64 OS."
- Else
- MyMainLOG = $"{ToStringForLog()}: File [ffmpeg.exe] not found"
- End If
- Exit Sub
- End If
-
Dim NextPage% = 0
Dim r$
+ Dim j As EContainer = Nothing
Dim jj As EContainer
- Dim e As ErrorsDescriber = EDP.ThrowException
- Dim user$ = MySettings.GetUserUrl(Name, False)
+ Dim user$ = MySettings.GetUserUrl(Me, False)
Dim p As UserMedia
Dim EnvirSet As Boolean = False
Do
ThrowAny(Token)
URL = $"https://www.xvideos.com/{user}/videos/new/{If(NextPage = 0, String.Empty, NextPage)}"
- r = Responser.GetResponse(URL,, e)
+ r = Responser.GetResponse(URL)
If Not r.IsEmptyString Then
If Not EnvirSet Then UserExists = True : UserSuspended = False : EnvirSet = True
- With JsonDocument.Parse(r).XmlIfNothing
+ j = JsonDocument.Parse(r).XmlIfNothing
+ With j
If .Contains("videos") Then
With .Item("videos")
If .Count > 0 Then
NextPage += 1
For Each jj In .Self
p = New UserMedia With {
- .Post = New UserPost With {.ID = jj.Value("id")},
- .URL = $"https://www.xvideos.com{jj.Value("u")}"
+ .Post = jj.Value("id"),
+ .URL = $"https://www.xvideos.com/{jj.Value("u").StringTrimStart("/")}"
}
If Not p.Post.ID.IsEmptyString And Not jj.Value("u").IsEmptyString Then
If Not _TempPostsList.Contains(p.Post.ID) Then
_TempPostsList.Add(p.Post.ID)
_TempMediaList.Add(p)
Else
- .Dispose()
Exit Do
End If
End If
Next
- Else
- .Dispose()
- Exit Do
+ Continue Do
End If
End With
- Else
- .Dispose()
- Exit Do
End If
- .Dispose()
End With
- Else
- Exit Do
End If
- Loop
+ If Not j Is Nothing Then j.Dispose()
+ Exit Do
+ Loop While NextPage < 100
+
+ If Not j Is Nothing Then j.Dispose()
If _TempMediaList.Count > 0 Then
For i% = 0 To _TempMediaList.Count - 1
ThrowAny(Token)
- With _TempMediaList(i) : _TempMediaList(i) = GetVideoData(.URL, Responser, MySettings.DownloadUHD.Value, .Post.ID) : End With
+ _TempMediaList(i) = GetVideoData(_TempMediaList(i), Responser, MySettings.DownloadUHD.Value)
Next
_TempMediaList.RemoveAll(Function(m) m.URL.IsEmptyString)
End If
@@ -108,38 +128,80 @@ Namespace API.XVIDEOS
If _TempMediaList.ListExists Then _TempMediaList.RemoveAll(Function(m) m.URL.IsEmptyString)
End Try
End Sub
- Private Function GetVideoData(ByVal URL As String, ByVal resp As Response, ByVal DownloadUHD As Boolean, ByVal ID As String) As UserMedia
+ Private Sub DownloadSavedVideos(ByVal Token As CancellationToken)
+ Dim URL$ = MySettings.SavedVideosPlaylist.Value
Try
- If Not URL.IsEmptyString Then
- Dim r$ = resp.GetResponse(URL,, EDP.ThrowException)
+ Dim NextPage% = 0
+ Dim __continue As Boolean = True
+ Dim r$
+ Dim data As List(Of PlayListVideo)
+ Dim i%
+ Do
+ ThrowAny(Token)
+ URL = $"{MySettings.SavedVideosPlaylist.Value}{If(NextPage = 0, String.Empty, $"/{NextPage}")}"
+ r = Responser.GetResponse(URL,, EDP.ReturnValue)
+ If Responser.HasError Then
+ If Responser.StatusCode = Net.HttpStatusCode.NotFound And NextPage > 0 Then Exit Do
+ Throw New Exception(Responser.ErrorText, Responser.ErrorException)
+ End If
+ NextPage += 1
If Not r.IsEmptyString Then
- Dim m$ = RegexReplace(r, M3U8Regex)
- If Not m.IsEmptyString Then
- Dim appender$ = RegexReplace(m, M3U8Appender)
- Dim t$ = RegexReplace(r, VideoTitleRegex)
- r = resp.GetResponse(m,, EDP.ThrowException)
+ data = RegexFields(Of PlayListVideo)(r, {Regex_SavedVideosPlaylist}, {1, 2, 3}, EDP.ReturnValue)
+ If data.ListExists Then
+ If data.RemoveAll(Function(d) _TempPostsList.Contains(d.ID)) > 0 Then __continue = False
+ If data.ListExists Then
+ _TempPostsList.ListAddList(data.Select(Function(d) d.ID), LNC)
+ i = _TempMediaList.Count
+ _TempMediaList.ListAddList(data.Select(Function(d) d.ToUserMedia()), LNC)
+ If _TempMediaList.Count = i Or Not __continue Then Exit Do Else Continue Do
+ End If
+ End If
+ End If
+ Exit Do
+ Loop While NextPage < 100 And __continue
+
+ If _TempMediaList.Count > 0 Then
+ For i% = 0 To _TempMediaList.Count - 1
+ ThrowAny(Token)
+ _TempMediaList(i) = GetVideoData(_TempMediaList(i), Responser, MySettings.DownloadUHD.Value)
+ Next
+ _TempMediaList.RemoveAll(Function(m) m.URL.IsEmptyString)
+ End If
+ Catch ex As Exception
+ ProcessException(ex, Token, $"data downloading error [{URL}]")
+ End Try
+ End Sub
+ Private Function GetVideoData(ByVal Media As UserMedia, ByVal resp As Response, ByVal DownloadUHD As Boolean) As UserMedia
+ Try
+ If Not Media.URL.IsEmptyString Then
+ Dim r$ = resp.GetResponse(Media.URL)
+ If Not r.IsEmptyString Then
+ Dim NewUrl$ = RegexReplace(r, Regex_M3U8)
+ If Not NewUrl.IsEmptyString Then
+ Dim appender$ = RegexReplace(NewUrl, Regex_M3U8_Appender)
+ Dim t$ = If(Media.PictureOption.IsEmptyString, RegexReplace(r, Regex_VideoTitle), Media.PictureOption)
+ r = resp.GetResponse(NewUrl)
If Not r.IsEmptyString Then
- Dim ls As List(Of Sizes) = RegexFields(Of Sizes)(r, {M3U8Reparse}, {1, 2})
+ Dim ls As List(Of Sizes) = RegexFields(Of Sizes)(r, {Regex_M3U8_Reparse}, {1, 2})
If ls.ListExists And Not DownloadUHD Then ls.RemoveAll(Function(v) Not v.Value.ValueBetween(1, 1080))
If ls.ListExists Then
ls.Sort()
- m = $"{appender}/{ls(0).Data}"
+ NewUrl = $"{appender}/{ls(0).Data.StringTrimStart("/")}"
ls.Clear()
- Dim pID$ = ID
- If pID.IsEmptyString Then pID = RegexReplace(r, VideoID)
+ Dim pID$ = Media.Post.ID
+ If pID.IsEmptyString Then pID = RegexReplace(r, Regex_VideoID)
If pID.IsEmptyString Then pID = "0"
- If Not t.IsEmptyString Then t = t.StringRemoveWinForbiddenSymbols(" ")
+ t = t.StringRemoveWinForbiddenSymbols.StringTrim
If t.IsEmptyString Then
t = pID
Else
If t.Length > 100 Then t = Left(t, 100)
End If
- If Not m.IsEmptyString Then
- Return New UserMedia With {
- .Type = UTypes.m3u8,
- .Post = New UserPost With {.ID = pID},
- .URL = m,
+ If Not NewUrl.IsEmptyString Then
+ Return New UserMedia(NewUrl, UTypes.m3u8) With {
+ .Post = pID,
+ .URL_BASE = Media.URL,
.File = $"{t}.mp4",
.PictureOption = appender
}
@@ -151,18 +213,18 @@ Namespace API.XVIDEOS
End If
Return Nothing
Catch ex As Exception
- LogError(ex, $"[XVIDEOS.UserData.GetVideoData({URL})]")
+ LogError(ex, $"[XVIDEOS.UserData.GetVideoData({Media.URL})]")
Return Nothing
End Try
End Function
Friend Function Download(ByVal URL As String, ByVal resp As Response, ByVal DownloadUHD As Boolean, ByVal ID As String)
- Dim m As UserMedia = GetVideoData(URL, resp, DownloadUHD, ID)
+ Dim m As UserMedia = GetVideoData(New UserMedia(URL, UTypes.VideoPre) With {.Post = ID}, resp, DownloadUHD)
If Not m.URL.IsEmptyString Then
Dim f As SFile = m.File
f.Path = MyFile.PathNoSeparator
m.State = UStates.Tried
Try
- f = M3U8.Download(m.URL, m.PictureOption, Settings.FfmpegFile, f)
+ f = M3U8.Download(m.URL, m.PictureOption, f)
m.File = f
m.State = UStates.Downloaded
Catch ex As Exception
@@ -175,7 +237,7 @@ Namespace API.XVIDEOS
DownloadContentDefault(Token)
End Sub
Protected Overrides Function DownloadM3U8(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile) As SFile
- Return M3U8.Download(Media.URL, Media.PictureOption, Settings.FfmpegFile, DestinationFile)
+ Return M3U8.Download(Media.URL, Media.PictureOption, DestinationFile)
End Function
Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False,
Optional ByVal EObj As Object = Nothing) As Integer
diff --git a/SCrawler/API/Xhamster/Declarations.vb b/SCrawler/API/Xhamster/Declarations.vb
new file mode 100644
index 0000000..0d07a8c
--- /dev/null
+++ b/SCrawler/API/Xhamster/Declarations.vb
@@ -0,0 +1,19 @@
+' Copyright (C) 2023 Andy https://github.com/AAndyProgram
+' This program is free software: you can redistribute it and/or modify
+' it under the terms of the GNU General Public License as published by
+' the Free Software Foundation, either version 3 of the License, or
+' (at your option) any later version.
+'
+' This program is distributed in the hope that it will be useful,
+' but WITHOUT ANY WARRANTY
+'Imports System.Globalization
+Imports PersonalUtilities.Functions.RegularExpressions
+Namespace API.Xhamster
+ Friend Module Declarations
+ Friend Const XhamsterSiteKey As String = "AndyProgram_XHamster"
+ Friend ReadOnly HtmlScript As RParams = RParams.DMS("\", 1, EDP.ReturnValue,
+ CType(Function(Input$) Input.StringTrim, Func(Of String, String)))
+ Friend ReadOnly DateProvider As New CustomProvider(Function(v, d, p, n, e) ADateTime.ParseUnicode(v))
+ Friend ReadOnly FirstM3U8FileRegEx As RParams = RParams.DM("RESOLUTION=\d+x(\d+).*?[\r\n]+?([^#]*?\.m3u8.*)", 0, RegexReturn.List)
+ End Module
+End Namespace
\ No newline at end of file
diff --git a/SCrawler/API/Xhamster/M3U8.vb b/SCrawler/API/Xhamster/M3U8.vb
new file mode 100644
index 0000000..c6b96df
--- /dev/null
+++ b/SCrawler/API/Xhamster/M3U8.vb
@@ -0,0 +1,79 @@
+' Copyright (C) 2023 Andy https://github.com/AAndyProgram
+' This program is free software: you can redistribute it and/or modify
+' it under the terms of the GNU General Public License as published by
+' the Free Software Foundation, either version 3 of the License, or
+' (at your option) any later version.
+'
+' This program is distributed in the hope that it will be useful,
+' but WITHOUT ANY WARRANTY
+Imports SCrawler.API.Base
+Imports SCrawler.API.Base.M3U8Declarations
+Imports PersonalUtilities.Functions.RegularExpressions
+Imports PersonalUtilities.Tools.Web.Clients
+Namespace API.Xhamster
+ Friend NotInheritable Class M3U8
+ Private Sub New()
+ End Sub
+ Private Shared Function ParseFirstM3U8(ByVal URL As String, ByVal Responser As Response, ByVal UHD As Boolean) As String
+ Dim r$, d$
+ Dim _DataObtained As Boolean = False
+ For i% = 0 To 1
+ Try
+ Responser.UseGZipStream = i
+ r = Responser.GetResponse(URL.Replace("\", String.Empty))
+ If Not r.IsEmptyString Then
+ r = r.StringFormatLines
+ Dim sList As List(Of Sizes) = RegexFields(Of Sizes)(r, {FirstM3U8FileRegEx}, {1, 2})
+ If sList.ListExists Then _DataObtained = True : sList.RemoveAll(Function(sv) sv.HasError Or sv.Data.IsEmptyString Or
+ sv.Value = 0 Or (Not UHD And sv.Value > 1080))
+ If sList.ListExists Then
+ sList.Sort()
+ d = sList.First.Data.Trim
+ If Not d.IsEmptyString Then Return d
+ End If
+ End If
+ Catch
+ End Try
+ If _DataObtained Then Exit For
+ Next
+ Return String.Empty
+ End Function
+ Private Shared Function ParseSecondM3U8(ByVal URL As String, ByVal Responser As Response, ByVal Appender As String) As List(Of String)
+ Dim r$
+ Dim l As List(Of String)
+ For i% = 0 To 1
+ Try
+ Responser.UseGZipStream = i
+ r = Responser.GetResponse(URL)
+ If Not r.IsEmptyString Then
+ l = RegexReplace(r, TsFilesRegEx)
+ If l.ListExists Then
+ For indx% = 0 To l.Count - 1 : l(indx) = M3U8Base.CreateUrl(Appender, l(indx)) : Next
+ Return l
+ End If
+ End If
+ Catch
+ End Try
+ Next
+ Return Nothing
+ End Function
+ Private Shared Function ObtainUrls(ByVal URL As String, ByVal Responser As Response, ByVal UHD As Boolean) As List(Of String)
+ Try
+ Dim file$ = ParseFirstM3U8(URL, Responser, UHD)
+ If Not file.IsEmptyString Then
+ Responser.UseGZipStream = False
+ Dim appender$ = URL.Replace(URL.Split("/").LastOrDefault, String.Empty)
+ URL = M3U8Base.CreateUrl(appender, file)
+ Dim l As List(Of String) = ParseSecondM3U8(URL, Responser, appender)
+ If l.ListExists Then Return l
+ End If
+ Return Nothing
+ Finally
+ Responser.UseGZipStream = False
+ End Try
+ End Function
+ Friend Shared Function Download(ByVal Media As UserMedia, ByVal Responser As Response, ByVal UHD As Boolean) As SFile
+ Return M3U8Base.Download(ObtainUrls(Media.URL, Responser, UHD), Media.File, Responser)
+ End Function
+ End Class
+End Namespace
\ No newline at end of file
diff --git a/SCrawler/API/Xhamster/SiteSettings.vb b/SCrawler/API/Xhamster/SiteSettings.vb
new file mode 100644
index 0000000..5d0295e
--- /dev/null
+++ b/SCrawler/API/Xhamster/SiteSettings.vb
@@ -0,0 +1,155 @@
+' Copyright (C) 2023 Andy https://github.com/AAndyProgram
+' This program is free software: you can redistribute it and/or modify
+' it under the terms of the GNU General Public License as published by
+' the Free Software Foundation, either version 3 of the License, or
+' (at your option) any later version.
+'
+' This program is distributed in the hope that it will be useful,
+' but WITHOUT ANY WARRANTY
+Imports SCrawler.API.Base
+Imports SCrawler.API.BaseObjects
+Imports SCrawler.Plugin
+Imports SCrawler.Plugin.Attributes
+Imports PersonalUtilities.Functions.RegularExpressions
+Imports PersonalUtilities.Tools.Web.Clients
+Namespace API.Xhamster
+
+ Friend Class SiteSettings : Inherits SiteSettingsBase : Implements IDomainContainer
+#Region "Declarations"
+ Friend Overrides ReadOnly Property Icon As Icon Implements IDomainContainer.Icon
+ Get
+ Return My.Resources.SiteResources.XhamsterIcon_32
+ End Get
+ End Property
+ Friend Overrides ReadOnly Property Image As Image
+ Get
+ Return My.Resources.SiteResources.XhamsterPic_32
+ End Get
+ End Property
+#Region "Domains"
+ Private ReadOnly Property IDomainContainer_Site As String Implements IDomainContainer.Site
+ Get
+ Return Site
+ End Get
+ End Property
+ Private ReadOnly Property SiteDomains As PropertyValue Implements IDomainContainer.DomainsSettingProp
+ Friend ReadOnly Property Domains As List(Of String) Implements IDomainContainer.Domains
+ Private ReadOnly Property DomainsTemp As List(Of String) Implements IDomainContainer.DomainsTemp
+ Private Property DomainsChanged As Boolean = False Implements IDomainContainer.DomainsChanged
+ Friend ReadOnly Property DomainsUpdated As Boolean
+ Get
+ Return DomainsUpdatedBySite
+ End Get
+ End Property
+ Private ReadOnly Property DomainsDefault As String = "xhamster.com" Implements IDomainContainer.DomainsDefault
+#End Region
+
+ Friend Property DownloadUHD As PropertyValue
+ Private Property Initialized As Boolean = False Implements IDomainContainer.Initialized
+#End Region
+#Region "Initializer"
+ Friend Sub New()
+ MyBase.New("XHamster", "xhamster.com")
+
+ Responser.DeclaredError = EDP.ThrowException
+
+ Domains = New List(Of String)
+ DomainsTemp = New List(Of String)
+ SiteDomains = New PropertyValue(DomainsDefault, GetType(String), Sub(s) UpdateDomains())
+ DownloadUHD = New PropertyValue(False)
+
+ UrlPatternUser = "https://xhamster.com/users/{0}"
+ UserRegex = RParams.DMS("xhamster.com/users/([^/]+).*?", 1)
+ ImageVideoContains = "xhamster"
+ End Sub
+ Friend Overrides Sub EndInit()
+ Initialized = True
+ DomainContainer.EndInit(Me)
+ DomainsTemp.ListAddList(Domains)
+ MyBase.EndInit()
+ End Sub
+#End Region
+#Region "UpdateDomains"
+ Private Property DomainsUpdateInProgress As Boolean = False Implements IDomainContainer.DomainsUpdateInProgress
+ Private Property DomainsUpdatedBySite As Boolean = False Implements IDomainContainer.DomainsUpdatedBySite
+ Friend Overloads Sub UpdateDomains() Implements IDomainContainer.UpdateDomains
+ DomainContainer.UpdateDomains(Me)
+ End Sub
+ Friend Overloads Sub UpdateDomains(ByVal NewDomains As IEnumerable(Of String), ByVal Internal As Boolean)
+ DomainContainer.UpdateDomains(Me, NewDomains, Internal)
+ End Sub
+#End Region
+#Region "Edit"
+ Friend Overrides Sub Update()
+ DomainContainer.Update(Me)
+ Responser.SaveSettings()
+ MyBase.Update()
+ End Sub
+ Friend Overrides Sub EndEdit()
+ DomainContainer.EndEdit(Me)
+ MyBase.EndEdit()
+ End Sub
+ Friend Overrides Sub OpenSettingsForm()
+ DomainContainer.OpenSettingsForm(Me)
+ End Sub
+#End Region
+ Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider
+ If What = ISiteSettings.Download.SavedPosts Then
+ Return New UserData With {.IsSavedPosts = True, .User = New UserInfo With {.Name = "xhamster"}}
+ Else
+ Return New UserData
+ End If
+ End Function
+ Friend Overrides Function GetSpecialData(ByVal URL As String, ByVal Path As String, ByVal AskForPath As Boolean) As IEnumerable
+ If Available(ISiteSettings.Download.Main, True) Then
+ Using resp As Response = Responser.Copy
+ Dim spf$ = String.Empty
+ Dim f As SFile = GetSpecialDataFile(Path, AskForPath, spf)
+ Dim m As UserMedia = UserData.GetVideoInfo(URL, resp, f)
+ If m.State = UserMedia.States.Downloaded Then
+ m.SpecialFolder = f
+ Return {m}
+ End If
+ End Using
+ End If
+ Return Nothing
+ End Function
+ Friend Overrides Function Available(ByVal What As ISiteSettings.Download, Silent As Boolean) As Boolean
+ If Settings.UseM3U8 AndAlso MyBase.Available(What, Silent) Then
+ If What = ISiteSettings.Download.SavedPosts Then
+ Return If(Responser.Cookies?.Count, 0) > 0
+ Else
+ Return True
+ End If
+ Else
+ Return False
+ End If
+ End Function
+ Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
+ Return Media.URL_BASE
+ End Function
+#Region "Is my user/data"
+ Private Const UserRegexDefault As String = "{0}/users/([^/]+).*?"
+ Friend Overrides Function IsMyUser(ByVal UserURL As String) As ExchangeOptions
+ Dim b As ExchangeOptions = MyBase.IsMyUser(UserURL)
+ If b.Exists Then Return b
+ If Not UserURL.IsEmptyString And Domains.Count > 0 Then
+ Dim uName$, fStr$
+ Dim uErr As New ErrorsDescriber(EDP.ReturnValue)
+ For i% = 0 To Domains.Count - 1
+ fStr = String.Format(UserRegexDefault, Domains(i))
+ uName = RegexReplace(UserURL, RParams.DMS(fStr, 1, uErr))
+ If Not uName.IsEmptyString Then Return New ExchangeOptions(Site, uName)
+ Next
+ End If
+ Return Nothing
+ End Function
+ Friend Overrides Function IsMyImageVideo(ByVal URL As String) As ExchangeOptions
+ If Not URL.IsEmptyString And Domains.Count > 0 Then
+ If Domains.Exists(Function(d) URL.Contains(d)) Then Return New ExchangeOptions With {.UserName = URL, .Exists = True}
+ End If
+ Return Nothing
+ End Function
+#End Region
+ End Class
+End Namespace
\ No newline at end of file
diff --git a/SCrawler/API/Xhamster/UserData.vb b/SCrawler/API/Xhamster/UserData.vb
new file mode 100644
index 0000000..e2f0774
--- /dev/null
+++ b/SCrawler/API/Xhamster/UserData.vb
@@ -0,0 +1,344 @@
+' Copyright (C) 2023 Andy https://github.com/AAndyProgram
+' This program is free software: you can redistribute it and/or modify
+' it under the terms of the GNU General Public License as published by
+' the Free Software Foundation, either version 3 of the License, or
+' (at your option) any later version.
+'
+' This program is distributed in the hope that it will be useful,
+' but WITHOUT ANY WARRANTY
+Imports System.Threading
+Imports SCrawler.API.Base
+Imports PersonalUtilities.Functions.XML
+Imports PersonalUtilities.Functions.RegularExpressions
+Imports PersonalUtilities.Tools.Web.Clients
+Imports PersonalUtilities.Tools.Web.Documents.JSON
+Imports UTypes = SCrawler.API.Base.UserMedia.Types
+Namespace API.Xhamster
+ Friend Class UserData : Inherits UserDataBase
+#Region "Declarations"
+ Private ReadOnly Property MySettings As SiteSettings
+ Get
+ Return DirectCast(HOST.Source, SiteSettings)
+ End Get
+ End Property
+ Private Structure ExchObj
+ Friend IsPhoto As Boolean
+ End Structure
+ Private ReadOnly _TempPhotoData As List(Of UserMedia)
+ Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean)
+ End Sub
+#End Region
+#Region "Initializer"
+ Friend Sub New()
+ UseInternalM3U8Function = True
+ _TempPhotoData = New List(Of UserMedia)
+ End Sub
+#End Region
+#Region "Download base functions"
+ Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
+ _TempPhotoData.Clear()
+ If DownloadVideos Then DownloadData(1, True, Token)
+ If DownloadImages Then
+ DownloadData(1, False, Token)
+ ReparsePhoto(Token)
+ End If
+ End Sub
+ Private Overloads Sub DownloadData(ByVal Page As Integer, ByVal IsVideo As Boolean, ByVal Token As CancellationToken)
+ Dim URL$ = String.Empty
+ Try
+ Dim MaxPage% = -1
+ Dim Type As UTypes = IIf(IsVideo, UTypes.VideoPre, UTypes.Picture)
+ Dim mPages$ = IIf(IsVideo, "maxVideoPages", "maxPhotoPages")
+ Dim listNode$()
+ Dim m As UserMedia
+
+ If IsSavedPosts Then
+ URL = $"https://xhamster.com/my/favorites/{IIf(IsVideo, "videos", "photos-and-galleries")}{IIf(Page = 1, String.Empty, $"/{Page}")}"
+ listNode = If(IsVideo, {"favoriteVideoListComponent", "models"}, {"favoritesGalleriesAndPhotosCollection"})
+ Else
+ URL = $"https://xhamster.com/users/{Name}/{IIf(IsVideo, "videos", "photos")}{IIf(Page = 1, String.Empty, $"/{Page}")}"
+ listNode = {If(IsVideo, "userVideoCollection", "userGalleriesCollection")}
+ End If
+ ThrowAny(Token)
+
+ Dim r$ = Responser.GetResponse(URL)
+ If Not r.IsEmptyString Then r = RegexReplace(r, HtmlScript)
+ If Not r.IsEmptyString Then
+ Using j As EContainer = JsonDocument.Parse(r).XmlIfNothing
+ If j.Count > 0 Then
+ If Not MySettings.DomainsUpdated AndAlso j.Contains("trustURLs") Then _
+ MySettings.UpdateDomains(j("trustURLs").Select(Function(d) d(0).XmlIfNothingValue), False)
+
+ MaxPage = j.Value(mPages).FromXML(Of Integer)(-1)
+
+ With j(listNode)
+ If .ListExists Then
+ For Each e As EContainer In .Self
+ m = ExtractMedia(e, Type)
+ If Not m.URL.IsEmptyString Then
+ If m.File.IsEmptyString Then Continue For
+
+ If m.Post.Date.HasValue Then
+ Select Case CheckDatesLimit(m.Post.Date.Value, Nothing)
+ Case DateResult.Skip : Continue For
+ Case DateResult.Exit : Exit Sub
+ End Select
+ End If
+
+ If IsVideo AndAlso Not _TempPostsList.Contains(m.Post.ID) Then
+ _TempPostsList.Add(m.Post.ID)
+ _TempMediaList.ListAddValue(m, LNC)
+ ElseIf Not IsVideo Then
+ If DirectCast(m.Object, ExchObj).IsPhoto Then
+ If Not m.Post.ID.IsEmptyString AndAlso Not _TempPostsList.Contains(m.Post.ID) Then
+ _TempPostsList.Add(m.Post.ID)
+ _TempMediaList.ListAddValue(m, LNC)
+ End If
+ Else
+ _TempPhotoData.ListAddValue(m, LNC)
+ End If
+ Else
+ Exit Sub
+ End If
+ End If
+ Next
+ End If
+ End With
+ End If
+ End Using
+ End If
+
+ If MaxPage > 0 AndAlso Page < MaxPage Then DownloadData(Page + 1, IsVideo, Token)
+ Catch ex As Exception
+ ProcessException(ex, Token, $"data downloading error [{URL}]")
+ End Try
+ End Sub
+#End Region
+#Region "Reparse video, photo"
+ Protected Overrides Sub ReparseVideo(ByVal Token As CancellationToken)
+ Dim URL$ = String.Empty
+ Try
+ If _TempMediaList.Count > 0 AndAlso _TempMediaList.Exists(Function(tm) tm.Type = UTypes.VideoPre) Then
+ Dim m As UserMedia, m2 As UserMedia
+ For i% = _TempMediaList.Count - 1 To 0 Step -1
+ If _TempMediaList(i).Type = UTypes.VideoPre Then
+ m = _TempMediaList(i)
+ If Not m.URL_BASE.IsEmptyString Then
+ m2 = Nothing
+ If GetM3U8(m2, m.URL_BASE, Responser) Then
+ m2.URL_BASE = m.URL_BASE
+ _TempMediaList(i) = m2
+ Else
+ m.State = UserMedia.States.Missing
+ _TempMediaList(i) = m
+ End If
+ End If
+ End If
+ Next
+ End If
+ Catch ex As Exception
+ ProcessException(ex, Token, "video reparsing error", False)
+ End Try
+ End Sub
+ Private Overloads Sub ReparsePhoto(ByVal Token As CancellationToken)
+ If _TempPhotoData.Count > 0 Then
+ For i% = 0 To _TempPhotoData.Count - 1 : ReparsePhoto(i, 1, Token) : Next
+ _TempPhotoData.Clear()
+ End If
+ End Sub
+ Private Overloads Sub ReparsePhoto(ByVal Index As Integer, ByVal Page As Integer, ByVal Token As CancellationToken)
+ Dim URL$ = String.Empty
+ Try
+ Dim MaxPage% = -1
+ Dim m As UserMedia
+ Dim sm As UserMedia = _TempPhotoData(Index)
+
+ URL = $"{sm.URL}{IIf(Page = 1, String.Empty, $"/{Page}")}"
+ ThrowAny(Token)
+ Dim r$ = Responser.GetResponse(URL)
+ If Not r.IsEmptyString Then r = RegexReplace(r, HtmlScript)
+ If Not r.IsEmptyString Then
+ Using j As EContainer = JsonDocument.Parse(r).XmlIfNothing
+ If j.Count > 0 Then
+ MaxPage = j.Value({"pagination"}, "maxPage").FromXML(Of Integer)(-1)
+ With j({"photosGalleryModel"}, "photos")
+ If .ListExists Then
+ For Each e In .Self
+ m = ExtractMedia(e, UTypes.Picture, "imageURL", False, sm.Post.Date)
+ m.URL_BASE = sm.URL
+ If Not m.URL.IsEmptyString Then
+ m.Post.ID = $"{sm.Post.ID}_{m.Post.ID}"
+ m.SpecialFolder = sm.SpecialFolder
+ If Not _TempPostsList.Contains(m.Post.ID) Then
+ _TempPostsList.Add(m.Post.ID)
+ _TempMediaList.ListAddValue(m, LNC)
+ Else
+ Exit Sub
+ End If
+ End If
+ Next
+ End If
+ End With
+ End If
+ End Using
+ End If
+
+ If MaxPage > 0 AndAlso Page < MaxPage Then ReparsePhoto(Index, Page + 1, Token)
+ Catch ex As Exception
+ ProcessException(ex, Token, "photo reparsing error", False)
+ End Try
+ End Sub
+#End Region
+#Region "Reparse missing"
+ Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken)
+ Dim rList As New List(Of Integer)
+ Try
+ If ContentMissingExists Then
+ Dim m As UserMedia, m2 As UserMedia
+ For i% = 0 To _ContentList.Count - 1
+ m = _ContentList(i)
+ If m.State = UserMedia.States.Missing AndAlso Not m.URL_BASE.IsEmptyString Then
+ ThrowAny(Token)
+ m2 = Nothing
+ If GetM3U8(m2, m.URL_BASE, Responser) Then
+ m2.URL_BASE = m.URL_BASE
+ _TempMediaList.ListAddValue(m2, LNC)
+ rList.Add(i)
+ End If
+ End If
+ Next
+ End If
+ Catch ex As Exception
+ ProcessException(ex, Token, "missing data downloading error")
+ Finally
+ If rList.Count > 0 Then
+ For i% = rList.Count - 1 To 0 Step -1 : _ContentList.RemoveAt(rList(i)) : Next
+ rList.Clear()
+ End If
+ End Try
+ End Sub
+#End Region
+#Region "GetM3U8"
+ Private Overloads Function GetM3U8(ByRef m As UserMedia, ByVal URL As String, ByVal Responser As Response,
+ Optional ByVal e As ErrorsDescriber = Nothing) As Boolean
+ Try
+ If Not URL.IsEmptyString Then
+ Dim r$ = Responser.GetResponse(URL)
+ If Not r.IsEmptyString Then r = RegexReplace(r, HtmlScript)
+ If Not r.IsEmptyString Then
+ Using j As EContainer = JsonDocument.Parse(r)
+ If j.ListExists Then
+ m = ExtractMedia(j("videoModel"), UTypes.VideoPre)
+ m.URL_BASE = URL
+ Return GetM3U8(m, j)
+ End If
+ End Using
+ End If
+ End If
+ Return False
+ Catch ex As Exception
+ If Not e.Exists Then e = EDP.ReturnValue
+ Return ErrorsDescriber.Execute(e, ex, $"[{ToStringForLog()}]: API.Xhamster.GetM3U8({URL})", False)
+ End Try
+ End Function
+ Private Overloads Function GetM3U8(ByRef m As UserMedia, ByVal j As EContainer) As Boolean
+ Dim url$ = j.Value({"xplayerSettings", "sources", "hls"}, "url")
+ If Not url.IsEmptyString Then m.URL = url : m.Type = UTypes.m3u8 : Return True
+ Return False
+ End Function
+#End Region
+#Region "Standalone downloader"
+ Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal Responser As Response, ByVal Path As SFile) As UserMedia
+ Try
+ Using u As New UserData With {.Responser = Responser, .HOST = Settings(XhamsterSiteKey)}
+ Dim m As UserMedia = Nothing
+ If u.GetM3U8(m, URL, Responser, EDP.ThrowException) Then
+ m.File.Path = Path.Path
+ Dim f As SFile = u.DownloadM3U8(m.URL, m, m.File)
+ If Not f.IsEmptyString Then
+ m.File = f
+ m.State = UserMedia.States.Downloaded
+ Return m
+ End If
+ End If
+ End Using
+ Return Nothing
+ Catch ex As Exception
+ Return ErrorsDescriber.Execute(EDP.SendInLog + EDP.ReturnValue, ex, $"XHamster standalone download error: [{URL}]", New UserMedia)
+ End Try
+ End Function
+#End Region
+#Region "Download data"
+ Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
+ DownloadContentDefault(Token)
+ End Sub
+ Protected Overloads Overrides Function DownloadM3U8(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile) As SFile
+ Media.File = DestinationFile
+ Return M3U8.Download(Media, Responser, MySettings.DownloadUHD.Value)
+ End Function
+#End Region
+#Region "Create media"
+ Private Shared Function ExtractMedia(ByVal j As EContainer, ByVal t As UTypes, Optional ByVal UrlNode As String = "pageURL",
+ Optional ByVal DetectGalery As Boolean = True, Optional ByVal PostDate As Date? = Nothing) As UserMedia
+ If Not j Is Nothing Then
+ Dim m As New UserMedia(j.Value(UrlNode).Replace("\", String.Empty), t) With {
+ .Post = New UserPost With {
+ .ID = j.Value("id"),
+ .Date = AConvert(Of Date)(j.Value("created"), DateProvider, Nothing)
+ },
+ .PictureOption = j.Value("title").StringRemoveWinForbiddenSymbols,
+ .Object = New ExchObj
+ }
+ If PostDate.HasValue Then m.Post.Date = PostDate
+ Dim setSpecialFolder As Boolean = False
+ Dim processFile As Boolean = True
+ Dim ext$ = "mp4"
+ If t = UTypes.Picture Then
+ ext = "jpg"
+ If (Not DetectGalery OrElse j.Contains("galleryId")) AndAlso Not j.Value("imageURL").IsEmptyString Then
+ m.Object = New ExchObj With {.IsPhoto = True}
+ m.URL = j.Value("imageURL")
+ m.URL_BASE = m.URL
+ If DetectGalery Then m.Post.ID = $"{j.Value("galleryId")}_{m.Post.ID}"
+ m.File = m.URL
+ m.File.Separator = "\"
+ processFile = m.File.File.IsEmptyString
+ Else
+ setSpecialFolder = True
+ End If
+ End If
+ If Not m.URL.IsEmptyString Then
+ If m.Post.ID.IsEmptyString Then m.Post.ID = m.URL.Split("/").LastOrDefault
+ If m.PictureOption.IsEmptyString Then m.PictureOption = j.Value("titleLocalized").StringRemoveWinForbiddenSymbols
+ If m.PictureOption.IsEmptyString Then m.PictureOption = m.Post.ID
+ If setSpecialFolder Then m.SpecialFolder = m.PictureOption
+
+ If processFile Then
+ If Not m.PictureOption.IsEmptyString Then
+ m.File = $"{m.PictureOption}.{ext}"
+ ElseIf Not m.Post.ID.IsEmptyString Then
+ m.File = $"{m.Post.ID}.{ext}"
+ End If
+ End If
+ m.File.Separator = "\"
+ End If
+ Return m
+ Else
+ Return Nothing
+ End If
+ End Function
+#End Region
+#Region "Exception"
+ Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False,
+ Optional ByVal EObj As Object = Nothing) As Integer
+ Return If(Responser.Status = Net.WebExceptionStatus.ConnectionClosed, 1, 0)
+ End Function
+#End Region
+#Region "Idisposable support"
+ Protected Overrides Sub Dispose(ByVal disposing As Boolean)
+ If Not disposedValue And disposing Then _TempPhotoData.Clear()
+ MyBase.Dispose(disposing)
+ End Sub
+#End Region
+ End Class
+End Namespace
\ No newline at end of file
diff --git a/SCrawler/Channels/ChannelViewForm.Designer.vb b/SCrawler/Channels/ChannelViewForm.Designer.vb
index 998d071..7773134 100644
--- a/SCrawler/Channels/ChannelViewForm.Designer.vb
+++ b/SCrawler/Channels/ChannelViewForm.Designer.vb
@@ -140,24 +140,28 @@ Partial Friend Class ChannelViewForm : Inherits System.Windows.Forms.Form
'
'BTT_C_OPEN_USER
'
+ Me.BTT_C_OPEN_USER.Image = Global.SCrawler.My.Resources.Resources.GlobePic_32
Me.BTT_C_OPEN_USER.Name = "BTT_C_OPEN_USER"
Me.BTT_C_OPEN_USER.Size = New System.Drawing.Size(305, 22)
Me.BTT_C_OPEN_USER.Text = "Open user"
'
'BTT_C_OPEN_POST
'
+ Me.BTT_C_OPEN_POST.Image = Global.SCrawler.My.Resources.Resources.GlobePic_32
Me.BTT_C_OPEN_POST.Name = "BTT_C_OPEN_POST"
Me.BTT_C_OPEN_POST.Size = New System.Drawing.Size(305, 22)
Me.BTT_C_OPEN_POST.Text = "Open post"
'
'BTT_C_OPEN_PICTURE
'
+ Me.BTT_C_OPEN_PICTURE.Image = Global.SCrawler.My.Resources.Resources.PicturePic_32
Me.BTT_C_OPEN_PICTURE.Name = "BTT_C_OPEN_PICTURE"
Me.BTT_C_OPEN_PICTURE.Size = New System.Drawing.Size(305, 22)
Me.BTT_C_OPEN_PICTURE.Text = "Open picture"
'
'BTT_C_OPEN_FOLDER
'
+ Me.BTT_C_OPEN_FOLDER.Image = Global.SCrawler.My.Resources.Resources.FolderPic_32
Me.BTT_C_OPEN_FOLDER.Name = "BTT_C_OPEN_FOLDER"
Me.BTT_C_OPEN_FOLDER.Size = New System.Drawing.Size(305, 22)
Me.BTT_C_OPEN_FOLDER.Text = "Open folder"
@@ -165,6 +169,7 @@ Partial Friend Class ChannelViewForm : Inherits System.Windows.Forms.Form
'BTT_C_REMOVE_FROM_SELECTED
'
Me.BTT_C_REMOVE_FROM_SELECTED.AutoToolTip = True
+ Me.BTT_C_REMOVE_FROM_SELECTED.Image = Global.SCrawler.My.Resources.Resources.DeletePic_24
Me.BTT_C_REMOVE_FROM_SELECTED.Name = "BTT_C_REMOVE_FROM_SELECTED"
Me.BTT_C_REMOVE_FROM_SELECTED.Size = New System.Drawing.Size(305, 22)
Me.BTT_C_REMOVE_FROM_SELECTED.Text = "Remove user from selected"
@@ -172,6 +177,7 @@ Partial Friend Class ChannelViewForm : Inherits System.Windows.Forms.Form
'
'BTT_C_ADD_TO_BLACKLIST
'
+ Me.BTT_C_ADD_TO_BLACKLIST.Image = Global.SCrawler.My.Resources.Resources.DBPic_32
Me.BTT_C_ADD_TO_BLACKLIST.Name = "BTT_C_ADD_TO_BLACKLIST"
Me.BTT_C_ADD_TO_BLACKLIST.Size = New System.Drawing.Size(305, 22)
Me.BTT_C_ADD_TO_BLACKLIST.Text = "Add/Remove this user to/from the BlackList"
diff --git a/SCrawler/Channels/ChannelViewForm.vb b/SCrawler/Channels/ChannelViewForm.vb
index 2e8e866..ae93d47 100644
--- a/SCrawler/Channels/ChannelViewForm.vb
+++ b/SCrawler/Channels/ChannelViewForm.vb
@@ -581,7 +581,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits
End If
End If
End Sub
- Private Sub CMB_CHANNELS_ActionSelectedItemChanged(ByVal _Item As ListViewItem) Handles CMB_CHANNELS.ActionSelectedItemChanged
+ Private Sub CMB_CHANNELS_ActionSelectedItemChanged(ByVal Sender As Object, ByVal e As EventArgs, ByVal Item As ListViewItem) Handles CMB_CHANNELS.ActionSelectedItemChanged
SetLimitsByChannel()
Dim c As Channel = GetCurrentChannel()
If Not c Is Nothing Then MyRange.Source = c
@@ -814,6 +814,14 @@ Friend Class ChannelViewForm : Implements IChannelLimits
End Sub
#End Region
#Region "MyRange"
+ Private ReadOnly GetListImage_Error As New ErrorsDescriber(EDP.ReturnValue)
+ Private Function GetListImage(ByVal Post As UserPost, ByVal s As Size, ByVal NullArg As Image) As Image
+ If Not Post.CachedFile.IsEmptyString Then
+ Return If(ImageRenderer.GetImage(SFile.GetBytes(Post.CachedFile), s, GetListImage_Error), NullArg.Clone)
+ Else
+ Return NullArg.Clone
+ End If
+ End Function
Private Sub MyRange_IndexChanged(ByVal Sender As Object, ByVal e As EventArgs) Handles MyRange.IndexChanged
Try
If MyDefs.Initializing Then Exit Sub
@@ -825,11 +833,10 @@ Friend Class ChannelViewForm : Implements IChannelLimits
If .Count > 0 Then
Dim s As Size = GetImageSize()
Dim NullImage As Image = New Bitmap(s.Width, s.Height)
- Dim ie As New ErrorsDescriber(EDP.ReturnValue)
For i% = 0 To .Count - 1
p = .Item(i)
With p
- LIST_POSTS.LargeImageList.Images.Add(.GetImage(s, ie, NullImage))
+ LIST_POSTS.LargeImageList.Images.Add(GetListImage(p, s, NullImage))
LIST_POSTS.Items.Add(New ListViewItem(.UserID, i) With {.Tag = p.ID})
With LIST_POSTS.Items(LIST_POSTS.Items.Count - 1)
If PendingUsers.Contains(.Text) Then .Checked = True
diff --git a/SCrawler/Content/Icons/SiteIcons/PornHubIcon_16.ico b/SCrawler/Content/Icons/SiteIcons/PornHubIcon_16.ico
new file mode 100644
index 0000000..8834012
Binary files /dev/null and b/SCrawler/Content/Icons/SiteIcons/PornHubIcon_16.ico differ
diff --git a/SCrawler/Content/Icons/SiteIcons/XhamsterIcon_32.ico b/SCrawler/Content/Icons/SiteIcons/XhamsterIcon_32.ico
new file mode 100644
index 0000000..719a0f9
Binary files /dev/null and b/SCrawler/Content/Icons/SiteIcons/XhamsterIcon_32.ico differ
diff --git a/SCrawler/Content/Pictures/SitePictures/PornHubPic_16.png b/SCrawler/Content/Pictures/SitePictures/PornHubPic_16.png
new file mode 100644
index 0000000..667ba3f
Binary files /dev/null and b/SCrawler/Content/Pictures/SitePictures/PornHubPic_16.png differ
diff --git a/SCrawler/Content/Pictures/SitePictures/XhamsterPic_32.png b/SCrawler/Content/Pictures/SitePictures/XhamsterPic_32.png
new file mode 100644
index 0000000..ad36305
Binary files /dev/null and b/SCrawler/Content/Pictures/SitePictures/XhamsterPic_32.png differ
diff --git a/SCrawler/Download/ActiveDownloadingProgress.Designer.vb b/SCrawler/Download/ActiveDownloadingProgress.Designer.vb
index bb9e406..a2153a4 100644
--- a/SCrawler/Download/ActiveDownloadingProgress.Designer.vb
+++ b/SCrawler/Download/ActiveDownloadingProgress.Designer.vb
@@ -22,7 +22,6 @@ Namespace DownloadObjects
Private components As System.ComponentModel.IContainer
Private Sub InitializeComponent()
- Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(ActiveDownloadingProgress))
Me.TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
Me.SuspendLayout()
'
@@ -36,8 +35,8 @@ Namespace DownloadObjects
Me.TP_MAIN.Location = New System.Drawing.Point(0, 0)
Me.TP_MAIN.Name = "TP_MAIN"
Me.TP_MAIN.RowCount = 1
- Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 64.0!))
- Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 64.0!))
+ Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 66.0!))
+ Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 66.0!))
Me.TP_MAIN.Size = New System.Drawing.Size(434, 61)
Me.TP_MAIN.TabIndex = 0
'
@@ -47,12 +46,13 @@ Namespace DownloadObjects
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(434, 61)
Me.Controls.Add(Me.TP_MAIN)
- Me.Icon = Global.SCrawler.My.Resources.ArrowDownIcon_Blue_24
+ Me.Icon = Global.SCrawler.My.Resources.Resources.ArrowDownIcon_Blue_24
Me.KeyPreview = True
Me.MinimumSize = New System.Drawing.Size(450, 100)
Me.Name = "ActiveDownloadingProgress"
Me.Text = "Active downloading progress"
Me.ResumeLayout(False)
+
End Sub
Private WithEvents TP_MAIN As TableLayoutPanel
End Class
diff --git a/SCrawler/Download/ActiveDownloadingProgress.vb b/SCrawler/Download/ActiveDownloadingProgress.vb
index 48013b0..13e3f1f 100644
--- a/SCrawler/Download/ActiveDownloadingProgress.vb
+++ b/SCrawler/Download/ActiveDownloadingProgress.vb
@@ -42,6 +42,7 @@ Namespace DownloadObjects
End Sub
Private Sub Downloader_Reconfigured()
Const RowHeight% = 30
+ Const LowestValue% = 39
Dim a As Action = Sub()
With TP_MAIN
If .Controls.Count > 0 Then
@@ -65,13 +66,18 @@ Namespace DownloadObjects
.Controls.Add(JobsList.Last.Get, 0, .RowStyles.Count - 1)
End With
Next
- TP_MAIN.RowStyles.Add(New RowStyle(SizeType.Percent, 100))
+ TP_MAIN.RowStyles.Add(New RowStyle(SizeType.AutoSize))
TP_MAIN.RowCount += 1
+
+ Dim s As Size = Size
+ Dim ss As Size = Screen.PrimaryScreen.WorkingArea.Size
+ Dim c% = TP_MAIN.RowStyles.Count - 1
+ s.Height = c * RowHeight + LowestValue + (PaddingE.GetOf({TP_MAIN}).Vertical(c) / c).RoundDown - c
+ If s.Height > ss.Height Then s.Height = ss.Height
+ MinimumSize = Nothing
+ Size = s
+ MinimumSize = New Size(MinWidth, s.Height)
End If
- Dim s As Size = Size
- s.Height = TP_MAIN.RowStyles.Count * RowHeight + PaddingE.GetOf({TP_MAIN}).Vertical(TP_MAIN.RowStyles.Count) - TP_MAIN.RowStyles.Count * 2
- MinimumSize = New Size(MinWidth, s.Height)
- Size = s
End With
TP_MAIN.Refresh()
End Sub
diff --git a/SCrawler/Download/Automation/AutoDownloader.vb b/SCrawler/Download/Automation/AutoDownloader.vb
index bb250f4..c6b85e4 100644
--- a/SCrawler/Download/Automation/AutoDownloader.vb
+++ b/SCrawler/Download/Automation/AutoDownloader.vb
@@ -7,7 +7,6 @@
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports System.Threading
-Imports SCrawler.API
Imports SCrawler.API.Base
Imports SCrawler.DownloadObjects.Groups
Imports PersonalUtilities.Functions.XML
@@ -421,21 +420,32 @@ Namespace DownloadObjects
LastDownloadDate = LastDownloadDate.AddMinutes(Timer)
End If
End Sub
+ Private _SpecialDelayUse As Boolean = False
+ Private _SpecialDelayTime As Date? = Nothing
Private Sub Checker()
Try
Dim _StartDownload As Boolean
While (Not _StopRequested Or Downloader.Working) And Not Mode = Modes.None
If LastDownloadDate.AddMinutes(Timer) < Now And _StartTime.AddMinutes(StartupDelay) < Now And
- Not Downloader.Working And Not IsPaused And Not _StopRequested And Not Mode = Modes.None Then
- _StartDownload = False
- If Settings.Automation.Count = 1 Then
- _StartDownload = True
- ElseIf Index = -1 Then
- _StartDownload = True
+ Not IsPaused And Not _StopRequested And Not Mode = Modes.None Then
+ If Downloader.Working Then
+ _SpecialDelayUse = True
Else
- _StartDownload = NextExecutionDate.AddMilliseconds(1000 * (Index + 1)).Ticks <= Now.Ticks
+ If _SpecialDelayUse And Not _SpecialDelayTime.HasValue Then _SpecialDelayTime = Now.AddSeconds(10)
+ If Not _SpecialDelayUse OrElse (_SpecialDelayTime.HasValue AndAlso _SpecialDelayTime.Value < Now) Then
+ _SpecialDelayUse = False
+ _SpecialDelayTime = Nothing
+ _StartDownload = False
+ If Settings.Automation.Count = 1 Then
+ _StartDownload = True
+ ElseIf Index = -1 Then
+ _StartDownload = True
+ Else
+ _StartDownload = NextExecutionDate.AddMilliseconds(1000 * (Index + 1)).Ticks <= Now.Ticks
+ End If
+ If _StartDownload Then Download()
+ End If
End If
- If _StartDownload Then Download()
End If
Thread.Sleep(500)
End While
diff --git a/SCrawler/Download/Feed/DownloadFeedForm.vb b/SCrawler/Download/Feed/DownloadFeedForm.vb
index 99960e4..7689cdd 100644
--- a/SCrawler/Download/Feed/DownloadFeedForm.vb
+++ b/SCrawler/Download/Feed/DownloadFeedForm.vb
@@ -157,7 +157,7 @@ Namespace DownloadObjects
Using chooser As New SimpleListForm(Of SFile)(fList, Settings.Design) With {
.FormText = "Sessions",
.Icon = My.Resources.ArrowDownIcon_Blue_24,
- .Mode = SimpleListForm(Of SFile).Modes.CheckedItems,
+ .Mode = SimpleListFormModes.CheckedItems,
.Provider = New CustomProvider(Function(v, d, p, n, ee) DirectCast(v, SFile).File)
}
chooser.ClearButtons()
diff --git a/SCrawler/Download/Feed/FeedVideo.vb b/SCrawler/Download/Feed/FeedVideo.vb
index da815b2..102ac62 100644
--- a/SCrawler/Download/Feed/FeedVideo.vb
+++ b/SCrawler/Download/Feed/FeedVideo.vb
@@ -10,7 +10,7 @@ Imports LibVLCSharp
Imports System.Threading
Imports System.ComponentModel
Imports PersonalUtilities.Tools
-Imports PersonalUtilities.Tools.WEB
+Imports PersonalUtilities.Tools.Web
Imports VLCState = LibVLCSharp.Shared.VLCState
Namespace DownloadObjects
diff --git a/SCrawler/Download/Groups/DownloadGroup.vb b/SCrawler/Download/Groups/DownloadGroup.vb
index c384dc1..5dafc8f 100644
--- a/SCrawler/Download/Groups/DownloadGroup.vb
+++ b/SCrawler/Download/Groups/DownloadGroup.vb
@@ -6,7 +6,6 @@
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
-Imports SCrawler.API
Imports SCrawler.API.Base
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.XML.Base
diff --git a/SCrawler/Download/TDownloader.vb b/SCrawler/Download/TDownloader.vb
index afd7167..b33fe3e 100644
--- a/SCrawler/Download/TDownloader.vb
+++ b/SCrawler/Download/TDownloader.vb
@@ -138,6 +138,7 @@ Namespace DownloadObjects
Return If(Pool.Count = 0, 0, Pool.Sum(Function(j) j.Count))
End Get
End Property
+ Friend Property Suspended As Boolean = False
#End Region
#Region "Automation Support"
Private _AutoDownloaderTasks As Integer = 0
@@ -166,9 +167,10 @@ Namespace DownloadObjects
End Property
Friend ReadOnly Property Name As String
Get
- Return Hosts(0).Name
+ If Not GroupName.IsEmptyString Then Return GroupName Else Return Hosts(0).Name
End Get
End Property
+ Friend ReadOnly Property GroupName As String
Friend ReadOnly Property TaskCount As Integer
Get
Return Hosts(0).TaskCount
@@ -190,6 +192,10 @@ Namespace DownloadObjects
Keys = New List(Of String)
[Type] = JobType
End Sub
+ Friend Sub New(ByVal JobType As Download, ByVal GroupName As String)
+ Me.New(JobType)
+ Me.GroupName = GroupName
+ End Sub
Public Overloads Function Add(ByVal User As IUserData, ByVal _IncludedInTheFeed As Boolean) As Boolean
With DirectCast(User, UserDataBase)
If Keys.Count > 0 Then
@@ -274,6 +280,7 @@ Namespace DownloadObjects
#Region "Pool"
Friend Sub ReconfPool()
If Pool.Count = 0 OrElse Not Pool.Exists(Function(j) j.Working Or j.Count > 0) Then
+ Dim i%
Pool.ListClearDispose
If Settings.Plugins.Count > 0 Then
Pool.Add(New Job(Download.Main))
@@ -281,6 +288,15 @@ Namespace DownloadObjects
If p.Settings.IsSeparatedTasks Then
Pool.Add(New Job(Download.Main))
Pool.Last.AddHost(p.Settings)
+ ElseIf Not p.Settings.TaskGroupName.IsEmptyString Then
+ i = -1
+ If Pool.Count > 0 Then i = Pool.FindIndex(Function(pt) pt.GroupName = p.Settings.TaskGroupName)
+ If i >= 0 Then
+ Pool(i).AddHost(p.Settings)
+ Else
+ Pool.Add(New Job(Download.Main, p.Settings.TaskGroupName))
+ Pool.Last.AddHost(p.Settings)
+ End If
Else
Pool(0).AddHost(p.Settings)
End If
@@ -315,7 +331,7 @@ Namespace DownloadObjects
MyProgressForm.DisableProgressChange = False
Do While Pool.Exists(Function(p) p.Count > 0 Or p.Working)
For Each j As Job In Pool
- If j.Count > 0 And Not j.Working Then j.Start(New ThreadStart(Sub() StartDownloading(j)))
+ If j.Count > 0 And Not j.Working And Not Suspended Then j.Start(New ThreadStart(Sub() StartDownloading(j)))
Next
Thread.Sleep(200)
Loop
diff --git a/SCrawler/Download/WebClient2.vb b/SCrawler/Download/WebClient2.vb
new file mode 100644
index 0000000..b6ee96b
--- /dev/null
+++ b/SCrawler/Download/WebClient2.vb
@@ -0,0 +1,50 @@
+' Copyright (C) 2023 Andy https://github.com/AAndyProgram
+' This program is free software: you can redistribute it and/or modify
+' it under the terms of the GNU General Public License as published by
+' the Free Software Foundation, either version 3 of the License, or
+' (at your option) any later version.
+'
+' This program is distributed in the hope that it will be useful,
+' but WITHOUT ANY WARRANTY
+Imports System.Net
+Imports PersonalUtilities.Tools.Web.Clients
+Namespace DownloadObjects
+ Friend Class WebClient2 : Implements IDisposable
+ Protected WC As WebClient
+ Protected RC As Response
+ Private ReadOnly RCERROR As New ErrorsDescriber(EDP.ThrowException)
+ Protected UseResponserClient As Boolean
+ Friend Sub New()
+ End Sub
+ Friend Sub New(ByVal Responser As Response)
+ If Not Responser Is Nothing Then
+ RC = Responser
+ UseResponserClient = True
+ Else
+ WC = New WebClient
+ End If
+ End Sub
+ Friend Sub DownloadFile(ByVal URL As String, ByVal File As String)
+ If UseResponserClient Then
+ RC.DownloadFile(URL, File, RCERROR)
+ Else
+ WC.DownloadFile(URL, File)
+ End If
+ End Sub
+#Region "IDisposable Support"
+ Private disposedValue As Boolean = False
+ Protected Overridable Sub Dispose(ByVal disposing As Boolean)
+ If Not disposedValue And disposing And Not WC Is Nothing Then WC.Dispose()
+ disposedValue = True
+ End Sub
+ Protected Overrides Sub Finalize()
+ Dispose(False)
+ MyBase.Finalize()
+ End Sub
+ Friend Sub Dispose() Implements IDisposable.Dispose
+ Dispose(True)
+ GC.SuppressFinalize(Me)
+ End Sub
+#End Region
+ End Class
+End Namespace
\ No newline at end of file
diff --git a/SCrawler/Editors/CollectionEditorForm.vb b/SCrawler/Editors/CollectionEditorForm.vb
index 85c2bf5..cbe0d35 100644
--- a/SCrawler/Editors/CollectionEditorForm.vb
+++ b/SCrawler/Editors/CollectionEditorForm.vb
@@ -24,8 +24,9 @@ Namespace Editors
.MyViewInitialize()
.AddOkCancelToolbar()
Collections.ListAddList(Settings.LastCollections)
- Collections.ListAddList((From c In Settings.Users Where c.IsCollection Select c.CollectionName), LAP.NotContainsOnly, EDP.ThrowException)
- If Collections.ListExists Then Collections.Sort() : CMB_COLLECTIONS.Items.AddRange(From c In Collections Select New ListItem(c))
+ Dim ecol As List(Of String) = ListAddList(Nothing, (From c In Settings.Users Where c.IsCollection Select c.CollectionName), LAP.NotContainsOnly)
+ If ecol.ListExists Then ecol.Sort() : Collections.ListAddList(ecol, LAP.NotContainsOnly) : ecol.Clear()
+ If Collections.Count > 0 Then CMB_COLLECTIONS.Items.AddRange(Collections.Select(Function(c) New ListItem(c)))
If Not Collection.IsEmptyString And Collections.Contains(Collection) Then CMB_COLLECTIONS.SelectedIndex = Collections.IndexOf(Collection)
.DelegateClosingChecker = False
.EndLoaderOperations()
@@ -55,8 +56,8 @@ Namespace Editors
Private Sub CMB_COLLECTIONS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles CMB_COLLECTIONS.ActionOnButtonClick
If Sender.DefaultButton = ActionButton.DefaultButtons.Add Then AddNewCollection()
End Sub
- Private Sub CMB_COLLECTIONS_ActionOnListDoubleClick(ByVal _Item As ListViewItem) Handles CMB_COLLECTIONS.ActionOnListDoubleClick
- _Item.Selected = True
+ Private Sub CMB_COLLECTIONS_ActionOnListDoubleClick(ByVal Sender As Object, ByVal e As EventArgs, ByVal Item As ListViewItem) Handles CMB_COLLECTIONS.ActionOnListDoubleClick
+ Item.Selected = True
MyDefs_ButtonOkClick()
End Sub
Private Sub AddNewCollection()
diff --git a/SCrawler/Editors/GlobalSettingsForm.vb b/SCrawler/Editors/GlobalSettingsForm.vb
index 1f1f733..7d1e797 100644
--- a/SCrawler/Editors/GlobalSettingsForm.vb
+++ b/SCrawler/Editors/GlobalSettingsForm.vb
@@ -221,7 +221,7 @@ Namespace Editors
End Sub
Private Sub TXT_GLOBAL_PATH_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles TXT_GLOBAL_PATH.ActionOnButtonClick
If Sender.DefaultButton = ADB.Open Then
- Dim f As SFile = SFile.SelectPath(Settings.GlobalPath.Value)
+ Dim f As SFile = SFile.SelectPath(Settings.GlobalPath.Value).IfNullOrEmpty(Settings.GlobalPath.Value)
If Not f.IsEmptyString Then TXT_GLOBAL_PATH.Text = f
End If
End Sub
diff --git a/SCrawler/Editors/LabelsForm.vb b/SCrawler/Editors/LabelsForm.vb
index f74c65b..81eebdd 100644
--- a/SCrawler/Editors/LabelsForm.vb
+++ b/SCrawler/Editors/LabelsForm.vb
@@ -9,7 +9,6 @@
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Controls
Imports PersonalUtilities.Forms.Controls.Base
-Imports PersonalUtilities.Functions.Messaging
Friend Class LabelsForm
Private WithEvents MyDefs As DefaultFormOptions
Friend ReadOnly Property LabelsList As List(Of String)
@@ -26,8 +25,6 @@ Friend Class LabelsForm
End Get
End Property
Private _AnyLabelAdd As Boolean = False
- Friend Property MultiUser As Boolean = False
- Friend Property MultiUserClearExists As Boolean = False
Friend Property WithDeleteButton As Boolean = False
Private ReadOnly AddNoParsed As Boolean = False
Friend Sub New(ByVal LabelsArr As IEnumerable(Of String), Optional ByVal AddNoParsed As Boolean = False)
@@ -47,12 +44,14 @@ Friend Class LabelsForm
.MyViewInitialize()
.AddOkCancelToolbar()
.MyOkCancel.BTT_DELETE.Visible = WithDeleteButton
- If Source.Count > 0 Then
+ Dim s As List(Of String) = ListAddList(Nothing, Source).ListAddList(LabelsList, LAP.NotContainsOnly)
+ If s.ListExists Then
Dim items As New List(Of Integer)
+ s.Sort()
CMB_LABELS.BeginUpdate()
- For i% = 0 To Source.Count - 1
- If LabelsList.Contains(Source(i)) Then items.Add(i)
- CMB_LABELS.Items.Add(Source(i))
+ For i% = 0 To s.Count - 1
+ If LabelsList.Contains(s(i)) Then items.Add(i)
+ CMB_LABELS.Items.Add(s(i))
Next
If Not _Source Is Nothing Then CMB_LABELS.Buttons.Clear()
CMB_LABELS.EndUpdate()
@@ -72,24 +71,11 @@ Friend Class LabelsForm
End Sub
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
Try
- If MultiUser Then
- Dim m As New MMessage("You are changing labels for more one user" & vbNewLine & "What do you want to do?",
- "MultiUser labels changing",
- {New MsgBoxButton("Replace exists") With {.ToolTip = "Per user: all existing labels will be removed and replaced with these labels"},
- New MsgBoxButton("Add to exists") With {.ToolTip = "Per user: these labels will be add to existing labels"},
- New MsgBoxButton("Cancel")},
- MsgBoxStyle.Exclamation)
- Select Case MsgBoxE(m).Index
- Case 0 : MultiUserClearExists = True
- Case 1 : MultiUserClearExists = False
- Case 2 : Exit Sub
- End Select
- End If
LabelsList.ListAddList(CMB_LABELS.Items.CheckedItems.Select(Function(l) CStr(l.Value(0))), LAP.ClearBeforeAdd, LAP.NotContainsOnly)
If _AnyLabelAdd And _Source Is Nothing Then Settings.Labels.Update()
MyDefs.CloseForm()
Catch ex As Exception
- ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Choosing labels")
+ ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Label selection")
End Try
End Sub
Private Sub MyDefs_ButtonDeleteClickOC(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonDeleteClickOC
diff --git a/SCrawler/Editors/SiteEditorForm.vb b/SCrawler/Editors/SiteEditorForm.vb
index 2d2f8fa..bdc31c7 100644
--- a/SCrawler/Editors/SiteEditorForm.vb
+++ b/SCrawler/Editors/SiteEditorForm.vb
@@ -11,8 +11,8 @@ Imports SCrawler.Plugin.Hosts
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Controls
Imports PersonalUtilities.Forms.Controls.Base
-Imports PersonalUtilities.Tools.WEB
-Imports CookieControl = PersonalUtilities.Tools.WEB.CookieListForm.CookieControl
+Imports PersonalUtilities.Tools.Web.Cookies
+Imports CookieControl = PersonalUtilities.Tools.Web.Cookies.CookieListForm.CookieControl
Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons
Namespace Editors
Friend Class SiteEditorForm
@@ -205,7 +205,7 @@ Namespace Editors
End Sub
Private Sub ChangePath(ByVal Sender As ActionButton, ByVal PathValue As SFile, ByRef CNT As TextBoxExtended)
If Sender.DefaultButton = ADB.Open Then
- Dim f As SFile = SFile.SelectPath(PathValue)
+ Dim f As SFile = SFile.SelectPath(PathValue).IfNullOrEmpty(PathValue)
If Not f.IsEmptyString Then CNT.Text = f
End If
End Sub
diff --git a/SCrawler/Editors/UserCreatorForm.Designer.vb b/SCrawler/Editors/UserCreatorForm.Designer.vb
index 471e424..bc6d10e 100644
--- a/SCrawler/Editors/UserCreatorForm.Designer.vb
+++ b/SCrawler/Editors/UserCreatorForm.Designer.vb
@@ -23,99 +23,147 @@ Namespace Editors
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container()
- Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
- Dim TP_SITE As System.Windows.Forms.TableLayoutPanel
+ Dim TT_MAIN As System.Windows.Forms.ToolTip
+ Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(UserCreatorForm))
Dim ListColumn1 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
Dim ListColumn2 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
- Dim TP_PARAMS As System.Windows.Forms.TableLayoutPanel
- Dim TP_OTHER As System.Windows.Forms.TableLayoutPanel
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton3 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton4 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
- Dim TP_DOWN_OPTIONS As System.Windows.Forms.TableLayoutPanel
Dim ActionButton5 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton6 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton7 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton8 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
- Dim TT_MAIN As System.Windows.Forms.ToolTip
- Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
- Me.TXT_USER = New PersonalUtilities.Forms.Controls.TextBoxExtended()
- Me.CH_IS_CHANNEL = New System.Windows.Forms.CheckBox()
- Me.CMB_SITE = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
- Me.BTT_OTHER_SETTINGS = New System.Windows.Forms.Button()
- Me.CH_TEMP = New System.Windows.Forms.CheckBox()
- Me.CH_FAV = New System.Windows.Forms.CheckBox()
Me.CH_PARSE_USER_MEDIA = New System.Windows.Forms.CheckBox()
Me.CH_READY_FOR_DOWN = New System.Windows.Forms.CheckBox()
+ Me.BTT_OTHER_SETTINGS = New System.Windows.Forms.Button()
+ Me.TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
+ Me.TXT_USER = New PersonalUtilities.Forms.Controls.TextBoxExtended()
+ Me.TP_SITE = New System.Windows.Forms.TableLayoutPanel()
+ Me.CH_IS_CHANNEL = New System.Windows.Forms.CheckBox()
+ Me.CMB_SITE = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
+ Me.TP_TEMP_FAV = New System.Windows.Forms.TableLayoutPanel()
+ Me.CH_TEMP = New System.Windows.Forms.CheckBox()
+ Me.CH_FAV = New System.Windows.Forms.CheckBox()
+ Me.TP_READY_USERMEDIA = New System.Windows.Forms.TableLayoutPanel()
Me.TXT_DESCR = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_USER_FRIENDLY = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TP_ADD_BY_LIST = New System.Windows.Forms.TableLayoutPanel()
Me.CH_ADD_BY_LIST = New System.Windows.Forms.CheckBox()
Me.CH_AUTO_DETECT_SITE = New System.Windows.Forms.CheckBox()
Me.TXT_LABELS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
+ Me.TP_DOWN_IMG_VID = New System.Windows.Forms.TableLayoutPanel()
Me.CH_DOWN_IMAGES = New System.Windows.Forms.CheckBox()
Me.CH_DOWN_VIDEOS = New System.Windows.Forms.CheckBox()
Me.TXT_SPEC_FOLDER = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_SCRIPT = New PersonalUtilities.Forms.Controls.TextBoxExtended()
- TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
- TP_SITE = New System.Windows.Forms.TableLayoutPanel()
- TP_PARAMS = New System.Windows.Forms.TableLayoutPanel()
- TP_OTHER = New System.Windows.Forms.TableLayoutPanel()
- TP_DOWN_OPTIONS = New System.Windows.Forms.TableLayoutPanel()
TT_MAIN = New System.Windows.Forms.ToolTip(Me.components)
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
- TP_MAIN.SuspendLayout()
+ CONTAINER_MAIN.ContentPanel.SuspendLayout()
+ CONTAINER_MAIN.SuspendLayout()
+ Me.TP_MAIN.SuspendLayout()
CType(Me.TXT_USER, System.ComponentModel.ISupportInitialize).BeginInit()
- TP_SITE.SuspendLayout()
+ Me.TP_SITE.SuspendLayout()
CType(Me.CMB_SITE, System.ComponentModel.ISupportInitialize).BeginInit()
- TP_PARAMS.SuspendLayout()
- TP_OTHER.SuspendLayout()
+ Me.TP_TEMP_FAV.SuspendLayout()
+ Me.TP_READY_USERMEDIA.SuspendLayout()
CType(Me.TXT_DESCR, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_USER_FRIENDLY, System.ComponentModel.ISupportInitialize).BeginInit()
Me.TP_ADD_BY_LIST.SuspendLayout()
CType(Me.TXT_LABELS, System.ComponentModel.ISupportInitialize).BeginInit()
- TP_DOWN_OPTIONS.SuspendLayout()
+ Me.TP_DOWN_IMG_VID.SuspendLayout()
CType(Me.TXT_SPEC_FOLDER, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_SCRIPT, System.ComponentModel.ISupportInitialize).BeginInit()
- CONTAINER_MAIN.ContentPanel.SuspendLayout()
- CONTAINER_MAIN.SuspendLayout()
Me.SuspendLayout()
'
+ 'CH_PARSE_USER_MEDIA
+ '
+ Me.CH_PARSE_USER_MEDIA.AutoSize = True
+ Me.CH_PARSE_USER_MEDIA.Dock = System.Windows.Forms.DockStyle.Fill
+ Me.CH_PARSE_USER_MEDIA.Location = New System.Drawing.Point(229, 4)
+ Me.CH_PARSE_USER_MEDIA.Name = "CH_PARSE_USER_MEDIA"
+ Me.CH_PARSE_USER_MEDIA.Size = New System.Drawing.Size(219, 20)
+ Me.CH_PARSE_USER_MEDIA.TabIndex = 0
+ Me.CH_PARSE_USER_MEDIA.Text = "Get user media only"
+ TT_MAIN.SetToolTip(Me.CH_PARSE_USER_MEDIA, "For twitter only!" & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "If checked then user media only will be downloaded." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Otherwise" &
+ " all media (include comments and retwits) will be downloaded.")
+ Me.CH_PARSE_USER_MEDIA.UseVisualStyleBackColor = True
+ '
+ 'CH_READY_FOR_DOWN
+ '
+ Me.CH_READY_FOR_DOWN.AutoSize = True
+ Me.CH_READY_FOR_DOWN.Dock = System.Windows.Forms.DockStyle.Fill
+ Me.CH_READY_FOR_DOWN.Location = New System.Drawing.Point(4, 4)
+ Me.CH_READY_FOR_DOWN.Name = "CH_READY_FOR_DOWN"
+ Me.CH_READY_FOR_DOWN.Size = New System.Drawing.Size(218, 20)
+ Me.CH_READY_FOR_DOWN.TabIndex = 1
+ Me.CH_READY_FOR_DOWN.Text = "Ready for download"
+ TT_MAIN.SetToolTip(Me.CH_READY_FOR_DOWN, "Can be downloaded by [Download All]")
+ Me.CH_READY_FOR_DOWN.UseVisualStyleBackColor = True
+ '
+ 'BTT_OTHER_SETTINGS
+ '
+ Me.BTT_OTHER_SETTINGS.Dock = System.Windows.Forms.DockStyle.Fill
+ Me.BTT_OTHER_SETTINGS.Location = New System.Drawing.Point(330, 2)
+ Me.BTT_OTHER_SETTINGS.Margin = New System.Windows.Forms.Padding(1)
+ Me.BTT_OTHER_SETTINGS.Name = "BTT_OTHER_SETTINGS"
+ Me.BTT_OTHER_SETTINGS.Size = New System.Drawing.Size(120, 24)
+ Me.BTT_OTHER_SETTINGS.TabIndex = 2
+ Me.BTT_OTHER_SETTINGS.Text = "Options (F2)"
+ TT_MAIN.SetToolTip(Me.BTT_OTHER_SETTINGS, "Other settings")
+ Me.BTT_OTHER_SETTINGS.UseVisualStyleBackColor = True
+ '
+ 'CONTAINER_MAIN
+ '
+ '
+ 'CONTAINER_MAIN.ContentPanel
+ '
+ CONTAINER_MAIN.ContentPanel.Controls.Add(Me.TP_MAIN)
+ CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(454, 436)
+ CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
+ CONTAINER_MAIN.LeftToolStripPanelVisible = False
+ CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
+ CONTAINER_MAIN.Name = "CONTAINER_MAIN"
+ CONTAINER_MAIN.RightToolStripPanelVisible = False
+ CONTAINER_MAIN.Size = New System.Drawing.Size(454, 461)
+ CONTAINER_MAIN.TabIndex = 0
+ CONTAINER_MAIN.TopToolStripPanelVisible = False
+ '
'TP_MAIN
'
- TP_MAIN.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
- TP_MAIN.ColumnCount = 1
- TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
- TP_MAIN.Controls.Add(Me.TXT_USER, 0, 0)
- TP_MAIN.Controls.Add(TP_SITE, 0, 3)
- TP_MAIN.Controls.Add(TP_PARAMS, 0, 4)
- TP_MAIN.Controls.Add(TP_OTHER, 0, 6)
- TP_MAIN.Controls.Add(Me.TXT_DESCR, 0, 10)
- TP_MAIN.Controls.Add(Me.TXT_USER_FRIENDLY, 0, 1)
- TP_MAIN.Controls.Add(Me.TP_ADD_BY_LIST, 0, 7)
- TP_MAIN.Controls.Add(Me.TXT_LABELS, 0, 8)
- TP_MAIN.Controls.Add(TP_DOWN_OPTIONS, 0, 5)
- TP_MAIN.Controls.Add(Me.TXT_SPEC_FOLDER, 0, 2)
- TP_MAIN.Controls.Add(Me.TXT_SCRIPT, 0, 9)
- TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
- TP_MAIN.Location = New System.Drawing.Point(0, 0)
- TP_MAIN.Name = "TP_MAIN"
- TP_MAIN.RowCount = 11
- TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
- TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
- TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
- TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
- TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
- TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
- TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
- TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
- TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26.0!))
- TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26.0!))
- TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
- TP_MAIN.Size = New System.Drawing.Size(454, 461)
- TP_MAIN.TabIndex = 0
+ Me.TP_MAIN.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
+ Me.TP_MAIN.ColumnCount = 1
+ Me.TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
+ Me.TP_MAIN.Controls.Add(Me.TXT_USER, 0, 0)
+ Me.TP_MAIN.Controls.Add(Me.TP_SITE, 0, 3)
+ Me.TP_MAIN.Controls.Add(Me.TP_TEMP_FAV, 0, 4)
+ Me.TP_MAIN.Controls.Add(Me.TP_READY_USERMEDIA, 0, 6)
+ Me.TP_MAIN.Controls.Add(Me.TXT_DESCR, 0, 10)
+ Me.TP_MAIN.Controls.Add(Me.TXT_USER_FRIENDLY, 0, 1)
+ Me.TP_MAIN.Controls.Add(Me.TP_ADD_BY_LIST, 0, 7)
+ Me.TP_MAIN.Controls.Add(Me.TXT_LABELS, 0, 8)
+ Me.TP_MAIN.Controls.Add(Me.TP_DOWN_IMG_VID, 0, 5)
+ Me.TP_MAIN.Controls.Add(Me.TXT_SPEC_FOLDER, 0, 2)
+ Me.TP_MAIN.Controls.Add(Me.TXT_SCRIPT, 0, 9)
+ Me.TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
+ Me.TP_MAIN.Location = New System.Drawing.Point(0, 0)
+ Me.TP_MAIN.Name = "TP_MAIN"
+ Me.TP_MAIN.RowCount = 11
+ Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
+ Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
+ Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
+ Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
+ Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
+ Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
+ Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
+ Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
+ Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26.0!))
+ Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26.0!))
+ Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
+ Me.TP_MAIN.Size = New System.Drawing.Size(454, 436)
+ Me.TP_MAIN.TabIndex = 0
'
'TXT_USER
'
@@ -130,22 +178,22 @@ Namespace Editors
'
'TP_SITE
'
- TP_SITE.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
- TP_SITE.ColumnCount = 3
- TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 79.0!))
- TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
- TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 104.0!))
- TP_SITE.Controls.Add(Me.CH_IS_CHANNEL, 0, 0)
- TP_SITE.Controls.Add(Me.CMB_SITE, 1, 0)
- TP_SITE.Controls.Add(Me.BTT_OTHER_SETTINGS, 2, 0)
- TP_SITE.Dock = System.Windows.Forms.DockStyle.Fill
- TP_SITE.Location = New System.Drawing.Point(1, 88)
- TP_SITE.Margin = New System.Windows.Forms.Padding(0)
- TP_SITE.Name = "TP_SITE"
- TP_SITE.RowCount = 1
- TP_SITE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
- TP_SITE.Size = New System.Drawing.Size(452, 28)
- TP_SITE.TabIndex = 3
+ Me.TP_SITE.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
+ Me.TP_SITE.ColumnCount = 3
+ Me.TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 79.0!))
+ Me.TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
+ Me.TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 122.0!))
+ Me.TP_SITE.Controls.Add(Me.CH_IS_CHANNEL, 0, 0)
+ Me.TP_SITE.Controls.Add(Me.CMB_SITE, 1, 0)
+ Me.TP_SITE.Controls.Add(Me.BTT_OTHER_SETTINGS, 2, 0)
+ Me.TP_SITE.Dock = System.Windows.Forms.DockStyle.Fill
+ Me.TP_SITE.Location = New System.Drawing.Point(1, 88)
+ Me.TP_SITE.Margin = New System.Windows.Forms.Padding(0)
+ Me.TP_SITE.Name = "TP_SITE"
+ Me.TP_SITE.RowCount = 1
+ Me.TP_SITE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
+ Me.TP_SITE.Size = New System.Drawing.Size(452, 28)
+ Me.TP_SITE.TabIndex = 3
'
'CH_IS_CHANNEL
'
@@ -177,39 +225,27 @@ Namespace Editors
Me.CMB_SITE.Location = New System.Drawing.Point(84, 3)
Me.CMB_SITE.Margin = New System.Windows.Forms.Padding(3, 2, 3, 3)
Me.CMB_SITE.Name = "CMB_SITE"
- Me.CMB_SITE.Size = New System.Drawing.Size(259, 22)
+ Me.CMB_SITE.Size = New System.Drawing.Size(241, 22)
Me.CMB_SITE.TabIndex = 1
Me.CMB_SITE.TextBoxBorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
'
- 'BTT_OTHER_SETTINGS
+ 'TP_TEMP_FAV
'
- Me.BTT_OTHER_SETTINGS.Dock = System.Windows.Forms.DockStyle.Fill
- Me.BTT_OTHER_SETTINGS.Location = New System.Drawing.Point(348, 2)
- Me.BTT_OTHER_SETTINGS.Margin = New System.Windows.Forms.Padding(1)
- Me.BTT_OTHER_SETTINGS.Name = "BTT_OTHER_SETTINGS"
- Me.BTT_OTHER_SETTINGS.Size = New System.Drawing.Size(102, 24)
- Me.BTT_OTHER_SETTINGS.TabIndex = 2
- Me.BTT_OTHER_SETTINGS.Text = "Options (F2)"
- TT_MAIN.SetToolTip(Me.BTT_OTHER_SETTINGS, "Other settings")
- Me.BTT_OTHER_SETTINGS.UseVisualStyleBackColor = True
- '
- 'TP_PARAMS
- '
- TP_PARAMS.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
- TP_PARAMS.ColumnCount = 2
- TP_PARAMS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
- TP_PARAMS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
- TP_PARAMS.Controls.Add(Me.CH_TEMP, 0, 0)
- TP_PARAMS.Controls.Add(Me.CH_FAV, 1, 0)
- TP_PARAMS.Dock = System.Windows.Forms.DockStyle.Fill
- TP_PARAMS.Location = New System.Drawing.Point(1, 117)
- TP_PARAMS.Margin = New System.Windows.Forms.Padding(0)
- TP_PARAMS.Name = "TP_PARAMS"
- TP_PARAMS.RowCount = 1
- TP_PARAMS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
- TP_PARAMS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 27.0!))
- TP_PARAMS.Size = New System.Drawing.Size(452, 28)
- TP_PARAMS.TabIndex = 4
+ Me.TP_TEMP_FAV.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
+ Me.TP_TEMP_FAV.ColumnCount = 2
+ Me.TP_TEMP_FAV.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
+ Me.TP_TEMP_FAV.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
+ Me.TP_TEMP_FAV.Controls.Add(Me.CH_TEMP, 0, 0)
+ Me.TP_TEMP_FAV.Controls.Add(Me.CH_FAV, 1, 0)
+ Me.TP_TEMP_FAV.Dock = System.Windows.Forms.DockStyle.Fill
+ Me.TP_TEMP_FAV.Location = New System.Drawing.Point(1, 117)
+ Me.TP_TEMP_FAV.Margin = New System.Windows.Forms.Padding(0)
+ Me.TP_TEMP_FAV.Name = "TP_TEMP_FAV"
+ Me.TP_TEMP_FAV.RowCount = 1
+ Me.TP_TEMP_FAV.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
+ Me.TP_TEMP_FAV.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 27.0!))
+ Me.TP_TEMP_FAV.Size = New System.Drawing.Size(452, 28)
+ Me.TP_TEMP_FAV.TabIndex = 4
'
'CH_TEMP
'
@@ -233,48 +269,23 @@ Namespace Editors
Me.CH_FAV.Text = "Favorite"
Me.CH_FAV.UseVisualStyleBackColor = True
'
- 'TP_OTHER
+ 'TP_READY_USERMEDIA
'
- TP_OTHER.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
- TP_OTHER.ColumnCount = 2
- TP_OTHER.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
- TP_OTHER.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
- TP_OTHER.Controls.Add(Me.CH_PARSE_USER_MEDIA, 1, 0)
- TP_OTHER.Controls.Add(Me.CH_READY_FOR_DOWN, 0, 0)
- TP_OTHER.Dock = System.Windows.Forms.DockStyle.Fill
- TP_OTHER.Location = New System.Drawing.Point(1, 175)
- TP_OTHER.Margin = New System.Windows.Forms.Padding(0)
- TP_OTHER.Name = "TP_OTHER"
- TP_OTHER.RowCount = 1
- TP_OTHER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
- TP_OTHER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 27.0!))
- TP_OTHER.Size = New System.Drawing.Size(452, 28)
- TP_OTHER.TabIndex = 6
- '
- 'CH_PARSE_USER_MEDIA
- '
- Me.CH_PARSE_USER_MEDIA.AutoSize = True
- Me.CH_PARSE_USER_MEDIA.Dock = System.Windows.Forms.DockStyle.Fill
- Me.CH_PARSE_USER_MEDIA.Location = New System.Drawing.Point(229, 4)
- Me.CH_PARSE_USER_MEDIA.Name = "CH_PARSE_USER_MEDIA"
- Me.CH_PARSE_USER_MEDIA.Size = New System.Drawing.Size(219, 20)
- Me.CH_PARSE_USER_MEDIA.TabIndex = 0
- Me.CH_PARSE_USER_MEDIA.Text = "Get user media only"
- TT_MAIN.SetToolTip(Me.CH_PARSE_USER_MEDIA, "For twitter only!" & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "If checked then user media only will be downloaded." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Otherwise" &
- " all media (include comments and retwits) will be downloaded.")
- Me.CH_PARSE_USER_MEDIA.UseVisualStyleBackColor = True
- '
- 'CH_READY_FOR_DOWN
- '
- Me.CH_READY_FOR_DOWN.AutoSize = True
- Me.CH_READY_FOR_DOWN.Dock = System.Windows.Forms.DockStyle.Fill
- Me.CH_READY_FOR_DOWN.Location = New System.Drawing.Point(4, 4)
- Me.CH_READY_FOR_DOWN.Name = "CH_READY_FOR_DOWN"
- Me.CH_READY_FOR_DOWN.Size = New System.Drawing.Size(218, 20)
- Me.CH_READY_FOR_DOWN.TabIndex = 1
- Me.CH_READY_FOR_DOWN.Text = "Ready for download"
- TT_MAIN.SetToolTip(Me.CH_READY_FOR_DOWN, "Can be downloaded by [Download All]")
- Me.CH_READY_FOR_DOWN.UseVisualStyleBackColor = True
+ Me.TP_READY_USERMEDIA.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
+ Me.TP_READY_USERMEDIA.ColumnCount = 2
+ Me.TP_READY_USERMEDIA.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
+ Me.TP_READY_USERMEDIA.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
+ Me.TP_READY_USERMEDIA.Controls.Add(Me.CH_PARSE_USER_MEDIA, 1, 0)
+ Me.TP_READY_USERMEDIA.Controls.Add(Me.CH_READY_FOR_DOWN, 0, 0)
+ Me.TP_READY_USERMEDIA.Dock = System.Windows.Forms.DockStyle.Fill
+ Me.TP_READY_USERMEDIA.Location = New System.Drawing.Point(1, 175)
+ Me.TP_READY_USERMEDIA.Margin = New System.Windows.Forms.Padding(0)
+ Me.TP_READY_USERMEDIA.Name = "TP_READY_USERMEDIA"
+ Me.TP_READY_USERMEDIA.RowCount = 1
+ Me.TP_READY_USERMEDIA.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
+ Me.TP_READY_USERMEDIA.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 27.0!))
+ Me.TP_READY_USERMEDIA.Size = New System.Drawing.Size(452, 28)
+ Me.TP_READY_USERMEDIA.TabIndex = 6
'
'TXT_DESCR
'
@@ -291,7 +302,7 @@ Namespace Editors
Me.TXT_DESCR.Location = New System.Drawing.Point(4, 290)
Me.TXT_DESCR.Multiline = True
Me.TXT_DESCR.Name = "TXT_DESCR"
- Me.TXT_DESCR.Size = New System.Drawing.Size(446, 167)
+ Me.TXT_DESCR.Size = New System.Drawing.Size(446, 142)
Me.TXT_DESCR.TabIndex = 10
'
'TXT_USER_FRIENDLY
@@ -361,23 +372,23 @@ Namespace Editors
Me.TXT_LABELS.TabIndex = 8
Me.TXT_LABELS.TextBoxReadOnly = True
'
- 'TP_DOWN_OPTIONS
+ 'TP_DOWN_IMG_VID
'
- TP_DOWN_OPTIONS.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
- TP_DOWN_OPTIONS.ColumnCount = 2
- TP_DOWN_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
- TP_DOWN_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
- TP_DOWN_OPTIONS.Controls.Add(Me.CH_DOWN_IMAGES, 0, 0)
- TP_DOWN_OPTIONS.Controls.Add(Me.CH_DOWN_VIDEOS, 1, 0)
- TP_DOWN_OPTIONS.Dock = System.Windows.Forms.DockStyle.Fill
- TP_DOWN_OPTIONS.Location = New System.Drawing.Point(1, 146)
- TP_DOWN_OPTIONS.Margin = New System.Windows.Forms.Padding(0)
- TP_DOWN_OPTIONS.Name = "TP_DOWN_OPTIONS"
- TP_DOWN_OPTIONS.RowCount = 1
- TP_DOWN_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
- TP_DOWN_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 27.0!))
- TP_DOWN_OPTIONS.Size = New System.Drawing.Size(452, 28)
- TP_DOWN_OPTIONS.TabIndex = 5
+ Me.TP_DOWN_IMG_VID.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
+ Me.TP_DOWN_IMG_VID.ColumnCount = 2
+ Me.TP_DOWN_IMG_VID.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
+ Me.TP_DOWN_IMG_VID.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
+ Me.TP_DOWN_IMG_VID.Controls.Add(Me.CH_DOWN_IMAGES, 0, 0)
+ Me.TP_DOWN_IMG_VID.Controls.Add(Me.CH_DOWN_VIDEOS, 1, 0)
+ Me.TP_DOWN_IMG_VID.Dock = System.Windows.Forms.DockStyle.Fill
+ Me.TP_DOWN_IMG_VID.Location = New System.Drawing.Point(1, 146)
+ Me.TP_DOWN_IMG_VID.Margin = New System.Windows.Forms.Padding(0)
+ Me.TP_DOWN_IMG_VID.Name = "TP_DOWN_IMG_VID"
+ Me.TP_DOWN_IMG_VID.RowCount = 1
+ Me.TP_DOWN_IMG_VID.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
+ Me.TP_DOWN_IMG_VID.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 27.0!))
+ Me.TP_DOWN_IMG_VID.Size = New System.Drawing.Size(452, 28)
+ Me.TP_DOWN_IMG_VID.TabIndex = 5
'
'CH_DOWN_IMAGES
'
@@ -442,22 +453,6 @@ Namespace Editors
Me.TXT_SCRIPT.Size = New System.Drawing.Size(446, 22)
Me.TXT_SCRIPT.TabIndex = 9
'
- 'CONTAINER_MAIN
- '
- '
- 'CONTAINER_MAIN.ContentPanel
- '
- CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
- CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(454, 461)
- CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
- CONTAINER_MAIN.LeftToolStripPanelVisible = False
- CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
- CONTAINER_MAIN.Name = "CONTAINER_MAIN"
- CONTAINER_MAIN.RightToolStripPanelVisible = False
- CONTAINER_MAIN.Size = New System.Drawing.Size(454, 461)
- CONTAINER_MAIN.TabIndex = 0
- CONTAINER_MAIN.TopToolStripPanelVisible = False
- '
'UserCreatorForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
@@ -475,27 +470,27 @@ Namespace Editors
Me.ShowInTaskbar = False
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
Me.Text = "Create User"
- TP_MAIN.ResumeLayout(False)
+ CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
+ CONTAINER_MAIN.ResumeLayout(False)
+ CONTAINER_MAIN.PerformLayout()
+ Me.TP_MAIN.ResumeLayout(False)
CType(Me.TXT_USER, System.ComponentModel.ISupportInitialize).EndInit()
- TP_SITE.ResumeLayout(False)
- TP_SITE.PerformLayout()
+ Me.TP_SITE.ResumeLayout(False)
+ Me.TP_SITE.PerformLayout()
CType(Me.CMB_SITE, System.ComponentModel.ISupportInitialize).EndInit()
- TP_PARAMS.ResumeLayout(False)
- TP_PARAMS.PerformLayout()
- TP_OTHER.ResumeLayout(False)
- TP_OTHER.PerformLayout()
+ Me.TP_TEMP_FAV.ResumeLayout(False)
+ Me.TP_TEMP_FAV.PerformLayout()
+ Me.TP_READY_USERMEDIA.ResumeLayout(False)
+ Me.TP_READY_USERMEDIA.PerformLayout()
CType(Me.TXT_DESCR, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_USER_FRIENDLY, System.ComponentModel.ISupportInitialize).EndInit()
Me.TP_ADD_BY_LIST.ResumeLayout(False)
Me.TP_ADD_BY_LIST.PerformLayout()
CType(Me.TXT_LABELS, System.ComponentModel.ISupportInitialize).EndInit()
- TP_DOWN_OPTIONS.ResumeLayout(False)
- TP_DOWN_OPTIONS.PerformLayout()
+ Me.TP_DOWN_IMG_VID.ResumeLayout(False)
+ Me.TP_DOWN_IMG_VID.PerformLayout()
CType(Me.TXT_SPEC_FOLDER, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_SCRIPT, System.ComponentModel.ISupportInitialize).EndInit()
- CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
- CONTAINER_MAIN.ResumeLayout(False)
- CONTAINER_MAIN.PerformLayout()
Me.ResumeLayout(False)
End Sub
@@ -517,5 +512,10 @@ Namespace Editors
Private WithEvents CMB_SITE As PersonalUtilities.Forms.Controls.ComboBoxExtended
Private WithEvents BTT_OTHER_SETTINGS As Button
Private WithEvents TXT_SCRIPT As PersonalUtilities.Forms.Controls.TextBoxExtended
+ Private WithEvents TP_SITE As TableLayoutPanel
+ Private WithEvents TP_MAIN As TableLayoutPanel
+ Private WithEvents TP_TEMP_FAV As TableLayoutPanel
+ Private WithEvents TP_READY_USERMEDIA As TableLayoutPanel
+ Private WithEvents TP_DOWN_IMG_VID As TableLayoutPanel
End Class
End Namespace
\ No newline at end of file
diff --git a/SCrawler/Editors/UserCreatorForm.resx b/SCrawler/Editors/UserCreatorForm.resx
index 876be63..7e231d4 100644
--- a/SCrawler/Editors/UserCreatorForm.resx
+++ b/SCrawler/Editors/UserCreatorForm.resx
@@ -117,10 +117,13 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
False
-
+
+ 17, 17
+
+
False
@@ -214,18 +217,6 @@
AAAASUVORK5CYII=
-
- False
-
-
- 17, 17
-
-
- False
-
-
- False
-
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
@@ -253,9 +244,6 @@
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
-
- False
-
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
@@ -294,7 +282,4 @@
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
-
- False
-
\ No newline at end of file
diff --git a/SCrawler/Editors/UserCreatorForm.vb b/SCrawler/Editors/UserCreatorForm.vb
index cb99b3c..87a4043 100644
--- a/SCrawler/Editors/UserCreatorForm.vb
+++ b/SCrawler/Editors/UserCreatorForm.vb
@@ -10,6 +10,8 @@ Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Controls
Imports PersonalUtilities.Forms.Controls.Base
Imports PersonalUtilities.Functions.RegularExpressions
+Imports PersonalUtilities.Tools
+Imports SCrawler.API
Imports SCrawler.API.Base
Imports SCrawler.Plugin
Imports SCrawler.Plugin.Hosts
@@ -19,7 +21,10 @@ Namespace Editors
Private WithEvents MyDef As DefaultFormOptions
Friend Property User As UserInfo
Private Property UserInstance As IUserData
+ Private ReadOnly UserIsCollection As Boolean = False
#Region "User options"
+ ''' COLLECTION EDITING ONLY
+ Friend Property CollectionName As String = String.Empty
Friend Property StartIndex As Integer = -1
Friend ReadOnly Property UserTemporary As Boolean
Get
@@ -107,10 +112,36 @@ Namespace Editors
If Not _Instance Is Nothing Then
UserInstance = _Instance
User = DirectCast(UserInstance, UserDataBase).User
+ UserIsCollection = TypeOf UserInstance Is UserDataBind
+ If UserIsCollection Then
+ With DirectCast(UserInstance, UserDataBind) : .CurrentlyEdited = True : CollectionName = .CollectionName : End With
+ End If
End If
End Sub
#End Region
#Region "Form handlers"
+ Private Class CollectionNameFieldProvider : Implements IFieldsCheckerProvider
+ Private Property ErrorMessage As String Implements IFieldsCheckerProvider.ErrorMessage
+ Private Property Name As String Implements IFieldsCheckerProvider.Name
+ Private Property TypeError As Boolean Implements IFieldsCheckerProvider.TypeError
+ Private Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider,
+ Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert
+ If ACheck(Value) Then
+ If Settings.Users.Exists(Function(u) u.IsCollection AndAlso u.CollectionName = CStr(Value) AndAlso
+ Not DirectCast(u, UserDataBind).CurrentlyEdited) Then
+ ErrorMessage = $"A collection named [{Value}] already exist"
+ Return Nothing
+ Else
+ Return Value
+ End If
+ Else
+ Return Nothing
+ End If
+ End Function
+ Private Function GetFormat(ByVal FormatType As Type) As Object Implements IFormatProvider.GetFormat
+ Throw New NotImplementedException("[GetFormat] is not available in the 'CollectionNameFieldProvider'")
+ End Function
+ End Class
Private Sub UserCreatorForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
With MyDef
@@ -122,52 +153,123 @@ Namespace Editors
.Items.AddRange(Settings.Plugins.Select(Function(p) New ListItem({p.Key, p.Name})))
.EndUpdate(True)
End With
- If User.Name.IsEmptyString Then
- CH_READY_FOR_DOWN.Checked = True
- CH_TEMP.Checked = Settings.DefaultTemporary
- CH_DOWN_IMAGES.Checked = Settings.DefaultDownloadImages
- CH_DOWN_VIDEOS.Checked = Settings.DefaultDownloadVideos
- TXT_SCRIPT.Checked = Settings.ScriptData.Attribute
- SetParamsBySite()
- Else
- TP_ADD_BY_LIST.Enabled = False
- TXT_USER.Text = User.Name
- TXT_SPEC_FOLDER.Text = User.SpecialPath
- Dim i% = Settings.Plugins.FindIndex(Function(p) p.Key = User.Plugin)
- If i >= 0 Then CMB_SITE.SelectedIndex = i
- SetParamsBySite()
- CH_IS_CHANNEL.Enabled = False
- CMB_SITE.Enabled = False
- CH_IS_CHANNEL.Checked = User.IsChannel
- If Not UserInstance Is Nothing Then
- TXT_USER.Enabled = False
- TXT_SPEC_FOLDER.TextBoxReadOnly = True
- TXT_SPEC_FOLDER.Buttons.Clear()
- TXT_SPEC_FOLDER.Buttons.UpdateButtonsPositions()
- With UserInstance
- TXT_USER_FRIENDLY.Text = .FriendlyName
- CH_FAV.Checked = .Favorite
- CH_TEMP.Checked = .Temporary
- CH_PARSE_USER_MEDIA.Checked = .ParseUserMediaOnly
- CH_READY_FOR_DOWN.Checked = .ReadyForDownload
- CH_DOWN_IMAGES.Checked = .DownloadImages
- CH_DOWN_VIDEOS.Checked = .DownloadVideos
- TXT_SCRIPT.Checked = .ScriptUse
- TXT_SCRIPT.Text = .ScriptData
- TXT_DESCR.Text = .Description.StringFormatLines
- UserLabels.ListAddList(.Labels)
- If UserLabels.ListExists Then TXT_LABELS.Text = UserLabels.ListToString
+
+ Dim NameFieldProvider As IFormatProvider = Nothing
+
+ If UserIsCollection Then
+ Icon = If(ImageRenderer.GetIcon(My.Resources.DBPic_32, EDP.ReturnValue), Icon)
+ Text = $"Collection: {UserInstance.CollectionName}"
+
+ TXT_USER.CaptionText = "Collection name"
+ TXT_USER.Text = UserInstance.CollectionName
+ TXT_USER.Buttons.AddRange({ADB.Refresh, ADB.Clear})
+ TXT_USER.Buttons.UpdateButtonsPositions()
+ TXT_SPEC_FOLDER.Buttons.Clear()
+ TXT_SPEC_FOLDER.TextBoxReadOnly = True
+ TXT_SPEC_FOLDER.Buttons.UpdateButtonsPositions()
+
+ With TP_MAIN
+ .Controls.Clear()
+ .RowStyles.Clear()
+ .RowCount = 0
+ With .RowStyles
+ .Add(New RowStyle(SizeType.Absolute, 28))
+ .Add(New RowStyle(SizeType.Absolute, 28))
+ .Add(New RowStyle(SizeType.Absolute, 28))
+ .Add(New RowStyle(SizeType.Absolute, 28))
+ .Add(New RowStyle(SizeType.Absolute, 28))
+ .Add(New RowStyle(SizeType.Absolute, 26))
+ .Add(New RowStyle(SizeType.Percent, 100))
End With
- CH_ADD_BY_LIST.Enabled = False
- Else
+ .RowCount = .RowStyles.Count
+ With .Controls
+ .Add(TXT_USER, 0, 0)
+ .Add(TXT_SPEC_FOLDER, 0, 1)
+ .Add(TP_TEMP_FAV, 0, 2)
+ .Add(TP_DOWN_IMG_VID, 0, 3)
+ .Add(TP_READY_USERMEDIA, 0, 4)
+ .Add(TXT_LABELS, 0, 5)
+ .Add(TXT_DESCR, 0, 6)
+ End With
+ .Refresh()
+ .Update()
+ End With
+
+ TXT_DESCR.TextBoxReadOnly = True
+ TXT_DESCR.Buttons.Clear()
+ TXT_DESCR.Buttons.UpdateButtonsPositions()
+
+ CH_TEMP.ThreeState = True
+ CH_FAV.ThreeState = True
+ CH_DOWN_IMAGES.ThreeState = True
+ CH_DOWN_VIDEOS.ThreeState = True
+ CH_READY_FOR_DOWN.ThreeState = True
+ CH_PARSE_USER_MEDIA.ThreeState = True
+
+ With DirectCast(UserInstance, UserDataBind)
+ Dim state As Func(Of Boolean, Func(Of IUserData, Boolean, Boolean), CheckState) =
+ Function(v, p) If(.All(Function(pp) p.Invoke(pp, v)), If(v, CheckState.Checked, CheckState.Unchecked), CheckState.Indeterminate)
+ TXT_SPEC_FOLDER.Text = DirectCast(.Item(0), UserDataBase).User.SpecialCollectionPath.ToString
+ CH_TEMP.CheckState = state(.Item(0).Temporary, Function(p, v) p.Temporary = v)
+ CH_FAV.CheckState = state(.Item(0).Favorite, Function(p, v) p.Favorite = v)
+ CH_DOWN_IMAGES.CheckState = state(.Item(0).DownloadImages, Function(p, v) p.DownloadImages = v)
+ CH_DOWN_VIDEOS.CheckState = state(.Item(0).DownloadVideos, Function(p, v) p.DownloadVideos = v)
+ CH_READY_FOR_DOWN.CheckState = state(.Item(0).ReadyForDownload, Function(p, v) p.ReadyForDownload = v)
+ CH_PARSE_USER_MEDIA.CheckState = state(.Item(0).ParseUserMediaOnly, Function(p, v) p.ParseUserMediaOnly = v)
+ TXT_DESCR.Text = .GetUserInformation.StringFormatLines
+ UserLabels.ListAddList(.Labels)
+ If UserLabels.ListExists Then TXT_LABELS.Text = UserLabels.ListToString
+ End With
+
+ NameFieldProvider = New CollectionNameFieldProvider
+ Else
+ If User.Name.IsEmptyString Then
+ CH_READY_FOR_DOWN.Checked = True
CH_TEMP.Checked = Settings.DefaultTemporary
- CH_READY_FOR_DOWN.Checked = Not Settings.DefaultTemporary
CH_DOWN_IMAGES.Checked = Settings.DefaultDownloadImages
CH_DOWN_VIDEOS.Checked = Settings.DefaultDownloadVideos
+ TXT_SCRIPT.Checked = Settings.ScriptData.Attribute
+ SetParamsBySite()
+ Else
+ TP_ADD_BY_LIST.Enabled = False
+ TXT_USER.Text = User.Name
+ TXT_SPEC_FOLDER.Text = User.SpecialPath
+ Dim i% = Settings.Plugins.FindIndex(Function(p) p.Key = User.Plugin)
+ If i >= 0 Then CMB_SITE.SelectedIndex = i
+ SetParamsBySite()
+ CH_IS_CHANNEL.Enabled = False
+ CMB_SITE.Enabled = False
+ CH_IS_CHANNEL.Checked = User.IsChannel
+ If Not UserInstance Is Nothing Then
+ TXT_USER.Enabled = False
+ TXT_SPEC_FOLDER.TextBoxReadOnly = True
+ TXT_SPEC_FOLDER.Buttons.Clear()
+ TXT_SPEC_FOLDER.Buttons.UpdateButtonsPositions()
+ With UserInstance
+ TXT_USER_FRIENDLY.Text = .FriendlyName
+ CH_FAV.Checked = .Favorite
+ CH_TEMP.Checked = .Temporary
+ CH_PARSE_USER_MEDIA.Checked = .ParseUserMediaOnly
+ CH_READY_FOR_DOWN.Checked = .ReadyForDownload
+ CH_DOWN_IMAGES.Checked = .DownloadImages
+ CH_DOWN_VIDEOS.Checked = .DownloadVideos
+ TXT_SCRIPT.Checked = .ScriptUse
+ TXT_SCRIPT.Text = .ScriptData
+ TXT_DESCR.Text = .Description.StringFormatLines
+ UserLabels.ListAddList(.Labels)
+ If UserLabels.ListExists Then TXT_LABELS.Text = UserLabels.ListToString
+ End With
+ CH_ADD_BY_LIST.Enabled = False
+ Else
+ CH_TEMP.Checked = Settings.DefaultTemporary
+ CH_READY_FOR_DOWN.Checked = Not Settings.DefaultTemporary
+ CH_DOWN_IMAGES.Checked = Settings.DefaultDownloadImages
+ CH_DOWN_VIDEOS.Checked = Settings.DefaultDownloadVideos
+ End If
End If
End If
.MyFieldsChecker = New FieldsChecker
- .MyFieldsCheckerE.AddControl(Of String)(TXT_USER, TXT_USER.CaptionText)
+ .MyFieldsCheckerE.AddControl(Of String)(TXT_USER, TXT_USER.CaptionText,, NameFieldProvider)
.MyFieldsChecker.EndLoaderOperations()
.EndLoaderOperations()
End With
@@ -186,64 +288,82 @@ Namespace Editors
End Sub
Private Sub UserCreatorForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
UserLabels.Clear()
+ If UserIsCollection And Not UserInstance Is Nothing Then DirectCast(UserInstance, UserDataBind).CurrentlyEdited = False
End Sub
#End Region
#Region "Ok, Cancel"
Private Sub MyDef_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDef.ButtonOkClick
- If Not CH_ADD_BY_LIST.Checked Then
+ If UserIsCollection Then
If MyDef.MyFieldsChecker.AllParamsOK Then
- Dim s As SettingsHost = GetSiteByCheckers()
- If Not s Is Nothing Then
- Dim tmpUser As UserInfo = User.Clone
- With tmpUser
- .Name = TXT_USER.Text
- .SpecialPath = SpecialPath(s)
- .Site = s.Name
- .Plugin = s.Key
- .IsChannel = CH_IS_CHANNEL.Checked
- .UpdateUserFile()
- End With
- User = tmpUser
- Dim ScriptText$ = TXT_SCRIPT.Text
- If Not ScriptText.IsEmptyString Then
- Dim f As SFile = ScriptText
- If Not SFile.IsDirectory(ScriptText) And Not UserInstance Is Nothing Then
- With DirectCast(UserInstance, UserDataBase) : f.Path = .MyFile.Path : End With
- End If
- TXT_SCRIPT.Text = f
- End If
- If Not UserInstance Is Nothing Then
- With DirectCast(UserInstance, UserDataBase)
- .User = User
- .FriendlyName = TXT_USER_FRIENDLY.Text
- .Favorite = CH_FAV.Checked
- .Temporary = CH_TEMP.Checked
- .ReadyForDownload = CH_READY_FOR_DOWN.Checked
- .DownloadImages = CH_DOWN_IMAGES.Checked
- .DownloadVideos = CH_DOWN_VIDEOS.Checked
- .UserDescription = TXT_DESCR.Text
- If Not MyExchangeOptions Is Nothing Then .ExchangeOptionsSet(MyExchangeOptions)
- Dim l As New ListAddParams(LAP.NotContainsOnly + LAP.ClearBeforeAdd)
- If .IsCollection Then
- With DirectCast(UserInstance, API.UserDataBind)
- If .Count > 0 Then .Collections.ForEach(Sub(c) c.Labels.ListAddList(UserLabels, l))
- End With
- Else
- .Labels.ListAddList(UserLabels, LAP.NotContainsOnly, LAP.ClearBeforeAdd)
- End If
- .ParseUserMediaOnly = CH_PARSE_USER_MEDIA.Checked
- .ScriptUse = TXT_SCRIPT.Checked
- .ScriptData = TXT_SCRIPT.Text
- .UpdateUserInformation()
- End With
- End If
- GoTo CloseForm
- Else
- MsgBoxE("User site not selected", MsgBoxStyle.Exclamation)
- End If
+ With UserInstance
+ If Not CH_TEMP.CheckState = CheckState.Indeterminate Then .Temporary = CH_TEMP.Checked
+ If Not CH_FAV.CheckState = CheckState.Indeterminate Then .Favorite = CH_FAV.Checked
+ If Not CH_DOWN_IMAGES.CheckState = CheckState.Indeterminate Then .DownloadImages = CH_DOWN_IMAGES.Checked
+ If Not CH_DOWN_VIDEOS.CheckState = CheckState.Indeterminate Then .DownloadVideos = CH_DOWN_VIDEOS.Checked
+ If Not CH_READY_FOR_DOWN.CheckState = CheckState.Indeterminate Then .ReadyForDownload = CH_READY_FOR_DOWN.Checked
+ If Not CH_PARSE_USER_MEDIA.CheckState = CheckState.Indeterminate Then .ParseUserMediaOnly = CH_PARSE_USER_MEDIA.Checked
+ DirectCast(UserInstance, UserDataBind).Collections.ForEach(Sub(u) u.Labels.ListAddList(UserLabels, LAP.ClearBeforeAdd, LAP.NotContainsOnly))
+ CollectionName = TXT_USER.Text
+ .UpdateUserInformation()
+ End With
+ GoTo CloseForm
End If
Else
- If CreateUsersByList() Then GoTo CloseForm
+ If Not CH_ADD_BY_LIST.Checked Then
+ If MyDef.MyFieldsChecker.AllParamsOK Then
+ Dim s As SettingsHost = GetSiteByCheckers()
+ If Not s Is Nothing Then
+ Dim tmpUser As UserInfo = User.Clone
+ With tmpUser
+ .Name = TXT_USER.Text
+ .SpecialPath = SpecialPath(s)
+ .Site = s.Name
+ .Plugin = s.Key
+ .IsChannel = CH_IS_CHANNEL.Checked
+ .UpdateUserFile()
+ End With
+ User = tmpUser
+ Dim ScriptText$ = TXT_SCRIPT.Text
+ If Not ScriptText.IsEmptyString Then
+ Dim f As SFile = ScriptText
+ If Not SFile.IsDirectory(ScriptText) And Not UserInstance Is Nothing Then
+ With DirectCast(UserInstance, UserDataBase) : f.Path = .MyFile.Path : End With
+ End If
+ TXT_SCRIPT.Text = f
+ End If
+ If Not UserInstance Is Nothing Then
+ With DirectCast(UserInstance, UserDataBase)
+ .User = User
+ .FriendlyName = TXT_USER_FRIENDLY.Text
+ .Favorite = CH_FAV.Checked
+ .Temporary = CH_TEMP.Checked
+ .ReadyForDownload = CH_READY_FOR_DOWN.Checked
+ .DownloadImages = CH_DOWN_IMAGES.Checked
+ .DownloadVideos = CH_DOWN_VIDEOS.Checked
+ .UserDescription = TXT_DESCR.Text
+ If Not MyExchangeOptions Is Nothing Then .ExchangeOptionsSet(MyExchangeOptions)
+ Dim l As New ListAddParams(LAP.NotContainsOnly + LAP.ClearBeforeAdd)
+ If .IsCollection Then
+ With DirectCast(UserInstance, API.UserDataBind)
+ If .Count > 0 Then .Collections.ForEach(Sub(c) c.Labels.ListAddList(UserLabels, l))
+ End With
+ Else
+ .Labels.ListAddList(UserLabels, LAP.NotContainsOnly, LAP.ClearBeforeAdd)
+ End If
+ .ParseUserMediaOnly = CH_PARSE_USER_MEDIA.Checked
+ .ScriptUse = TXT_SCRIPT.Checked
+ .ScriptData = TXT_SCRIPT.Text
+ .UpdateUserInformation()
+ End With
+ End If
+ GoTo CloseForm
+ Else
+ MsgBoxE("User site not selected", MsgBoxStyle.Exclamation)
+ End If
+ End If
+ Else
+ If CreateUsersByList() Then GoTo CloseForm
+ End If
End If
Exit Sub
CloseForm:
@@ -257,7 +377,7 @@ CloseForm:
Private _TextChangeInvoked As Boolean = False
Private Sub TXT_USER_ActionOnTextChanged(ByVal Sender As Object, ByVal e As EventArgs) Handles TXT_USER.ActionOnTextChanged
Try
- If Not _TextChangeInvoked Then
+ If Not _TextChangeInvoked And Not UserIsCollection Then
_TextChangeInvoked = True
If Not CH_ADD_BY_LIST.Checked Then
Dim s As ExchangeOptions = GetSiteByText(TXT_USER.Text)
@@ -282,7 +402,10 @@ CloseForm:
Catch
End Try
End Sub
- Private Sub CMB_SITE_ActionSelectedItemChanged(ByVal Item As ListViewItem) Handles CMB_SITE.ActionSelectedItemChanged
+ Private Sub TXT_USER_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_USER.ActionOnButtonClick
+ If UserIsCollection AndAlso Sender.DefaultButton = ADB.Refresh Then TXT_USER.Text = UserInstance.CollectionName
+ End Sub
+ Private Sub CMB_SITE_ActionSelectedItemChanged(ByVal Sender As Object, ByVal e As EventArgs, ByVal Item As ListViewItem) Handles CMB_SITE.ActionSelectedItemChanged
CH_IS_CHANNEL.Checked = False
MyExchangeOptions = Nothing
SetParamsBySite()
@@ -299,7 +422,7 @@ CloseForm:
If Sender.DefaultButton = ADB.Open Then
Dim f As SFile = Nothing
If Not TXT_SPEC_FOLDER.Text.IsEmptyString Then f = $"{TXT_SPEC_FOLDER.Text}\"
- f = SFile.SelectPath(f, True)
+ f = SFile.SelectPath(f)
If Not f.IsEmptyString Then TXT_SPEC_FOLDER.Text = f.PathWithSeparator
End If
End Sub
@@ -382,7 +505,8 @@ CloseForm:
End If
If Not s Is Nothing Then
- tmpUser = New UserInfo(uu, s,,, __sf(uu, s)) With {.IsChannel = _IsChannel}
+ tmpUser = New UserInfo(uu, s) With {.SpecialPath = __sf(uu, s), .IsChannel = _IsChannel}
+ tmpUser.UpdateUserFile()
uid = -1
If Settings.UsersList.Count > 0 Then uid = Settings.UsersList.IndexOf(tmpUser)
If uid < 0 And Not UsersForCreate.Contains(tmpUser) Then
diff --git a/SCrawler/EncryptCookies.vb b/SCrawler/EncryptCookies.vb
index de3bf72..eb70f84 100644
--- a/SCrawler/EncryptCookies.vb
+++ b/SCrawler/EncryptCookies.vb
@@ -6,7 +6,7 @@
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
-Imports PersonalUtilities.Tools.WEB
+Imports PersonalUtilities.Tools.Web.Clients
Namespace EncryptCookies
Friend Module EncryptFunction
Friend CookiesEncrypted As Boolean = False
diff --git a/SCrawler/MainFrame.vb b/SCrawler/MainFrame.vb
index d6334b5..aaf2206 100644
--- a/SCrawler/MainFrame.vb
+++ b/SCrawler/MainFrame.vb
@@ -7,7 +7,6 @@
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports System.Threading
-Imports System.Globalization
Imports System.ComponentModel
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Functions.Messaging
@@ -21,9 +20,10 @@ Public Class MainFrame
#Region "Declarations"
Private MyView As FormView
Private WithEvents MyActivator As FormActivator
+ Private WithEvents BTT_IMPORT_USERS As ToolStripMenuItem
Private ReadOnly _VideoDownloadingMode As Boolean = False
- Private MyChannels As ChannelViewForm
- Private MySavedPosts As DownloadSavedPostsForm
+ Friend MyChannels As ChannelViewForm
+ Friend MySavedPosts As DownloadSavedPostsForm
Private MyMissingPosts As MissingPostsForm
Private MyFeed As DownloadFeedForm
Private MySearch As UserSearchForm
@@ -32,10 +32,6 @@ Public Class MainFrame
#Region "Initializer"
Public Sub New()
InitializeComponent()
- Dim n As DateTimeFormatInfo = CultureInfo.GetCultureInfo("en-us").DateTimeFormat.Clone
- n.FullDateTimePattern = "ddd MMM dd HH:mm:ss +ffff yyyy"
- n.TimeSeparator = String.Empty
- Twitter.DateProvider = New ADateTime(DirectCast(n.Clone, DateTimeFormatInfo)) With {.DateTimeStyle = DateTimeStyles.AssumeUniversal}
Settings = New SettingsCLS
With Settings.Plugins
If .Count > 0 Then
@@ -44,6 +40,8 @@ Public Class MainFrame
Next
End If
End With
+ BTT_IMPORT_USERS = New ToolStripMenuItem With {.Text = "Import", .Image = My.Resources.UsersIcon_32.ToBitmap}
+ MENU_SETTINGS.DropDownItems.AddRange({New ToolStripSeparator, BTT_IMPORT_USERS})
Dim Args() As String = Environment.GetCommandLineArgs
If Args.ListExists(2) AndAlso Args(1) = "v" Then
Using f As New VideosDownloaderForm With {.IsStandalone = True} : f.ShowDialog() : End Using
@@ -278,6 +276,35 @@ CloseResume:
End Using
End With
End Sub
+ Private Sub BTT_IMPORT_USERS_Click(sender As Object, e As EventArgs) Handles BTT_IMPORT_USERS.Click
+ Const MsgTitle$ = "Import users"
+ Try
+ Dim file As SFile = Nothing
+ Dim _OriginalLocations As Boolean = False
+ Select Case MsgBoxE({"Where do you want to import users from?" & vbCr & vbCr &
+ "This feature is not for importing users from the site. It's more like searching for missing users.", MsgTitle}, vbQuestion,,,
+ {"Select path", New MsgBoxButton("Current", "All plugin paths will be checked"), "Cancel"}).Index
+ Case 0 : file = SFile.SelectPath
+ Case 1 : _OriginalLocations = True
+ Case Else : MsgBoxE({"Operation canceled", MsgTitle}) : Exit Sub
+ End Select
+ If Not file.IsEmptyString Or _OriginalLocations Then
+ Using import As New UserFinder(file)
+ With import
+ .Find(_OriginalLocations)
+ If .Count > 0 Then
+ .Verify()
+ .Dialog()
+ Else
+ MsgBoxE({"No users found", MsgTitle})
+ End If
+ End With
+ End Using
+ End If
+ Catch ex As Exception
+ ErrorsDescriber.Execute(EDP.LogMessageValue, ex, MsgTitle)
+ End Try
+ End Sub
#End Region
#Region "Add, Edit, Delete, Refresh"
Private Sub OnUsersAddedHandler(ByVal StartIndex As Integer)
@@ -718,23 +745,47 @@ CloseResume:
End If
End Sub
Private Sub BTT_CONTEXT_GROUPS_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_GROUPS.Click
+ Const MsgTitle$ = "Label change"
Try
Dim users As List(Of IUserData) = GetSelectedUserArray()
If users.ListExists Then
Dim l As List(Of String) = ListAddList(Nothing, users.SelectMany(Function(u) u.Labels), LAP.NotContainsOnly)
- Using f As New LabelsForm(l) With {.MultiUser = True}
+ Using f As New LabelsForm(l) With {.WithDeleteButton = l.Count > 0}
f.ShowDialog()
If f.DialogResult = DialogResult.OK Then
- Dim _lp As LAP = LAP.NotContainsOnly
- If f.MultiUserClearExists Then _lp += LAP.ClearBeforeAdd
- Dim lp As New ListAddParams(_lp)
+ Dim labels As List(Of String) = f.LabelsList
+ Dim lp As New ListAddParams(LAP.NotContainsOnly)
+ Dim a As Action(Of IUserData) = Sub(u) u.Labels.ListAddList(labels, lp)
+ Dim cMsg As New MMessage("Operation canceled", MsgTitle)
+ If labels.ListExists Then
+ Select Case MsgBoxE(New MMessage($"What do you want to do with the selected labels?{vbCr}Selected labels:{vbCr}{labels.ListToString(vbCr)}",
+ MsgTitle,
+ {
+ New MsgBoxButton("Replace", "All existing labels will be removed and replaced with these labels"),
+ New MsgBoxButton("Add", "These labels will be added to the existing ones"),
+ New MsgBoxButton("Remove", "These labels will be removed from the existing ones"),
+ "Cancel"
+ }, vbExclamation) With {.ButtonsPerRow = 2}).Index
+ Case 0 : lp.ClearBeforeAdd = True
+ Case 1 : lp.ClearBeforeAdd = False
+ Case 2 : a = Sub(u) u.Labels.ListDisposeRemove(labels)
+ Case Else : cMsg.Show() : Exit Sub
+ End Select
+ Else
+ If MsgBoxE({"Are you sure you want to remove all labels?", MsgTitle}, vbExclamation + vbYesNo) = vbYes Then
+ a = Sub(u) u.Labels.Clear()
+ Else
+ cMsg.Show()
+ Exit Sub
+ End If
+ End If
users.ForEach(Sub(ByVal u As IUserData)
If u.IsCollection Then
With DirectCast(u, UserDataBind)
- If .Count > 0 Then .Collections.ForEach(Sub(uu) uu.Labels.ListAddList(f.LabelsList, lp))
+ If .Count > 0 Then .Collections.ForEach(a)
End With
Else
- u.Labels.ListAddList(f.LabelsList, lp)
+ a.Invoke(u)
End If
u.UpdateUserInformation()
End Sub)
@@ -818,11 +869,48 @@ CloseResume:
MainFrameObj.CollectionHandler(DirectCast(.Users.Last, UserDataBind))
userCollection = .Users.Last
End If
+
+ Dim __modelUser As UsageModel = -1
+ Dim __modelCollection As UsageModel = -1
+ Dim __ModelAskForDecision As Boolean = False
+ If Not Added Then __modelCollection = userCollection.CollectionModel
+ If Added Then
+ __ModelAskForDecision = True
+ ElseIf userCollection.CollectionModel = UsageModel.Virtual Then
+ __modelUser = UsageModel.Virtual
+ __modelCollection = UsageModel.Virtual
+ Else
+ __ModelAskForDecision = True
+ End If
+ If __ModelAskForDecision Then
+ Select Case MsgBoxE({"How do you want to add users to the collection?", MsgTitle}, vbQuestion,,,
+ {
+ New MsgBoxButton("Default", "User files will be moved to the collection") With {.KeyCode = Keys.Enter},
+ New MsgBoxButton("Virtual", "The user will be included in the collection, but user files will not be moved") With {
+ .KeyCode = New ButtonKey(Keys.Enter, True)}
+ }).Index
+ Case 0
+ __modelUser = UsageModel.Default
+ If __modelCollection = -1 Then __modelCollection = UsageModel.Default
+ Case 1
+ __modelUser = UsageModel.Virtual
+ If __modelCollection = -1 Then __modelCollection = UsageModel.Virtual
+ End Select
+ End If
+ If __modelUser = -1 Or __modelCollection = -1 Then
+ MsgBoxE({$"Some parameters cannot be processed:{vbCr}" &
+ $"UserModel: {CInt(__modelUser)}{vbCr}CollectionModel: {CInt(__modelCollection)}{vbCr}" &
+ "Operation canceled", MsgTitle}, vbCritical)
+ Exit Sub
+ End If
+
Dim __added_users As New List(Of IUserData)
Dim __added_users_not As New List(Of IUserData)
- For Each user As IUserData In users
+ For Each user As UserDataBase In users
If Not user.IsCollection Then
Try
+ user.User.UserModel = __modelUser
+ user.User.CollectionModel = __modelCollection
userCollection.Add(user)
RemoveUserFromList(user)
UserListUpdate(userCollection, Added)
@@ -862,15 +950,17 @@ CloseResume:
End If
End Sub
Private Sub BTT_CONTEXT_COL_MERGE_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_COL_MERGE.Click
+ Const MsgTitle$ = "Merging files"
Dim user As IUserData = GetSelectedUser()
If Not user Is Nothing Then
If user.IsCollection Then
If DirectCast(user, UserDataBind).DataMerging Then
- MsgBoxE("Collection files are already merged")
+ MsgBoxE({"Collection files are already merged", MsgTitle})
+ ElseIf user.IsVirtual Then
+ MsgBoxE({"The action cannot be performed. This is a virtual collection.", MsgTitle}, vbCritical)
Else
- If MsgBoxE({"Do you really want to merge collection files into one folder?" & vbNewLine &
- "This action is not turnable!", "Merging files"},
- MsgBoxStyle.Exclamation + MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
+ If MsgBoxE({"Are you sure you want to merge the collection files into one folder?" & vbNewLine &
+ "This action is not turnable!", MsgTitle}, vbExclamation + vbYesNo) = vbYes Then
DirectCast(user, UserDataBind).DataMerging = True
End If
End If
@@ -880,83 +970,118 @@ CloseResume:
End If
End Sub
Private Sub BTT_CONTEXT_CHANGE_FOLDER_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_CHANGE_FOLDER.Click
+ Const MsgTitle$ = "Change user folder"
Try
+ If Downloader.Working Then
+ MsgBoxE({"Some users are currently downloading." & vbCr &
+ "You cannot change paths while downloading." & vbCr &
+ "Wait until the download is complete.", MsgTitle}, vbCritical)
+ Exit Sub
+ Else
+ Downloader.Suspended = True
+ End If
Dim users As List(Of IUserData) = GetSelectedUserArray()
If users.ListExists Then
If users.Count = 1 Then
Dim CutOption% = 1
Dim _IsCollection As Boolean = False
+ Dim CurrDir As SFile
+ Dim colName$ = String.Empty
With users(0)
If .IsCollection Then
_IsCollection = True
With DirectCast(.Self, UserDataBind)
If .Count = 0 Then
Throw New ArgumentOutOfRangeException("Collection", "Collection is empty")
+ ElseIf .IsVirtual Then
+ MsgBoxE({"This is a virtual collection." & vbCr &
+ "The virtual collection path cannot be changed." & vbCr &
+ "To change the paths of users included in a virtual collection, " &
+ "you must split the collection and then change the user paths.", MsgTitle}, vbCritical)
+ Exit Sub
Else
- With DirectCast(.Collections(0), UserDataBase)
- If Not .User.Merged Then CutOption = 2
- End With
+ CurrDir = .GetRealUserFile
+ If CurrDir.IsEmptyString Then
+ MsgBoxE({"Non-virtual users not found", MsgTitle}, vbCritical)
+ Exit Sub
+ End If
+ CurrDir = CurrDir.CutPath(IIf(.DataMerging, 3, 2))
+ colName = CurrDir.PathFolders.LastOrDefault
+ Dim vu As IEnumerable(Of IUserData) = .Where(Function(vuu) vuu.UserModel = UsageModel.Virtual)
+ If vu.ListExists Then
+ If MsgBoxE({"This collection contains virtual users." & vbCr &
+ "If you continue, the virtual user paths will not be changed." & vbCr &
+ "The following users have been added to the collection in virtual mode:" & vbCr &
+ vu.ListToStringE(vbCr, GetUserListProvider(False)), MsgTitle},
+ vbExclamation,,, {"Continue", "Cancel"}) = 1 Then MsgBoxE({"Operation canceled", MsgTitle}) : Exit Sub
+ End If
End If
End With
+ Else
+ CurrDir = .Self.File.CutPath(1)
End If
- End With
- Dim CurrDir As SFile = users(0).File.CutPath(CutOption)
- Dim NewDest As SFile = SFile.GetPath(InputBoxE($"Enter a new destination for user [{users(0)}]", "Change user folder", CurrDir.Path))
- If Not NewDest.IsEmptyString Then
- If MsgBoxE({$"You are changing the user's [{users(0)}] destination" & vbCr &
- $"Current destination: {CurrDir.PathNoSeparator}" & vbCr &
- $"New destination: {NewDest.Path}",
- "Changing user destination"}, MsgBoxStyle.Exclamation,,, {"Confirm", "Cancel"}) = 0 Then
- If Not NewDest.IsEmptyString AndAlso
- (Not NewDest.Exists(SFO.Path, False) OrElse
- (
- SFile.GetFiles(NewDest,, IO.SearchOption.AllDirectories, EDP.ThrowException).ListIfNothing.Count = 0 AndAlso
- NewDest.Delete(SFO.Path, Settings.DeleteMode, EDP.ThrowException) AndAlso
- Not NewDest.Exists(SFO.Path, False)
- )
- ) Then
- NewDest.CutPath.Exists(SFO.Path)
- IO.Directory.Move(CurrDir.Path, NewDest.Path)
- Dim ApplyChanges As Action(Of IUserData) = Sub(ByVal __user As IUserData)
- With DirectCast(__user, UserDataBase)
- Dim u As UserInfo = .User.Clone
- Settings.UsersList.Remove(u)
- Dim d As SFile = Nothing
- If _IsCollection Then d = SFile.GetPath($"{NewDest.PathWithSeparator}{u.File.PathFolders(1).LastOrDefault}")
- If d.IsEmptyString Then d = NewDest
- u.SpecialPath = d.PathWithSeparator
- u.UpdateUserFile()
- Settings.UpdateUsersList(u)
- .User = u.Clone
- .UpdateUserInformation()
- End With
- End Sub
- If users(0).IsCollection Then
- With DirectCast(users(0), UserDataBind)
- For Each user In .Collections : ApplyChanges(user) : Next
- End With
+ Dim NewDest As SFile = SFile.SelectPath(CurrDir, $"Select a new destination for {IIf(_IsCollection, "collection", "user")} [{ .Self}]")
+ If Not NewDest.IsEmptyString Then
+ NewDest = $"{NewDest.PathWithSeparator}{colName}\"
+ If MsgBoxE({$"You are changing the user's [{ .Self}] destination" & vbCr &
+ $"Current destination: {CurrDir.PathNoSeparator}" & vbCr &
+ $"New destination: {NewDest.PathNoSeparator}",
+ MsgTitle}, MsgBoxStyle.Exclamation,,, {"Confirm", "Cancel"}) = 0 Then
+ If Not NewDest.IsEmptyString AndAlso
+ (Not NewDest.Exists(SFO.Path, False) OrElse
+ (
+ SFile.GetFiles(NewDest,, IO.SearchOption.AllDirectories, EDP.ThrowException).ListIfNothing.Count = 0 AndAlso
+ NewDest.Delete(SFO.Path, Settings.DeleteMode, EDP.ThrowException) AndAlso
+ Not NewDest.Exists(SFO.Path, False)
+ )
+ ) Then
+ If SFile.Move(CurrDir, NewDest, SFO.Path,,, EDP.ShowMainMsg + EDP.ReturnValue) Then
+ Dim ApplyChanges As Action(Of IUserData) = Sub(ByVal __user As IUserData)
+ With DirectCast(__user, UserDataBase)
+ Dim u As UserInfo = .User
+ Settings.UsersList.Remove(u)
+ If _IsCollection Then
+ u.SpecialCollectionPath = NewDest
+ Else
+ u.SpecialPath = NewDest
+ End If
+ u.UpdateUserFile()
+ Settings.UsersList.Add(u)
+ .User = u
+ .UpdateUserInformation()
+ End With
+ End Sub
+ If .Self.IsCollection Then
+ With DirectCast(.Self, UserDataBind)
+ For Each user In .Collections : ApplyChanges(user) : Next
+ End With
+ Else
+ ApplyChanges(.Self)
+ End If
+ Settings.UpdateUsersList()
+ MsgBoxE({"User data has been moved", MsgTitle})
+ End If
Else
- ApplyChanges(users(0))
+ MsgBoxE({$"Unable to move user data to new destination [{NewDest}]{vbCr}Operation canceled", MsgTitle}, MsgBoxStyle.Critical)
End If
- MsgBoxE($"User data has been moved")
Else
- MsgBoxE($"Unable to move user data to new destination [{NewDest}]{vbCr}Operation canceled", MsgBoxStyle.Critical)
+ MsgBoxE({"Operation canceled", MsgTitle})
End If
Else
- MsgBoxE("Operation canceled")
+ MsgBoxE({$"You have not entered a new destination{vbCr}Operation canceled", MsgTitle}, MsgBoxStyle.Exclamation)
End If
- Else
- MsgBoxE("You have not entered a new destination" & vbCr & "Operation canceled", MsgBoxStyle.Exclamation)
- End If
+ End With
Else
- MsgBoxE("You have selected multiple users. You can change the folder only for one user!", MsgBoxStyle.Critical)
+ MsgBoxE({"You have selected multiple users. You can change the folder only for one user!", MsgTitle}, MsgBoxStyle.Critical)
End If
Else
- MsgBoxE("No one user selected", MsgBoxStyle.Exclamation)
+ MsgBoxE({"No one user selected", MsgTitle}, MsgBoxStyle.Exclamation)
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.ShowAllMsg, ex, "Error while moving user")
+ Finally
+ Downloader.Suspended = False
End Try
End Sub
#End Region
@@ -987,7 +1112,7 @@ CloseResume:
#Region "6 - information"
Private Sub BTT_CONTEXT_INFO_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_INFO.Click
Dim user As IUserData = GetSelectedUser()
- If Not user Is Nothing Then MsgBoxE(DirectCast(user, UserDataBase).GetUserInformation())
+ If Not user Is Nothing Then MsgBoxE(New MMessage(DirectCast(user, UserDataBase).GetUserInformation(), "User information") With {.Editable = True})
End Sub
#End Region
Private Sub USER_CONTEXT_VisibleChanged(sender As Object, e As EventArgs) Handles USER_CONTEXT.VisibleChanged
@@ -1169,7 +1294,7 @@ CancelDownloadingOperation:
Exit Sub
ResumeDownloadingOperation:
Dim uStr$ = If(users.Count = 1, String.Empty, users.ListToStringE(vbNewLine, GetUserListProvider(True)))
- Dim fStr$ = $"({IIf(IncludeInTheFeed, "included in", "excluded from")} the feed)"
+ Dim fStr$ = $" ({IIf(IncludeInTheFeed, "included in", "excluded from")} the feed)"
If users.Count = 1 OrElse MsgBoxE({$"You have selected {users.Count} user profiles" & vbCr &
$"Do you want to download them all{fStr}?{vbNewLine.StringDup(2)}" &
$"Selected users:{vbNewLine}{uStr}", "Multiple users selected"},
@@ -1184,16 +1309,61 @@ ResumeDownloadingOperation:
End If
End Sub
Private Sub EditSelectedUser()
+ Const MsgTitle$ = "User update"
Dim user As IUserData = GetSelectedUser()
If Not user Is Nothing Then
On Error Resume Next
- If user.IsCollection Then
- If USER_CONTEXT.Visible Then USER_CONTEXT.Hide()
- MsgBoxE($"This is collection!{vbNewLine}Collection editing not allowed!", vbExclamation)
- Else
+ If Not user.IsCollection OrElse DirectCast(user, UserDataBind).Count > 0 Then
+ If user.IsCollection And USER_CONTEXT.Visible Then USER_CONTEXT.Hide()
Using f As New UserCreatorForm(user)
f.ShowDialog()
- If f.DialogResult = DialogResult.OK Then UserListUpdate(user, False)
+ If f.DialogResult = DialogResult.OK Then
+ Dim NeedToUpdate As Boolean = True
+ If user.IsCollection Then
+ If user.IsCollection And Not user.CollectionName = f.CollectionName Then
+ If Not user.IsVirtual AndAlso Downloader.Working Then
+ MsgBoxE({"Some users are currently downloading." & vbCr &
+ "You cannot change collection name while downloading." & vbCr &
+ "Wait until the download is complete.", MsgTitle}, vbCritical)
+ Exit Sub
+ Else
+ If Not user.IsVirtual Then
+ Dim colFile As SFile = DirectCast(user, UserDataBind).GetRealUserFile
+ If Not colFile.IsEmptyString Then
+ colFile = colFile.CutPath(IIf(DirectCast(user, UserDataBind).DataMerging, 1, 2))
+ If Not colFile.IsEmptyString Then
+ Dim nf As SFile = $"{colFile.CutPath(1).PathWithSeparator}{f.CollectionName}".CSFilePS
+ If Not SFile.Rename(colFile, New SFile With {.Path = f.CollectionName}, SFO.Path,
+ New ErrorsDescriber(True, False, False, New SFile)).IsEmptyString Then
+ RemoveUserFromList(user)
+ Dim __user As UserInfo
+ For Each ColUser As UserDataBase In DirectCast(user, UserDataBind).Collections
+ __user = ColUser.User
+ Settings.UsersList.Remove(__user)
+ __user.CollectionName = f.CollectionName
+ If Not __user.SpecialCollectionPath.IsEmptyString Then __user.SpecialCollectionPath = nf
+ __user.UpdateUserFile()
+ ColUser.User = __user
+ Settings.UsersList.Add(__user)
+ Next
+ user.UpdateUserInformation()
+ UserListUpdate(user, True)
+ NeedToUpdate = False
+ End If
+ End If
+ End If
+ Else
+ RemoveUserFromList(user)
+ user.CollectionName = f.CollectionName
+ user.UpdateUserInformation()
+ UserListUpdate(user, True)
+ NeedToUpdate = False
+ End If
+ End If
+ End If
+ End If
+ If NeedToUpdate Then UserListUpdate(user, False)
+ End If
End Using
End If
End If
@@ -1206,19 +1376,26 @@ ResumeDownloadingOperation:
Dim userProvider As IFormatProvider = GetUserListProvider(True)
Dim ugn As Func(Of IUserData, String) = Function(u) AConvert(Of String)(u, userProvider)
Dim m As New MMessage(users.ListToStringE(vbNewLine, userProvider), "Users deleting",
- {New MsgBoxButton("Delete and ban") With {.ToolTip = "Users and their data will be deleted and added to the blacklist"},
+ {New MsgBoxButton("Delete and ban") With {
+ .ToolTip = "Users and their data will be deleted and added to the blacklist",
+ .KeyCode = Keys.Enter},
New MsgBoxButton("Delete user only and ban") With {
.ToolTip = "Users will be deleted and added to the blacklist (user data will not be deleted)"},
New MsgBoxButton("Delete and ban with reason") With {
- .ToolTip = "Users and their data will be deleted and added to the blacklist with set a reason to delete"},
+ .ToolTip = "Users and their data will be deleted and added to the blacklist with set a reason to delete",
+ .KeyCode = New ButtonKey(Keys.Enter,, True)},
New MsgBoxButton("Delete user only and ban with reason") With {
.ToolTip = "Users will be deleted and added to the blacklist with set a reason to delete (user data will not be deleted)"},
- New MsgBoxButton("Delete") With {.ToolTip = "Delete users and their data"},
+ New MsgBoxButton("Delete") With {
+ .ToolTip = "Delete users and their data",
+ .KeyCode = New ButtonKey(Keys.Enter, True)},
New MsgBoxButton("Delete user only") With {.ToolTip = "Delete users but keep data"}, "Cancel"},
MsgBoxStyle.Exclamation) With {.ButtonsPerRow = 2, .ButtonsPlacing = MMessage.ButtonsPlacings.StartToEnd}
m.Text = $"The following users ({users.Count}) will be deleted:{vbNewLine}{m.Text}"
Dim result% = MsgBoxE(m)
If result < 6 Then
+ Dim collectionResult% = -1
+ Dim tmpResult%
Dim IsMultiple As Boolean = users.Count > 1
Dim removedUsers As New List(Of String)
Dim keepData As Boolean = Not (result Mod 2) = 0
@@ -1253,7 +1430,9 @@ ResumeDownloadingOperation:
removedUsers.Add(ugn(user))
user.Dispose()
Else
- If user.Delete(IsMultiple) > 0 Then
+ tmpResult = user.Delete(IsMultiple, collectionResult)
+ If user.IsCollection And collectionResult = -1 Then collectionResult = tmpResult
+ If tmpResult > 0 Then
If banUser Then Settings.BlackList.ListAddValue(New UserBan(user.Name, reason), l) : b = True
RemoveUserFromList(user)
removedUsers.Add(ugn(user))
@@ -1294,7 +1473,7 @@ ResumeDownloadingOperation:
If users.ListExists Then
Dim f As SFile = Settings.LastCopyPath
Dim _select_path As Func(Of Boolean) = Function() As Boolean
- f = SFile.SelectPath(f, True)
+ f = SFile.SelectPath(f)
If f.Exists(SFO.Path, False) Then
Return MsgBoxE({$"Are you sure you want to copy the data to the selected folder?{vbCr}{f}",
MsgTitle}, vbQuestion + vbYesNo) = vbYes
diff --git a/SCrawler/MainFrameObjects.vb b/SCrawler/MainFrameObjects.vb
index 06b2353..b7be299 100644
--- a/SCrawler/MainFrameObjects.vb
+++ b/SCrawler/MainFrameObjects.vb
@@ -9,6 +9,7 @@
Imports SCrawler.API
Imports SCrawler.API.Base
Imports PersonalUtilities.Tools.Notifications
+Imports NotifyObj = SCrawler.SettingsCLS.NotificationObjects
Friend Class MainFrameObjects
Friend ReadOnly Property MF As MainFrame
Private WithEvents Notificator As NotificationsManager
@@ -63,16 +64,28 @@ Friend Class MainFrameObjects
#End Region
#Region "Notifications"
Private Const NotificationInternalKey As String = "NotificationInternalKey"
- Friend Sub ShowNotification(ByVal Sender As SettingsCLS.NotificationObjects, ByVal Message As String)
+ Friend Sub ShowNotification(ByVal Sender As NotifyObj, ByVal Message As String)
If Settings.ProcessNotification(Sender) Then
- Using n As New Notification(Message) With {.Key = NotificationInternalKey} : n.Show() : End Using
+ Using n As New Notification(Message) With {.Key = $"{NotificationInternalKey}_{Sender}"} : n.Show() : End Using
End If
End Sub
Friend Sub ClearNotifications()
Notificator.Clear()
End Sub
Private Sub Notificator_OnClicked(ByVal Key As String) Handles Notificator.OnClicked
- If Key = NotificationInternalKey OrElse Settings.Automation Is Nothing OrElse Not Settings.Automation.NotificationClicked(Key) Then Focus(True)
+ If Not Key.IsEmptyString Then
+ If Key.StartsWith(NotificationInternalKey) Then
+ Select Case Key
+ Case $"{NotificationInternalKey}_{NotifyObj.Channels}" : MF.MyChannels.FormShowS()
+ Case $"{NotificationInternalKey}_{NotifyObj.SavedPosts}" : MF.MySavedPosts.FormShowS()
+ Case Else : Focus(True)
+ End Select
+ ElseIf Settings.Automation Is Nothing OrElse Not Settings.Automation.NotificationClicked(Key) Then
+ Focus(True)
+ Else
+ Focus(True)
+ End If
+ End If
End Sub
#End Region
End Class
\ No newline at end of file
diff --git a/SCrawler/MainMod.vb b/SCrawler/MainMod.vb
index 44afa60..d7abb30 100644
--- a/SCrawler/MainMod.vb
+++ b/SCrawler/MainMod.vb
@@ -10,7 +10,7 @@ Imports PersonalUtilities.Functions.XML.Base
Imports PersonalUtilities.Functions.RegularExpressions
Imports PersonalUtilities.Forms.Toolbars
Imports PersonalUtilities.Tools
-Imports PersonalUtilities.Tools.WEB
+Imports PersonalUtilities.Tools.Web
Imports SCrawler.API
Imports SCrawler.API.Base
Imports SCrawler.Plugin.Hosts
@@ -93,6 +93,10 @@ Friend Module MainMod
Replace = 1
Add = 2
End Enum
+ Friend Enum UsageModel As Integer
+ [Default] = 0
+ Virtual = 1
+ End Enum
Friend Downloader As TDownloader
Friend InfoForm As DownloadedInfoForm
Friend VideoDownloader As VideosDownloaderForm
diff --git a/SCrawler/My Project/AssemblyInfo.vb b/SCrawler/My Project/AssemblyInfo.vb
index 0e9b979..e3e7840 100644
--- a/SCrawler/My Project/AssemblyInfo.vb
+++ b/SCrawler/My Project/AssemblyInfo.vb
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
' by using the '*' as shown below:
'
-
-
+
+
diff --git a/SCrawler/PluginsEnvironment/Hosts/PluginHost.vb b/SCrawler/PluginsEnvironment/Hosts/PluginHost.vb
index 00ae531..d24b947 100644
--- a/SCrawler/PluginsEnvironment/Hosts/PluginHost.vb
+++ b/SCrawler/PluginsEnvironment/Hosts/PluginHost.vb
@@ -81,6 +81,8 @@ Namespace Plugin.Hosts
New PluginHost(New API.RedGifs.SiteSettings, _XML, GlobalPath, _Temp, _Imgs, _Vids),
New PluginHost(New API.TikTok.SiteSettings, _XML, GlobalPath, _Temp, _Imgs, _Vids),
New PluginHost(New API.LPSG.SiteSettings, _XML, GlobalPath, _Temp, _Imgs, _Vids),
+ New PluginHost(New API.PornHub.SiteSettings, _XML, GlobalPath, _Temp, _Imgs, _Vids),
+ New PluginHost(New API.Xhamster.SiteSettings, _XML, GlobalPath, _Temp, _Imgs, _Vids),
New PluginHost(New API.XVIDEOS.SiteSettings, _XML, GlobalPath, _Temp, _Imgs, _Vids)}
End Function
Friend Shared Function GetPluginsHosts(ByRef _XML As XmlFile, ByVal GlobalPath As SFile,
diff --git a/SCrawler/PluginsEnvironment/Hosts/PropertyValueHost.vb b/SCrawler/PluginsEnvironment/Hosts/PropertyValueHost.vb
index 648cb16..d4393c4 100644
--- a/SCrawler/PluginsEnvironment/Hosts/PropertyValueHost.vb
+++ b/SCrawler/PluginsEnvironment/Hosts/PropertyValueHost.vb
@@ -50,7 +50,7 @@ Namespace Plugin.Hosts
End With
If Not .ControlToolTip.IsEmptyString And Not TT Is Nothing Then TT.SetToolTip(Control, .ControlToolTip)
Else
- If Type Is GetType(Boolean) Then
+ If Type Is GetType(Boolean) Or .ThreeStates Then
Control = New CheckBox
If Not .ControlToolTip.IsEmptyString And Not TT Is Nothing Then TT.SetToolTip(Control, .ControlToolTip)
DirectCast(Control, CheckBox).ThreeState = .ThreeStates
diff --git a/SCrawler/PluginsEnvironment/Hosts/SettingsHost.vb b/SCrawler/PluginsEnvironment/Hosts/SettingsHost.vb
index 73ab6d8..813070a 100644
--- a/SCrawler/PluginsEnvironment/Hosts/SettingsHost.vb
+++ b/SCrawler/PluginsEnvironment/Hosts/SettingsHost.vb
@@ -11,7 +11,7 @@ Imports SCrawler.API.Base
Imports SCrawler.Plugin.Attributes
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.XML.Base
-Imports PersonalUtilities.Tools.WEB
+Imports PersonalUtilities.Tools.Web.Clients
Imports Download = SCrawler.Plugin.ISiteSettings.Download
Namespace Plugin.Hosts
Friend Class SettingsHost
@@ -71,11 +71,12 @@ Namespace Plugin.Hosts
Dim i% = PropList.FindIndex(Function(p) p.IsTaskCounter)
If i >= 0 Then Return CInt(PropList(i).Value)
End If
- If _TaskCountDefined.HasValue Then Return _TaskCountDefined.Value
+ If _TaskCountDefined.HasValue AndAlso _TaskCountDefined.Value > 0 Then Return _TaskCountDefined.Value
End If
Return Settings.MaxUsersJobsCount
End Get
End Property
+ Friend ReadOnly Property TaskGroupName As String = String.Empty
Friend ReadOnly Property HasSpecialOptions As Boolean = False
Private ReadOnly _ResponserGetMethod As MethodInfo
Private ReadOnly _ResponserIsContainer As Boolean = False
@@ -156,6 +157,8 @@ Namespace Plugin.Hosts
With DirectCast(a, SeparatedTasks)
If .TasksCount > 0 Then _TaskCountDefined = .TasksCount
End With
+ ElseIf TypeOf a Is TaskGroup Then
+ TaskGroupName = DirectCast(a, TaskGroup).Name
ElseIf TypeOf a Is SavedPosts Then
IsSavedPostsCompatible = True
ElseIf TypeOf a Is SpecialForm Then
@@ -291,8 +294,8 @@ Namespace Plugin.Hosts
If Not um Is Nothing Then
If TypeOf um Is IEnumerable(Of UserMedia) Then
Return um
- ElseIf TypeOf um Is IEnumerable(Of PluginUserMedia) Then
- Return um.ToObjectsList.ListCast(Of UserMedia)(New ListAddParams With {.Converter = Function(v) New UserMedia(DirectCast(v, PluginUserMedia))})
+ ElseIf TypeOf um Is IEnumerable(Of IUserMedia) Then
+ Return um.ToObjectsList.ListCast(Of UserMedia)(New ListAddParams With {.Converter = Function(v) New UserMedia(DirectCast(v, IUserMedia))})
End If
End If
Return Nothing
@@ -309,8 +312,8 @@ Namespace Plugin.Hosts
Throw New ArgumentNullException("IPluginContentProvider", $"Plugin [{Key}] does not provide user instance")
End If
End Function
- Friend Function GetUserPostUrl(ByVal UserID As String, ByVal PostID As String) As String
- Return Source.GetUserPostUrl(UserID, PostID)
+ Friend Function GetUserPostUrl(ByVal User As IPluginContentProvider, ByVal Media As IUserMedia) As String
+ Return Source.GetUserPostUrl(User, Media)
End Function
Private _AvailableValue As Boolean = True
Private _AvailableAsked As Boolean = False
diff --git a/SCrawler/PluginsEnvironment/Hosts/UserDataHost.vb b/SCrawler/PluginsEnvironment/Hosts/UserDataHost.vb
index 215055e..e9aed13 100644
--- a/SCrawler/PluginsEnvironment/Hosts/UserDataHost.vb
+++ b/SCrawler/PluginsEnvironment/Hosts/UserDataHost.vb
@@ -10,8 +10,8 @@ Imports System.Threading
Imports System.Reflection
Imports PersonalUtilities.Functions.XML
Imports SCrawler.API.Base
-Imports UStates = SCrawler.Plugin.PluginUserMedia.States
-Imports UTypes = SCrawler.Plugin.PluginUserMedia.Types
+Imports UStates = SCrawler.Plugin.UserMediaStates
+Imports UTypes = SCrawler.Plugin.UserMediaTypes
Namespace Plugin.Hosts
Friend Class UserDataHost : Inherits UserDataBase
Private ReadOnly UseInternalDownloader As Boolean
@@ -56,11 +56,11 @@ Namespace Plugin.Hosts
.DownloadDateFrom = DownloadDateFrom
.DownloadDateTo = DownloadDateTo
- .ExistingContentList = New List(Of PluginUserMedia)
- .TempMediaList = New List(Of PluginUserMedia)
+ .ExistingContentList = New List(Of IUserMedia)
+ .TempMediaList = New List(Of IUserMedia)
.TempPostsList = New List(Of String)
- If _ContentList.Count > 0 Then ExternalPlugin.ExistingContentList = _ContentList.Select(Function(u) u.PluginUserMedia).ToList
+ If _ContentList.Count > 0 Then ExternalPlugin.ExistingContentList = _ContentList.ListCast(Of IUserMedia)
ExternalPlugin.TempPostsList = ListAddList(Nothing, _TempPostsList)
.GetMedia()
@@ -81,8 +81,8 @@ Namespace Plugin.Hosts
Else
With ExternalPlugin
If .TempMediaList.ListExists Then .TempMediaList.Clear()
- .TempMediaList = New List(Of PluginUserMedia)
- .TempMediaList.ListAddList(_ContentNew.Select(Function(c) c.PluginUserMedia()))
+ .TempMediaList = New List(Of IUserMedia)
+ .TempMediaList.ListAddList(_ContentNew)
.Download()
_ContentNew.Clear()
If .TempMediaList.ListExists Then
diff --git a/SCrawler/SCrawler.vbproj b/SCrawler/SCrawler.vbproj
index a00ca80..3080712 100644
--- a/SCrawler/SCrawler.vbproj
+++ b/SCrawler/SCrawler.vbproj
@@ -158,8 +158,10 @@
+
+
@@ -180,6 +182,17 @@
+
+
+
+ OptionsForm.vb
+
+
+ Form
+
+
+
+
RedditViewSettingsForm.vb
@@ -190,14 +203,12 @@
+
+
+
+
-
- SettingsForm.vb
-
-
- Form
-
@@ -258,6 +269,7 @@
Form
+
@@ -385,6 +397,7 @@
Component
+
VideosDownloaderForm.vb
@@ -407,12 +420,12 @@
OptionsForm.vb
+
+ OptionsForm.vb
+
RedditViewSettingsForm.vb
-
- SettingsForm.vb
-
ChannelsStatsForm.vb
@@ -512,6 +525,9 @@
+
+ PreserveNewest
+
MyApplicationCodeGenerator
@@ -564,6 +580,19 @@
+
+
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
diff --git a/SCrawler/SettingsCLS.vb b/SCrawler/SettingsCLS.vb
index b84817f..562438e 100644
--- a/SCrawler/SettingsCLS.vb
+++ b/SCrawler/SettingsCLS.vb
@@ -17,6 +17,7 @@ Imports SCrawler.Plugin.Hosts
Imports SCrawler.DownloadObjects
Friend Class SettingsCLS : Implements IDisposable
Friend Const DefaultMaxDownloadingTasks As Integer = 5
+ Friend Const TaskStackNamePornSite As String = "Porn sites"
Friend Const Name_Node_Sites As String = "Sites"
Private Const SitesValuesSeparator As String = ","
Friend Const CookieEncryptKey As String = "SCrawlerCookiesEncryptKeyword"
@@ -256,15 +257,14 @@ Friend Class SettingsCLS : Implements IDisposable
If UsersList.Count > 0 Then
Dim cUsers As List(Of UserInfo) = UsersList.Where(Function(u) u.IncludedInCollection And Not u.Protected).ToList
If cUsers.ListExists Then
- Dim d As New Dictionary(Of SFile, List(Of UserInfo))
+ Dim d As New Dictionary(Of String, List(Of UserInfo))
cUsers = cUsers.ListForEachCopy(Of List(Of UserInfo))(Function(ByVal f As UserInfo, ByVal f_indx As Integer) As UserInfo
- Dim m% = IIf(f.Merged, 1, 2)
+ Dim m% = IIf(f.Merged Or f.IsVirual, 1, 2)
If Not f.Protected AndAlso SFile.GetPath(f.File.CutPath(m - 1).Path).Exists(SFO.Path, False) Then
- Dim fp As SFile = SFile.GetPath(f.File.CutPath(m).Path)
- If Not d.ContainsKey(fp) Then
- d.Add(fp, New List(Of UserInfo) From {f})
+ If Not d.ContainsKey(f.CollectionName) Then
+ d.Add(f.CollectionName, New List(Of UserInfo) From {f})
Else
- d(f.File.CutPath(m).Path).Add(f)
+ d(f.CollectionName).Add(f)
End If
Return f
Else
@@ -274,8 +274,8 @@ Friend Class SettingsCLS : Implements IDisposable
End Function, True)
Dim v%
If d.Count > 0 Then
- For Each kv In d
- Users.Add(New UserDataBind(kv.Value(0).CollectionName))
+ For Each kv As KeyValuePair(Of String, List(Of UserInfo)) In d
+ Users.Add(New UserDataBind(kv.Key))
MainFrameObj.CollectionHandler(DirectCast(Users(Users.Count - 1), UserDataBind))
For v = 0 To kv.Value.Count - 1 : DirectCast(Users(Users.Count - 1), UserDataBind).Add(kv.Value(v), False) : Next
Next
diff --git a/SCrawler/SiteResources.Designer.vb b/SCrawler/SiteResources.Designer.vb
index cd72662..3cfbb97 100644
--- a/SCrawler/SiteResources.Designer.vb
+++ b/SCrawler/SiteResources.Designer.vb
@@ -104,6 +104,26 @@ Namespace My.Resources
End Get
End Property
+ '''
+ ''' Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
+ '''
+ Friend Shared ReadOnly Property PornHubIcon_16() As System.Drawing.Icon
+ Get
+ Dim obj As Object = ResourceManager.GetObject("PornHubIcon_16", resourceCulture)
+ Return CType(obj,System.Drawing.Icon)
+ End Get
+ End Property
+
+ '''
+ ''' Looks up a localized resource of type System.Drawing.Bitmap.
+ '''
+ Friend Shared ReadOnly Property PornHubPic_16() As System.Drawing.Bitmap
+ Get
+ Dim obj As Object = ResourceManager.GetObject("PornHubPic_16", resourceCulture)
+ Return CType(obj,System.Drawing.Bitmap)
+ End Get
+ End Property
+
'''
''' Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
'''
@@ -184,6 +204,26 @@ Namespace My.Resources
End Get
End Property
+ '''
+ ''' Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
+ '''
+ Friend Shared ReadOnly Property XhamsterIcon_32() As System.Drawing.Icon
+ Get
+ Dim obj As Object = ResourceManager.GetObject("XhamsterIcon_32", resourceCulture)
+ Return CType(obj,System.Drawing.Icon)
+ End Get
+ End Property
+
+ '''
+ ''' Looks up a localized resource of type System.Drawing.Bitmap.
+ '''
+ Friend Shared ReadOnly Property XhamsterPic_32() As System.Drawing.Bitmap
+ Get
+ Dim obj As Object = ResourceManager.GetObject("XhamsterPic_32", resourceCulture)
+ Return CType(obj,System.Drawing.Bitmap)
+ End Get
+ End Property
+
'''
''' Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
'''
diff --git a/SCrawler/SiteResources.resx b/SCrawler/SiteResources.resx
index 74a01bc..fc93ecb 100644
--- a/SCrawler/SiteResources.resx
+++ b/SCrawler/SiteResources.resx
@@ -130,6 +130,12 @@
Content\Pictures\SitePictures\LPSGPic_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+ Content\Icons\SiteIcons\PornHubIcon_16.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ Content\Pictures\SitePictures\PornHubPic_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
Content\Icons\SiteIcons\RedditIcon_128.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
@@ -154,6 +160,12 @@
Content\Pictures\SitePictures\TwitterPic_400.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+ Content\Icons\SiteIcons\XhamsterIcon_32.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ Content\Pictures\SitePictures\XhamsterPic_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
Content\Icons\SiteIcons\XvideosIcon_48.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
diff --git a/SCrawler/UserFinder.vb b/SCrawler/UserFinder.vb
new file mode 100644
index 0000000..77be89d
--- /dev/null
+++ b/SCrawler/UserFinder.vb
@@ -0,0 +1,334 @@
+' Copyright (C) 2023 Andy https://github.com/AAndyProgram
+' This program is free software: you can redistribute it and/or modify
+' it under the terms of the GNU General Public License as published by
+' the Free Software Foundation, either version 3 of the License, or
+' (at your option) any later version.
+'
+' This program is distributed in the hope that it will be useful,
+' but WITHOUT ANY WARRANTY
+Imports SCrawler.API.Base
+Imports PersonalUtilities.Functions.XML
+Imports PersonalUtilities.Functions.Messaging
+Imports PersonalUtilities.Forms
+Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons
+Friend Class UserFinder : Implements IDisposable
+ Private Structure SkippedUser
+ Friend User As UserInfo
+ Friend Reason As String
+ End Structure
+ Private ReadOnly Paths As List(Of SFile)
+ Private ReadOnly FoundUsers As List(Of UserInfo)
+ Private ReadOnly Added As List(Of UserInfo)
+ Private ReadOnly Skipped As List(Of SkippedUser)
+ Private ReadOnly Duplicates As List(Of UserInfo)
+ Private ReadOnly IgnoredCollections As List(Of String)
+ Private ReadOnly NotRecognized As List(Of SFile)
+ Private OriginalLocations As Boolean = False
+ Private PathStr As String
+ Private Const LabelImported As String = "Imported"
+ Private ReadOnly Labels As List(Of String)
+ Friend ReadOnly Property Count As Integer
+ Get
+ Return FoundUsers.Count
+ End Get
+ End Property
+ Friend Sub New(ByVal Path As SFile)
+ Paths = New List(Of SFile) From {Path}
+ PathStr = vbCr & Path.ToString
+ FoundUsers = New List(Of UserInfo)
+ Added = New List(Of UserInfo)
+ Skipped = New List(Of SkippedUser)
+ Duplicates = New List(Of UserInfo)
+ IgnoredCollections = New List(Of String)
+ NotRecognized = New List(Of SFile)
+ Labels = New List(Of String)
+ End Sub
+ Private Function GetFiles() As List(Of SFile)
+ Dim files As New List(Of SFile)
+ If Paths.Count > 0 Then
+ For Each path As SFile In Paths
+ files.ListAddList(SFile.GetFiles(path, "User_*.xml", IO.SearchOption.AllDirectories, EDP.ReturnValue), LAP.NotContainsOnly)
+ Next
+ End If
+ Return files
+ End Function
+ Friend Function Find(ByVal OriginalLocations As Boolean) As Boolean
+ Try
+ Me.OriginalLocations = OriginalLocations
+ If OriginalLocations Then
+ Paths.Clear()
+ PathStr = String.Empty
+ Paths.ListAddList(Settings.Plugins.Select(Function(p) p.Settings.Path), LAP.NotContainsOnly)
+ Paths.ListAddValue(Settings.CollectionsPathF, LAP.NotContainsOnly)
+ PathStr = vbCr & Paths.ListToString(vbCr)
+ End If
+ FoundUsers.Clear()
+ If Paths.Count > 0 Then
+ Dim files As List(Of SFile) = GetFiles()
+ If files.ListExists Then files.RemoveAll(Function(ff) ff.Name.EndsWith("_Data"))
+ If files.ListExists Then
+ Dim x As XmlFile
+ Dim xErr As New ErrorsDescriber(EDP.None)
+ Dim u As UserInfo
+ For Each f As SFile In files
+ x = New XmlFile(f, Protector.Modes.All, False) With {.XmlReadOnly = True}
+ x.LoadData(xErr)
+ If Not x.HasError And x.Count > 0 Then
+ u = New UserInfo With {
+ .Name = x.Value(UserDataBase.Name_UserName),
+ .Site = x.Value(UserInfo.Name_Site),
+ .Plugin = x.Value(UserInfo.Name_Plugin),
+ .File = f,
+ .SpecialPath = x.Value(UserInfo.Name_SpecialPath),
+ .SpecialCollectionPath = x.Value(UserInfo.Name_SpecialCollectionPath),
+ .UserModel = x.Value(UserInfo.Name_Model_User).FromXML(Of Integer)(UsageModel.Default),
+ .CollectionModel = x.Value(UserInfo.Name_Model_Collection).FromXML(Of Integer)(UsageModel.Default),
+ .CollectionName = x.Value(UserInfo.Name_Collection),
+ .IsChannel = x.Value(UserInfo.Name_IsChannel).FromXML(Of Boolean)(False)
+ }
+#Disable Warning BC40000
+ If x.Contains(UserDataBase.Name_DataMerging) Then
+ u.Merged = x.Value(UserDataBase.Name_DataMerging).FromXML(Of Boolean)(False)
+ Else
+ u.Merged = x.Value(UserInfo.Name_Merged).FromXML(Of Boolean)(False)
+ End If
+#Enable Warning
+ FoundUsers.Add(u)
+ Else
+ If x.HasError Then NotRecognized.Add(f)
+ End If
+ x.Dispose()
+ Next
+ End If
+ End If
+ Return Count > 0
+ Catch ex As Exception
+ Return ErrorsDescriber.Execute(EDP.LogMessageValue, ex, $"[UserFinder.Find:{PathStr}]", False)
+ End Try
+ End Function
+ Friend Sub Verify()
+ Try
+ Added.Clear()
+ Skipped.Clear()
+ Duplicates.Clear()
+ IgnoredCollections.Clear()
+ If Count > 0 Then
+ Dim u As UserInfo
+ Dim s As Plugin.Hosts.SettingsHost
+ Dim pIndx%
+ For i% = 0 To Count - 1
+ u = FoundUsers(i)
+ s = Nothing
+ If u.Plugin.IsEmptyString Then
+ pIndx = Settings.Plugins.FindIndex(Function(pp) pp.Name.ToLower = u.Site.ToLower)
+ If pIndx >= 0 Then s = Settings.Plugins(pIndx).Settings
+ Else
+ s = Settings(u.Plugin)
+ End If
+ If Not s Is Nothing Then
+ u.Plugin = s.Key
+ If Not OriginalLocations Then
+ If u.IncludedInCollection And u.UserModel = UsageModel.Default Then
+ u.SpecialCollectionPath = u.File.CutPath(IIf(u.Merged, 1, 2)).Path.CSFileP
+ Else
+ u.SpecialPath = u.File.CutPath(1).Path.CSFileP
+ End If
+ End If
+ u.UpdateUserFile()
+ If Settings.UsersList.Contains(u) Then
+ Duplicates.Add(u)
+ ElseIf u.File.Exists And (u.CollectionName.IsEmptyString OrElse
+ IgnoredCollections.Contains(u.CollectionName.ToLower) OrElse
+ Not Settings.UsersList.Exists(Function(uu) uu.CollectionName.StringToLower = u.CollectionName.ToLower)) Then
+ Added.Add(u)
+ If Not IgnoredCollections.Contains(u.CollectionName) Then IgnoredCollections.Add(u.CollectionName)
+ Else
+ Skipped.Add(New SkippedUser With {.User = u, .Reason = "file path generation / collection exists"})
+ End If
+ Else
+ Skipped.Add(New SkippedUser With {.User = u, .Reason = "user plugin not recognized"})
+ End If
+ Next
+ End If
+ Catch ex As Exception
+ ErrorsDescriber.Execute(EDP.LogMessageValue, ex, $"[UserFinder.Verify:{PathStr}]")
+ End Try
+ End Sub
+ Friend Function Dialog() As Boolean
+ Const MsgTitle$ = "Import users"
+ Const DesignNode$ = "ImportUserSelector"
+ Try
+ Dim uStr As Func(Of UserInfo, String) = Function(u) $"{IIf(u.CollectionName.IsEmptyString, String.Empty, $"[{u.CollectionName}]: ")} {u.Site} - {u.Name}"
+ Dim uc As Comparison(Of UserInfo) = Function(ByVal x As UserInfo, ByVal y As UserInfo) As Integer
+ If Not x.CollectionName.IsEmptyString And Not y.CollectionName.IsEmptyString Then
+ Return x.CollectionName.CompareTo(y.CollectionName)
+ ElseIf Not x.CollectionName.IsEmptyString Then
+ Return -1
+ ElseIf Not y.CollectionName.IsEmptyString Then
+ Return 1
+ Else
+ Return uStr(x).CompareTo(uStr(y))
+ End If
+ End Function
+ Dim __added$ = String.Empty
+ Dim __dup$ = String.Empty
+ Dim __skipped$ = String.Empty
+ Dim __labelText$
+ If Added.Count > 0 Then Added.Sort(uc) : __added = $"The following users will be added to SCrawler:{vbCr}{Added.Select(uStr).ListToString(vbCr)}"
+ If Duplicates.Count > 0 Then Duplicates.Sort(uc) : __dup = $"The following users already exist In SCrawler and will not be added:{vbCr}{Duplicates.Select(uStr).ListToString(vbCr)}"
+ If Skipped.Count > 0 Then
+ Skipped.Sort(Function(x, y) uc(x.User, y.User))
+ __skipped = $"The following users will not be added to SCrawler{vbCr}{Skipped.Select(Function(u) $"{uStr(u.User)} ({u.Reason})").ListToString(vbCr)}"
+ End If
+ __added = {__added, __dup, __skipped}.ListToString(vbCr.StringDup(2))
+ If Not __added.IsEmptyString Then
+ Using t As New TextSaver($"LOGs\ImportUsers.txt") With {.ForceAddDateTimeToFileName = True}
+ t.Append(__added)
+ If Added.Count > 0 Then
+ t.AppendLine(vbNewLine.StringDup(2))
+ t.AppendLine($"Added:{vbNewLine}{Added.Select(Function(u) u.File.ToString).ListToString(vbNewLine)}")
+ End If
+ If Duplicates.Count > 0 Then
+ t.AppendLine(vbNewLine.StringDup(2))
+ t.AppendLine($"Duplicates:{vbNewLine}{Duplicates.Select(Function(u) u.File.ToString).ListToString(vbNewLine)}")
+ End If
+ If Skipped.Count > 0 Then
+ t.AppendLine(vbNewLine.StringDup(2))
+ t.AppendLine($"Duplicates:{vbNewLine}{Skipped.Select(Function(u) u.User.File.ToString).ListToString(vbNewLine)}")
+ End If
+ If NotRecognized.Count > 0 Then
+ t.AppendLine(vbNewLine.StringDup(2))
+ t.AppendLine($"Not recognized:{vbNewLine}{NotRecognized.ListToString(vbNewLine)}")
+ End If
+ t.Save()
+ End Using
+ Dim msg As New MMessage(__added, MsgTitle,, vbQuestion) With {.Editable = True}
+ Dim BttSelect As New MsgBoxButton("Select", "Select users to import") With {
+ .IsDialogResultButton = False,
+ .CallBack = Sub(r, m, b)
+ If Not Settings.Design.Contains(DesignNode) Then Settings.Design.Add(DesignNode, String.Empty)
+ Using f As New SimpleListForm(Of UserInfo)(Added, Settings.Design(DesignNode)) With {
+ .Icon = My.Resources.UsersIcon_32,
+ .FormText = MsgTitle,
+ .Mode = SimpleListFormModes.CheckedItemsAutoCheckAll,
+ .ButtonInsertKey = Nothing,
+ .Provider = New CustomProvider(Function(v, d, p, n, e) uStr(v))
+ }
+ If f.ShowDialog() = DialogResult.OK Then
+ Added.Clear()
+ Added.ListAddList(f.DataResult)
+ End If
+ End Using
+ End Sub}
+ msg.Buttons = If(Added.Count > 0, {New MsgBoxButton("Process"), BttSelect, New MsgBoxButton("Cancel")}, Nothing)
+ If MsgBoxE(msg) = 0 Then
+ If Added.Count > 0 Then
+ Add()
+ If Labels.Count = 0 Then
+ __labelText = String.Empty
+ ElseIf Labels.Count = 1 Then
+ __labelText = $"{vbCr}{vbCr}The '{Labels(0)}' label has been added to each user."
+ Else
+ __labelText = $"{vbCr}{vbCr}The following labels have been added to each user: {Labels.ListToString}."
+ End If
+ MsgBoxE(New MMessage($"Restart SCrawler to take effect.{__labelText}{vbCr}{vbCr}" &
+ $"The following users have been added to SCrawler:{vbCr}" &
+ Added.Select(uStr).ListToString(vbCr), MsgTitle) With {.Editable = True})
+ Return True
+ End If
+ Else
+ If Added.Count > 0 Then MsgBoxE({"Operation canceled", MsgTitle})
+ End If
+ Else
+ MsgBoxE({"No users found", MsgTitle})
+ End If
+ Return False
+ Catch ex As Exception
+ Return ErrorsDescriber.Execute(EDP.LogMessageValue, ex, $"[UserFinder.Dialog:{PathStr}]", False)
+ End Try
+ End Function
+ Friend Sub Add()
+ Try
+ Labels.Clear()
+ Select Case MsgBoxE({"Do you want to add an 'Imported' label to each user?", "User labels"}, vbQuestion,,,
+ {"Yes", New MsgBoxButton("Select", "Select labels to add"), "No"}).Index
+ Case 0 : Labels.Add(LabelImported)
+ Case 1
+ Labels.ListAddList(GetLabels())
+ If Labels.Count = 0 AndAlso MsgBoxE({"You have not selected any labels." &
+ "Do you want to add an 'Imported' label to each user?", "User labels"},
+ vbExclamation + vbYesNo) = vbYes Then Labels.Add(LabelImported)
+ End Select
+ If Labels.Count > 0 Then
+ Dim x As XmlFile
+ Dim l As List(Of String)
+ Dim lp As New ListAddParams(LAP.NotContainsOnly)
+ For Each u As UserInfo In Added
+ x = New XmlFile(u.File, Protector.Modes.All)
+ l = x.Value(UserDataBase.Name_LabelsName).StringToList(Of String, List(Of String))("|", EDP.ReturnValue)
+ If Not l.ListExists Then l = New List(Of String)
+ l.ListAddList(Labels, lp)
+ x.Value(UserDataBase.Name_LabelsName) = l.ListToString("|")
+ x.UpdateData()
+ x.Dispose()
+ Next
+ End If
+ Settings.UsersList.AddRange(Added)
+ Settings.UpdateUsersList()
+ Catch ex As Exception
+ ErrorsDescriber.Execute(EDP.LogMessageValue, ex, $"[UserFinder.Add:{PathStr}]")
+ End Try
+ End Sub
+ Private Function GetLabels() As List(Of String)
+ Const DesignNode$ = "ImportUserSelectorLabels"
+ Try
+ Dim __add As EventHandler(Of SimpleListFormEventArgs) = Sub(sender, e) e.ValueNew = InputBoxE("Enter a new label name", "New label").IfNullOrEmptyE(Nothing)
+ Dim l As List(Of String) = ListAddList(Nothing, Settings.Labels, LAP.NotContainsOnly).ListAddValue(LabelImported, LAP.NotContainsOnly)
+ If l.Count > 0 Then l.Sort()
+ If Not Settings.Design.Contains(DesignNode) Then Settings.Design.Add(DesignNode, String.Empty)
+ Using f As New SimpleListForm(Of String)(l, Settings.Design(DesignNode)) With {
+ .Icon = My.Resources.TagIcon_32,
+ .FormText = "Labels for imported users",
+ .Mode = SimpleListFormModes.CheckedItems,
+ .Buttons = {ADB.Add}
+ }
+ f.DataSelected.Add(LabelImported)
+ AddHandler f.AddClick, __add
+ If f.ShowDialog() = DialogResult.OK Then
+ l.Clear()
+ l.AddRange(f.DataResult)
+ Return l
+ End If
+ End Using
+ Return Nothing
+ Catch ex As Exception
+ Return ErrorsDescriber.Execute(EDP.LogMessageValue, ex, $"[UserFinder.GetLabels:{PathStr}]")
+ End Try
+ End Function
+#Region "IDisposable Support"
+ Private disposedValue As Boolean = False
+ Protected Overridable Sub Dispose(ByVal disposing As Boolean)
+ If Not disposedValue Then
+ If disposing Then
+ Paths.Clear()
+ FoundUsers.Clear()
+ Added.Clear()
+ Skipped.Clear()
+ Duplicates.Clear()
+ IgnoredCollections.Clear()
+ NotRecognized.Clear()
+ Labels.Clear()
+ End If
+ disposedValue = True
+ End If
+ End Sub
+ Protected Overrides Sub Finalize()
+ Dispose(False)
+ MyBase.Finalize()
+ End Sub
+ Friend Sub Dispose() Implements IDisposable.Dispose
+ Dispose(True)
+ GC.SuppressFinalize(Me)
+ End Sub
+#End Region
+End Class
\ No newline at end of file
diff --git a/SCrawler/UserInfo.vb b/SCrawler/UserInfo.vb
index 191225f..64b523f 100644
--- a/SCrawler/UserInfo.vb
+++ b/SCrawler/UserInfo.vb
@@ -15,22 +15,38 @@ Imports DownOptions = SCrawler.Plugin.ISiteSettings.Download
Partial Friend Module MainMod
Friend Structure UserInfo : Implements IComparable(Of UserInfo), IEquatable(Of UserInfo), ICloneable, IEContainerProvider
#Region "XML Names"
+ Friend Const Name_UserNode As String = "User"
Friend Const Name_Site As String = "Site"
Friend Const Name_Plugin As String = "Plugin"
Friend Const Name_Collection As String = "Collection"
+ Friend Const Name_Model_User As String = "ModelUser"
+ Friend Const Name_Model_Collection As String = "ModelCollection"
Friend Const Name_Merged As String = "Merged"
Friend Const Name_IsChannel As String = "IsChannel"
Friend Const Name_SpecialPath As String = "SpecialPath"
- Friend Const Name_UserNode As String = "User"
+ Friend Const Name_SpecialCollectionPath As String = "SpecialCollectionPath"
#End Region
+#Region "Declarations"
Friend Name As String
Friend Site As String
Friend Plugin As String
Friend File As SFile
Friend SpecialPath As SFile
+ Friend SpecialCollectionPath As SFile
Friend Merged As Boolean
- Friend IncludedInCollection As Boolean
+ Friend ReadOnly Property IncludedInCollection As Boolean
+ Get
+ Return Not CollectionName.IsEmptyString
+ End Get
+ End Property
+ Friend ReadOnly Property IsVirual As Boolean
+ Get
+ Return CollectionModel = UsageModel.Virtual Or UserModel = UsageModel.Virtual
+ End Get
+ End Property
+ Friend UserModel As UsageModel
Friend CollectionName As String
+ Friend CollectionModel As UsageModel
Friend IsChannel As Boolean
Friend [Protected] As Boolean
Friend ReadOnly Property DownloadOption As DownOptions
@@ -42,15 +58,12 @@ Partial Friend Module MainMod
End If
End Get
End Property
- Friend Sub New(ByVal _Name As String, ByVal Host As SettingsHost, Optional ByVal Collection As String = Nothing,
- Optional ByVal _Merged As Boolean = False, Optional ByVal _SpecialPath As SFile = Nothing)
+#End Region
+#Region "Initializers"
+ Friend Sub New(ByVal _Name As String, ByVal Host As SettingsHost)
Name = _Name
Site = Host.Name
Plugin = Host.Key
- IncludedInCollection = Not Collection.IsEmptyString
- CollectionName = Collection
- Merged = _Merged
- SpecialPath = _SpecialPath
UpdateUserFile()
End Sub
Private Sub New(ByVal x As EContainer)
@@ -58,9 +71,11 @@ Partial Friend Module MainMod
Site = x.Attribute(Name_Site).Value
Plugin = x.Attribute(Name_Plugin).Value
CollectionName = x.Attribute(Name_Collection).Value
- IncludedInCollection = Not CollectionName.IsEmptyString
+ CollectionModel = x.Attribute(Name_Model_Collection).Value.FromXML(Of Integer)(UsageModel.Default)
+ UserModel = x.Attribute(Name_Model_User).Value.FromXML(Of Integer)(UsageModel.Default)
Merged = x.Attribute(Name_Merged).Value.FromXML(Of Boolean)(False)
SpecialPath = SFile.GetPath(x.Attribute(Name_SpecialPath).Value)
+ SpecialCollectionPath = SFile.GetPath(x.Attribute(Name_SpecialCollectionPath).Value)
IsChannel = x.Attribute(Name_IsChannel).Value.FromXML(Of Boolean)(False)
End Sub
Friend Sub New(ByVal c As Reddit.Channel)
@@ -76,15 +91,21 @@ Partial Friend Module MainMod
Public Shared Widening Operator CType(ByVal u As UserInfo) As String
Return u.Name
End Operator
+#End Region
+#Region "Operators"
Public Shared Operator =(ByVal x As UserInfo, ByVal y As UserInfo)
Return x.Equals(y)
End Operator
Public Shared Operator <>(ByVal x As UserInfo, ByVal y As UserInfo)
Return Not x.Equals(y)
End Operator
+#End Region
+#Region "ToString"
Public Overrides Function ToString() As String
Return Name
End Function
+#End Region
+#Region "FilePath"
Friend Sub UpdateUserFile()
File = New SFile With {
.Separator = "\",
@@ -95,13 +116,15 @@ Partial Friend Module MainMod
End Sub
Private Function GetFilePathByParams() As String
If [Protected] Then Return String.Empty
+ Dim ColPath$ = If(SpecialCollectionPath.IsEmptyString, Settings.CollectionsPathF, SpecialCollectionPath).PathNoSeparator
+ If SpecialCollectionPath.IsEmptyString Then ColPath &= $"\{CollectionName}"
If Not SpecialPath.IsEmptyString Then
Return $"{SpecialPath.PathWithSeparator}{SettingsFolderName}"
ElseIf Merged And IncludedInCollection Then
- Return $"{Settings.CollectionsPathF.PathNoSeparator}\{CollectionName}\{SettingsFolderName}"
+ Return $"{ColPath}\{SettingsFolderName}"
Else
- If IncludedInCollection Then
- Return $"{Settings.CollectionsPathF.PathNoSeparator}\{CollectionName}\{Site}_{Name}\{SettingsFolderName}"
+ If IncludedInCollection And Not IsVirual Then
+ Return $"{ColPath}\{Site}_{Name}\{SettingsFolderName}"
ElseIf Not Settings(Plugin) Is Nothing Then
Return $"{Settings(Plugin).Path.PathNoSeparator}\{Name}\{SettingsFolderName}"
Else
@@ -111,14 +134,21 @@ Partial Friend Module MainMod
End If
End If
End Function
+#End Region
+#Region "ToEContainer Support"
Friend Function ToEContainer(Optional ByVal e As ErrorsDescriber = Nothing) As EContainer Implements IEContainerProvider.ToEContainer
Return New EContainer(Name_UserNode, Name, {New EAttribute(Name_Site, Site),
New EAttribute(Name_Plugin, Plugin),
New EAttribute(Name_Collection, CollectionName),
+ New EAttribute(Name_Model_User, CInt(UserModel)),
+ New EAttribute(Name_Model_Collection, CInt(CollectionModel)),
New EAttribute(Name_Merged, Merged.BoolToInteger),
New EAttribute(Name_IsChannel, IsChannel.BoolToInteger),
- New EAttribute(Name_SpecialPath, SpecialPath.PathWithSeparator)})
+ New EAttribute(Name_SpecialPath, SpecialPath.PathWithSeparator),
+ New EAttribute(Name_SpecialCollectionPath, SpecialCollectionPath.PathWithSeparator)})
End Function
+#End Region
+#Region "IComparable Support"
Friend Function CompareTo(ByVal Other As UserInfo) As Integer Implements IComparable(Of UserInfo).CompareTo
If Site = Other.Site Then
Return Name.CompareTo(Other.Name)
@@ -126,12 +156,16 @@ Partial Friend Module MainMod
Return Site.CompareTo(Other.Site)
End If
End Function
+#End Region
+#Region "IEquatable Support"
Friend Overloads Function Equals(ByVal Other As UserInfo) As Boolean Implements IEquatable(Of UserInfo).Equals
- Return Site = Other.Site And Name = Other.Name
+ Return Site.StringToLower = Other.Site.StringToLower And Name.StringToLower = Other.Name.StringToLower
End Function
Public Overloads Overrides Function Equals(ByVal Obj As Object) As Boolean
Return Equals(DirectCast(Obj, UserInfo))
End Function
+#End Region
+#Region "ICloneable Support"
Friend Function Clone() As Object Implements ICloneable.Clone
Return New UserInfo With {
.Name = Name,
@@ -140,11 +174,13 @@ Partial Friend Module MainMod
.File = File,
.SpecialPath = SpecialPath,
.Merged = Merged,
- .IncludedInCollection = IncludedInCollection,
.CollectionName = CollectionName,
+ .CollectionModel = CollectionModel,
+ .UserModel = UserModel,
.IsChannel = IsChannel,
.[Protected] = [Protected]
}
End Function
+#End Region
End Structure
End Module
\ No newline at end of file
diff --git a/SCrawler/UserSearchForm.vb b/SCrawler/UserSearchForm.vb
index 92dc7bf..00bc05a 100644
--- a/SCrawler/UserSearchForm.vb
+++ b/SCrawler/UserSearchForm.vb
@@ -65,6 +65,7 @@ Friend Class UserSearchForm
If e.KeyCode = Keys.Escape Then Hide() : e.Handled = True
End Sub
Private Sub UserSearchForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
+ MyView.Dispose()
Results.Clear()
End Sub
Private Sub TXT_SEARCH_TextChanged(sender As Object, e As EventArgs) Handles TXT_SEARCH.TextChanged