diff --git a/Changelog.md b/Changelog.md index 3543ed6..2820ecb 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,25 @@ +# 2023.3.1.0 + +*2023-03-01* + +- Added + - **Path plugin.** Now you can add paths. *This may be suitable if you want to add a collection of media data to a specific user collection.* + - MainWindow: setting a background image + - MainWindow: setting background color and font color + - Feed: setting background color and font color + - Feed: (Request #108) center the image in the feed grid + - Users: the ability to use user site name (if it exists) as a friendly name (on supported sites: Reddit, Twitter, Instagram) + - Users: the ability to update user site name every time + - Twitter: ability to download images using MD5 comparison to protect against duplicate downloads *(this may be suitable for the users who post the same image many times)* + - Twitter: one-time duplicate image removal option + - XHamster: (Request #107) added channels downloading +- Updated + - Updated ffmpeg to version [5.1.2](https://github.com/GyanD/codexffmpeg/releases/tag/5.1.2) +- Fixed + - PornHub: (Issue #106) unicode titles + - (Issue #106) problem with non-Latin characters + - ffmpeg: maximum input length error when merging parts of files + # 2023.2.5.0 *2023-02-05* diff --git a/ProgramScreenshots/SettingsGlobalBasis.png b/ProgramScreenshots/SettingsGlobalBasis.png index d8b6f12..9cd66bc 100644 Binary files a/ProgramScreenshots/SettingsGlobalBasis.png and b/ProgramScreenshots/SettingsGlobalBasis.png differ diff --git a/ProgramScreenshots/SettingsGlobalDefaults.png b/ProgramScreenshots/SettingsGlobalDefaults.png index 944ee83..ff0b745 100644 Binary files a/ProgramScreenshots/SettingsGlobalDefaults.png and b/ProgramScreenshots/SettingsGlobalDefaults.png differ diff --git a/ProgramScreenshots/SettingsGlobalDownloading.png b/ProgramScreenshots/SettingsGlobalDownloading.png index 17bdf7b..c8717ea 100644 Binary files a/ProgramScreenshots/SettingsGlobalDownloading.png and b/ProgramScreenshots/SettingsGlobalDownloading.png differ diff --git a/ProgramScreenshots/SettingsGlobalFeed.png b/ProgramScreenshots/SettingsGlobalFeed.png index 2e15371..6ad8d21 100644 Binary files a/ProgramScreenshots/SettingsGlobalFeed.png and b/ProgramScreenshots/SettingsGlobalFeed.png differ diff --git a/ProgramScreenshots/SettingsSiteInstagram.png b/ProgramScreenshots/SettingsSiteInstagram.png index a532f69..55a02ee 100644 Binary files a/ProgramScreenshots/SettingsSiteInstagram.png and b/ProgramScreenshots/SettingsSiteInstagram.png differ diff --git a/ProgramScreenshots/SettingsSiteTwitter.png b/ProgramScreenshots/SettingsSiteTwitter.png index 224880c..fb193df 100644 Binary files a/ProgramScreenshots/SettingsSiteTwitter.png and b/ProgramScreenshots/SettingsSiteTwitter.png differ diff --git a/ProgramScreenshots/SettingsSiteXvideosAdditional.png b/ProgramScreenshots/SettingsSiteXvideosAdditional.png index d226d40..29c4854 100644 Binary files a/ProgramScreenshots/SettingsSiteXvideosAdditional.png and b/ProgramScreenshots/SettingsSiteXvideosAdditional.png differ diff --git a/ProgramScreenshots/SettingsTwitterUser.png b/ProgramScreenshots/SettingsTwitterUser.png new file mode 100644 index 0000000..d47197f Binary files /dev/null and b/ProgramScreenshots/SettingsTwitterUser.png differ diff --git a/ProgramScreenshots/TrayContextMenu.png b/ProgramScreenshots/TrayContextMenu.png index f809dc4..4b7e67c 100644 Binary files a/ProgramScreenshots/TrayContextMenu.png and b/ProgramScreenshots/TrayContextMenu.png differ diff --git a/SCrawler/API/Base/Declarations.vb b/SCrawler/API/Base/Declarations.vb index b1be790..714cbad 100644 --- a/SCrawler/API/Base/Declarations.vb +++ b/SCrawler/API/Base/Declarations.vb @@ -9,5 +9,8 @@ Namespace API.Base Friend Module Declarations Friend ReadOnly LNC As New ListAddParams(LAP.NotContainsOnly) + Friend ReadOnly TitleHtmlConverter As Func(Of String, String) = + Function(Input) SymbolsConverter.HTML.Decode(SymbolsConverter.Convert(Input, EDP.ReturnValue), EDP.ReturnValue). + StringRemoveWinForbiddenSymbols().StringTrim() End Module End Namespace \ No newline at end of file diff --git a/SCrawler/API/Base/Structures.vb b/SCrawler/API/Base/Structures.vb index 29fa892..df56a67 100644 --- a/SCrawler/API/Base/Structures.vb +++ b/SCrawler/API/Base/Structures.vb @@ -187,7 +187,7 @@ Namespace API.Base Post = New UserPost With { .ID = e.Attribute(Name_MediaPostID).Value, - .[Date] = AConvert(Of Date)(e.Attribute(Name_MediaPostDate).Value, ParsersDataDateProvider, Nothing) + .[Date] = AConvert(Of Date)(e.Attribute(Name_MediaPostDate).Value, DateTimeDefaultProvider, Nothing) } End Sub Public Shared Widening Operator CType(ByVal _URL As String) As UserMedia @@ -225,7 +225,7 @@ Namespace API.Base New EAttribute(Name_MediaFile, File.File), New EAttribute(Name_SpecialFolder, SpecialFolder), New EAttribute(Name_MediaPostID, Post.ID), - New EAttribute(Name_MediaPostDate, AConvert(Of String)(Post.Date, ParsersDataDateProvider, String.Empty)) + New EAttribute(Name_MediaPostDate, AConvert(Of String)(Post.Date, DateTimeDefaultProvider, String.Empty)) } ) End Function diff --git a/SCrawler/API/Base/UserDataBase.vb b/SCrawler/API/Base/UserDataBase.vb index cc1b5a4..da557d4 100644 --- a/SCrawler/API/Base/UserDataBase.vb +++ b/SCrawler/API/Base/UserDataBase.vb @@ -6,17 +6,18 @@ ' ' This program is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY +Imports System.IO +Imports System.Net +Imports System.Threading +Imports System.Runtime.CompilerServices +Imports SCrawler.Plugin +Imports SCrawler.Plugin.Hosts Imports PersonalUtilities.Functions.XML Imports PersonalUtilities.Functions.XML.Objects Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Forms.Toolbars Imports PersonalUtilities.Tools Imports PersonalUtilities.Tools.Web.Clients -Imports System.IO -Imports System.Net -Imports System.Threading -Imports SCrawler.Plugin -Imports SCrawler.Plugin.Hosts Imports UStates = SCrawler.API.Base.UserMedia.States Imports UTypes = SCrawler.API.Base.UserMedia.Types Namespace API.Base @@ -108,6 +109,7 @@ Namespace API.Base Private Const Name_UserExists As String = "UserExists" Private Const Name_UserSuspended As String = "UserSuspended" Private Const Name_FriendlyName As String = "FriendlyName" + Private Const Name_UserSiteName As String = "UserSiteName" Private Const Name_UserID As String = "UserID" Private Const Name_Description As String = "Description" Private Const Name_ParseUserMediaOnly As String = "ParseUserMediaOnly" @@ -141,17 +143,30 @@ Namespace API.Base End Get End Property Friend Property Progress As MyProgress - Friend ReadOnly Property Self As IUserData Implements IUserData.Self - Get - Return Me - End Get - End Property #End Region #Region "User name, ID, exist, suspend" Friend User As UserInfo Friend Property IsSavedPosts As Boolean Implements IPluginContentProvider.IsSavedPosts - Friend Overridable Property UserExists As Boolean = True Implements IUserData.Exists, IPluginContentProvider.UserExists - Friend Overridable Property UserSuspended As Boolean = False Implements IUserData.Suspended, IPluginContentProvider.UserSuspended + Private _UserExists As Boolean = True + Friend Overridable Property UserExists As Boolean Implements IUserData.Exists, IPluginContentProvider.UserExists + Get + Return _UserExists + End Get + Set(ByVal _UserExists As Boolean) + If Not Me._UserExists = _UserExists Then EnvirChanged(_UserExists) + Me._UserExists = _UserExists + End Set + End Property + Private _UserSuspended As Boolean = False + Friend Overridable Property UserSuspended As Boolean Implements IUserData.Suspended, IPluginContentProvider.UserSuspended + Get + Return _UserSuspended + End Get + Set(ByVal _UserSuspended As Boolean) + If Not Me._UserSuspended = _UserSuspended Then EnvirChanged(_UserSuspended) + Me._UserSuspended = _UserSuspended + End Set + End Property Friend Overridable Property Name As String Implements IContentProvider.Name, IPluginContentProvider.Name Get Return User.Name @@ -163,7 +178,46 @@ Namespace API.Base End Set End Property Friend Overridable Property ID As String = String.Empty Implements IContentProvider.ID, IPluginContentProvider.ID - Friend Overridable Property FriendlyName As String = String.Empty Implements IContentProvider.FriendlyName + Protected _FriendlyName As String = String.Empty + Friend Overridable Property FriendlyName As String Implements IContentProvider.FriendlyName + Get + If Settings.UserSiteNameAsFriendly Then + Return _FriendlyName.IfNullOrEmpty(UserSiteName) + Else + Return _FriendlyName + End If + End Get + Set(ByVal n As String) + _FriendlyName = n + End Set + End Property + Friend ReadOnly Property FriendlyNameOrig As String + Get + Return _FriendlyName + End Get + End Property + Friend ReadOnly Property FriendlyNameIsSiteName As Boolean + Get + If Settings.UserSiteNameAsFriendly Then + Return Not FriendlyName.IsEmptyString And Not _FriendlyName = UserSiteName And FriendlyName = UserSiteName + Else + Return False + End If + End Get + End Property + Private _UserSiteName As String = String.Empty + Friend Property UserSiteName As String + Get + Return _UserSiteName + End Get + Set(ByVal _UserSiteName As String) + If Not Me._UserSiteName = _UserSiteName Then EnvirChanged(_UserSiteName) + Me._UserSiteName = _UserSiteName + End Set + End Property + Protected Sub UserSiteNameUpdate(ByVal NewName As String) + If Not NewName.IsEmptyString And (UserSiteName.IsEmptyString Or Settings.UserSiteNameUpdateEveryTime) Then UserSiteName = NewName + End Sub Friend ReadOnly Property UserModel As UsageModel Implements IUserData.UserModel Get Return User.UserModel @@ -197,10 +251,6 @@ Namespace API.Base _DescriptionChecked = True End If End Sub - Protected Sub UserDescriptionReset() - _DescriptionChecked = False - _DescriptionEveryTime = Settings.UpdateUserDescriptionEveryTime - End Sub #End Region #Region "Favorite, Temporary" Protected _Favorite As Boolean = False @@ -246,7 +296,7 @@ Namespace API.Base Friend Overridable Sub SetPicture(ByVal f As SFile) Implements IUserData.SetPicture Try If f.Exists Then - Using p As New UserImage(f, User.File) : p.Save() : End Using + Using p As New UserImage(f, MyFile) : p.Save() : End Using End If Catch End Try @@ -409,13 +459,18 @@ BlockNullPicture: #Region "Files" Friend Overridable Property MyFile As SFile Implements IUserData.File Get - Return User.File + If IsSavedPosts Then + Return MyFileSettings + Else + Return User.File + End If End Get Set(ByVal f As SFile) User.File = f Settings.UpdateUsersList(User) End Set End Property + Protected MyFileSettings As SFile Protected MyFileData As SFile Protected MyFilePosts As SFile Friend Overridable Property FileExists As Boolean = False Implements IUserData.FileExists @@ -661,14 +716,16 @@ BlockNullPicture: Private _UserInformationLoaded As Boolean = False Friend Overridable Sub LoadUserInformation() Implements IUserData.LoadUserInformation Try - If MyFile.Exists Then + UpdateDataFiles(, True) + If MyFileSettings.Exists Then FileExists = True - Using x As New XmlFile(MyFile) With {.XmlReadOnly = True} + Using x As New XmlFile(MyFileSettings) With {.XmlReadOnly = True} If User.Name.IsEmptyString Then User.Name = x.Value(Name_UserName) UserExists = x.Value(Name_UserExists).FromXML(Of Boolean)(True) UserSuspended = x.Value(Name_UserSuspended).FromXML(Of Boolean)(False) ID = x.Value(Name_UserID) - FriendlyName = x.Value(Name_FriendlyName) + _FriendlyName = x.Value(Name_FriendlyName) + UserSiteName = x.Value(Name_UserSiteName) UserDescription = x.Value(Name_Description) ParseUserMediaOnly = x.Value(Name_ParseUserMediaOnly).FromXML(Of Boolean)(False) Temporary = x.Value(Name_Temporary).FromXML(Of Boolean)(False) @@ -705,7 +762,8 @@ BlockNullPicture: End Sub Friend Overridable Sub UpdateUserInformation() Implements IUserData.UpdateUserInformation Try - MyFile.Exists(SFO.Path) + UpdateDataFiles(True) + MyFileSettings.Exists(SFO.Path) Using x As New XmlFile With {.Name = "User"} x.Add(Name_Site, Site) x.Add(Name_Plugin, HOST.Key) @@ -718,7 +776,8 @@ BlockNullPicture: x.Add(Name_UserExists, UserExists.BoolToInteger) x.Add(Name_UserSuspended, UserSuspended.BoolToInteger) x.Add(Name_UserID, ID) - x.Add(Name_FriendlyName, FriendlyName) + x.Add(Name_FriendlyName, _FriendlyName) + x.Add(Name_UserSiteName, UserSiteName) x.Add(Name_Description, UserDescription) x.Add(Name_ParseUserMediaOnly, ParseUserMediaOnly.BoolToInteger) x.Add(Name_Temporary, Temporary.BoolToInteger) @@ -743,7 +802,7 @@ BlockNullPicture: LoadUserInformation_OptionalFields(x, False) - x.Save(MyFile) + x.Save(MyFileSettings) End Using If Not IsSavedPosts Then Settings.UpdateUsersList(User) Catch ex As Exception @@ -756,7 +815,7 @@ BlockNullPicture: #Region "User data" Friend Overridable Overloads Sub LoadContentInformation(Optional ByVal Force As Boolean = False) Try - UpdateDataFiles() + UpdateDataFiles(, True) If Not MyFileData.Exists Or (_DataLoaded And Not Force) Then Exit Sub Using x As New XmlFile(MyFileData, Protector.Modes.All, False) With {.XmlReadOnly = True, .AllowSameNames = True} x.LoadData() @@ -771,7 +830,7 @@ BlockNullPicture: End Sub Friend Sub UpdateContentInformation() Try - UpdateDataFiles() + UpdateDataFiles(True, True) If MyFileData.IsEmptyString Then Exit Sub MyFileData.Exists(SFO.Path) Using x As New XmlFile With {.AllowSameNames = True, .Name = "Data"} @@ -847,12 +906,45 @@ BlockNullPicture: #Region "Download functions and options" Protected Responser As Responser Protected UseResponserClient As Boolean = False + Protected _ForceSaveUserData As Boolean = False + Protected _ForceSaveUserInfo As Boolean = False + Private _DownloadInProgress As Boolean = False + Private _EnvirUserExists As Boolean + Private _EnvirUserSuspended As Boolean + Private _EnvirChanged As Boolean = False + Private _PictureExists As Boolean + Private _EnvirInvokeUserUpdated As Boolean = False + Protected Sub EnvirDownloadSet() + UpdateDataFiles(, True) + _DownloadInProgress = True + _DescriptionChecked = False + _DescriptionEveryTime = Settings.UpdateUserDescriptionEveryTime + _ForceSaveUserData = False + _ForceSaveUserInfo = False + _EnvirUserExists = UserExists + _EnvirUserSuspended = UserSuspended + _EnvirChanged = False + UserExists = True + UserSuspended = False + DownloadedPictures(False) = 0 + DownloadedVideos(False) = 0 + _PictureExists = Settings.ViewModeIsPicture AndAlso Not GetPicture(Of Image)(False) Is Nothing + _EnvirInvokeUserUpdated = False + End Sub + Private Sub EnvirChanged(ByVal NewValue As Object, Optional ByVal Caller As String = Nothing) + If _DownloadInProgress Then + Select Case Caller + Case NameOf(UserExists) : If Not _EnvirUserExists = CBool(NewValue) Then _EnvirChanged = True : _EnvirInvokeUserUpdated = True + Case NameOf(UserSuspended) : If Not _EnvirUserSuspended = CBool(NewValue) Then _EnvirChanged = True : _EnvirInvokeUserUpdated = True + Case Else : _EnvirChanged = True + End Select + End If + End Sub Friend Overridable Sub DownloadData(ByVal Token As CancellationToken) Implements IContentProvider.DownloadData Dim Canceled As Boolean = False _ExternalCompatibilityToken = Token Try - UpdateDataFiles() - UserDescriptionReset() + EnvirDownloadSet() If Not Responser Is Nothing Then Responser.Dispose() Responser = New Responser If Not HOST.Responser Is Nothing Then Responser.Copy(HOST.Responser) @@ -860,14 +952,7 @@ BlockNullPicture: Responser.DecodersError = New ErrorsDescriber(EDP.SendInLog + EDP.ReturnValue) With { .DeclaredMessage = New MMessage($"SymbolsConverter error: [{ToStringForLog()}]", ToStringForLog())} - Dim UpPic As Boolean = Settings.ViewModeIsPicture AndAlso GetPicture(Of Image)(False) Is Nothing - Dim sEnvir() As Boolean = {UserExists, UserSuspended} - Dim EnvirChanged As Func(Of Boolean) = Function() Not sEnvir(0) = UserExists Or Not sEnvir(1) = UserSuspended Dim _downContent As Func(Of UserMedia, Boolean) = Function(c) c.State = UStates.Downloaded - UserExists = True - UserSuspended = False - DownloadedPictures(False) = 0 - DownloadedVideos(False) = 0 _TempMediaList.Clear() _TempPostsList.Clear() LatestData.Clear() @@ -896,6 +981,7 @@ BlockNullPicture: ReparseVideo(Token) ThrowAny(Token) + If IsSavedPosts Then UpdateDataFiles(True) If _TempPostsList.Count > 0 And Not DownloadMissingOnly And __SaveData Then _ TextSaver.SaveTextToFile(_TempPostsList.ListToString(Environment.NewLine), MyFilePosts, True,, EDP.None) _ContentNew.ListAddList(_TempMediaList, LAP.ClearBeforeAdd) @@ -906,12 +992,12 @@ BlockNullPicture: Dim mcb& = If(ContentMissingExists, _ContentList.LongCount(Function(c) MissingFinder(c)), 0) _ContentList.ListAddList(_ContentNew.Where(Function(c) _downContent(c) Or MissingFinder(c)), LNC) Dim mca& = If(ContentMissingExists, _ContentList.LongCount(Function(c) MissingFinder(c)), 0) - If DownloadedTotal(False) > 0 Or EnvirChanged.Invoke Or Not mcb = mca Then + If DownloadedTotal(False) > 0 Or _EnvirChanged Or Not mcb = mca Or _ForceSaveUserData Then If __SaveData Then LastUpdated = Now RunScript() - DownloadedPictures(True) = SFile.GetFiles(User.File.CutPath, "*.jpg|*.jpeg|*.png|*.gif|*.webm",, EDP.ReturnValue).Count - DownloadedVideos(True) = SFile.GetFiles(User.File.CutPath, "*.mp4|*.mkv|*.mov", SearchOption.AllDirectories, EDP.ReturnValue).Count + DownloadedPictures(True) = SFile.GetFiles(MyFile.CutPath, "*.jpg|*.jpeg|*.png|*.gif|*.webm",, EDP.ReturnValue).Count + DownloadedVideos(True) = SFile.GetFiles(MyFile.CutPath, "*.mp4|*.mkv|*.mov", SearchOption.AllDirectories, EDP.ReturnValue).Count If Labels.Contains(LabelsKeeper.NoParsedUser) Then Labels.Remove(LabelsKeeper.NoParsedUser) UpdateContentInformation() Else @@ -922,10 +1008,12 @@ BlockNullPicture: End If If Not UserExists Then ReadyForDownload = False UpdateUserInformation() - If _CollectionButtonsExists AndAlso EnvirChanged.Invoke Then UpdateButtonsColor() + If _CollectionButtonsExists AndAlso _EnvirChanged Then UpdateButtonsColor() + ElseIf _ForceSaveUserInfo Then + UpdateUserInformation() End If ThrowIfDisposed() - If UpPic Or EnvirChanged.Invoke Then OnUserUpdated() + If Not _PictureExists Or _EnvirInvokeUserUpdated Then OnUserUpdated() Catch oex As OperationCanceledException When Token.IsCancellationRequested MyMainLOG = $"{ToStringForLog()}: downloading canceled" Canceled = True @@ -938,17 +1026,32 @@ BlockNullPicture: If Not Responser Is Nothing Then Responser.Dispose() : Responser = Nothing If Not Canceled Then _DataParsed = True _ContentNew.Clear() + _DownloadInProgress = False DownloadTopCount = Nothing DownloadDateFrom = Nothing DownloadDateTo = Nothing DownloadMissingOnly = False + _ForceSaveUserData = False + _ForceSaveUserInfo = False End Try End Sub - Protected Sub UpdateDataFiles() + Protected Sub UpdateDataFiles(Optional ByVal ForceSaved As Boolean = False, Optional ByVal ValidateContetnt As Boolean = False) + 'TODELETE: saved posts name compatibility 2023.2.5.0 + Dim __validateSaved As Func(Of Boolean) = Function() MyFileData.Exists Or MyFilePosts.Exists If Not User.File.IsEmptyString Then - MyFileData = User.File + MyFileSettings = Nothing + If IsSavedPosts Then + Dim u As UserInfo = User + u.Name = "SavedPosts" + u.UpdateUserFile() + Dim mfp As SFile = u.File + mfp.Name &= "_Posts" + If (ValidateContetnt AndAlso mfp.Exists) Or (Not ValidateContetnt AndAlso u.File.Exists) Or ForceSaved Then MyFileSettings = u.File + End If + If MyFileSettings.IsEmptyString Then MyFileSettings = User.File + MyFileData = MyFileSettings MyFileData.Name &= "_Data" - MyFilePosts = User.File + MyFilePosts = MyFileSettings MyFilePosts.Name &= "_Posts" MyFilePosts.Extension = "txt" Else @@ -1098,7 +1201,6 @@ BlockNullPicture: Return v End If Else - 'URGENT: UserDataBase.ProcessException [Throw ex] If ThrowEx Then Throw ex Else Return EXCEPTION_OPERATION_CANCELED End If Return 0 @@ -1293,7 +1395,7 @@ BlockNullPicture: Else pOffset = 1 End If - fSource = User.File.CutPath(pOffset).Path.CSFileP + fSource = MyFile.CutPath(pOffset).Path.CSFileP Dim OptPath$ = String.Empty If IncludedInCollection Then @@ -1501,7 +1603,6 @@ BlockNullPicture: Function MoveFiles(ByVal CollectionName As String, ByVal SpecialCollectionPath As SFile) As Boolean Function CopyFiles(ByVal DestinationPath As SFile, Optional ByVal e As ErrorsDescriber = Nothing) As Boolean Sub OpenFolder() - ReadOnly Property Self As IUserData Property DownloadTopCount As Integer? Property DownloadDateFrom As Date? Property DownloadDateTo As Date? diff --git a/SCrawler/API/Instagram/SiteSettings.vb b/SCrawler/API/Instagram/SiteSettings.vb index 2ddcd00..78046d0 100644 --- a/SCrawler/API/Instagram/SiteSettings.vb +++ b/SCrawler/API/Instagram/SiteSettings.vb @@ -86,10 +86,10 @@ Namespace API.Instagram Friend ReadOnly Property CSRF_TOKEN As PropertyValue Friend Property IG_APP_ID As PropertyValue - + Friend Property IG_WWW_CLAIM As PropertyValue Friend Overrides Function BaseAuthExists() As Boolean - Return Responser.CookiesExists And ACheck(IG_APP_ID.Value) And ACheck(IG_WWW_CLAIM.Value) And ACheck(CSRF_TOKEN.Value) + Return Responser.CookiesExists And ACheck(IG_APP_ID.Value) And ACheck(CSRF_TOKEN.Value) End Function Private Const Header_IG_APP_ID As String = "x-ig-app-id" Friend Const Header_IG_WWW_CLAIM As String = "x-ig-www-claim" @@ -219,7 +219,7 @@ Namespace API.Instagram HashTagged = New PropertyValue(String.Empty, GetType(String)) CSRF_TOKEN = New PropertyValue(token, GetType(String), Sub(v) ChangeResponserFields(NameOf(CSRF_TOKEN), v)) IG_APP_ID = New PropertyValue(app_id, GetType(String), Sub(v) ChangeResponserFields(NameOf(IG_APP_ID), v)) - IG_WWW_CLAIM = New PropertyValue(www_claim, GetType(String), Sub(v) ChangeResponserFields(NameOf(IG_WWW_CLAIM), v)) + IG_WWW_CLAIM = New PropertyValue(www_claim.IfNullOrEmpty(0), GetType(String), Sub(v) ChangeResponserFields(NameOf(IG_WWW_CLAIM), v)) DownloadTimeline = New PropertyValue(True) DownloadStories = New PropertyValue(True) @@ -291,6 +291,7 @@ Namespace API.Instagram Private _NextTagged As Boolean = True Friend Overrides Sub DownloadStarted(ByVal What As Download) ActiveJobs += 1 + If LastDownloadDate.Value.AddMinutes(120) < Now Or Not ACheck(IG_WWW_CLAIM.Value) Then IG_WWW_CLAIM.Value = "0" End Sub Friend Overrides Sub BeforeStartDownload(ByVal User As Object, ByVal What As Download) With DirectCast(User, UserData) diff --git a/SCrawler/API/Instagram/UserData.vb b/SCrawler/API/Instagram/UserData.vb index 4f49608..3eb9bf6 100644 --- a/SCrawler/API/Instagram/UserData.vb +++ b/SCrawler/API/Instagram/UserData.vb @@ -281,7 +281,7 @@ Namespace API.Instagram Case Else : WaitNotificationMode = WNM.SkipTemp End Select End If - If Not ProgressTempSet Then Progress.InformationTemporary = $"Waiting until { .GetWaitDate().ToString(ParsersDataDateProvider)}" + If Not ProgressTempSet Then Progress.InformationTemporary = $"Waiting until { .GetWaitDate().ToString(DateTimeDefaultProvider)}" ProgressTempSet = True Return False Else @@ -452,6 +452,7 @@ Namespace API.Instagram HasNextPage = .Value("more_available").FromXML(Of Boolean)(False) EndCursor = .Value("next_max_id") If If(.Item("items")?.Count, 0) > 0 Then + UserSiteNameUpdate(.ItemF({"items", 0, "user", "full_name"}).XmlIfNothingValue) If Not DefaultParser(.Item("items"), Section, Token) Then Throw New ExitException Else HasNextPage = False @@ -742,18 +743,40 @@ Namespace API.Instagram #End Region #Region "GetUserId" Private Sub GetUserId() + Dim __idFound As Boolean = False Try Dim r$ = Responser.GetResponse($"https://i.instagram.com/api/v1/users/web_profile_info/?username={Name}",, EDP.ThrowException) If Not r.IsEmptyString Then - Using j As EContainer = JsonDocument.Parse(r).XmlIfNothing - ID = j({"data", "user"}, "id").XmlIfNothingValue + Using j As EContainer = JsonDocument.Parse(r) + If Not j Is Nothing AndAlso j.Contains({"data", "user"}) Then + With j({"data", "user"}) + ID = .Value("id") + __idFound = True + UserSiteNameUpdate(.Value("full_name")) + Dim descr$ = .Value("biography") + If If(.Item("bio_links")?.Count, 0) > 0 Then descr.StringAppend(.Item("bio_links").Select(Function(bl) bl.Value("url")).ListToString(vbNewLine), vbNewLine) + Dim eUrl$ = .Value("external_url") + If Not eUrl.IsEmptyString AndAlso (descr.IsEmptyString OrElse Not descr.Contains(eUrl)) Then descr.StringAppendLine(eUrl) + UserDescriptionUpdate(descr) + Dim f As New SFile With {.Path = MyFile.CutPath.Path, .Name = "ProfilePicture", .Extension = "jpg"} + If Not f.Exists Then + Dim profilePicture$ = .Value("profile_pic_url_hd") + If profilePicture.IsEmptyString OrElse Not GetWebFile(profilePicture, f, EDP.ReturnValue) Then + profilePicture = .Value("profile_pic_url") + If Not profilePicture.IsEmptyString Then GetWebFile(profilePicture, f, EDP.ReturnValue) + End If + End If + End With + End If End Using End If Catch ex As Exception - If Responser.StatusCode = HttpStatusCode.NotFound Or Responser.StatusCode = HttpStatusCode.BadRequest Then - Throw ex - Else - LogError(ex, "get Instagram user id") + If Not __idFound Then + If Responser.StatusCode = HttpStatusCode.NotFound Or Responser.StatusCode = HttpStatusCode.BadRequest Then + Throw ex + Else + LogError(ex, "get Instagram user id") + End If End If End Try End Sub diff --git a/SCrawler/API/PathPlugin/Declarations.vb b/SCrawler/API/PathPlugin/Declarations.vb new file mode 100644 index 0000000..c58e5b0 --- /dev/null +++ b/SCrawler/API/PathPlugin/Declarations.vb @@ -0,0 +1,14 @@ +' 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.PathPlugin + Friend Module Declarations + Friend Const PluginKey As String = "AndyProgram_PathPlugin" + Friend Const PluginName As String = "Path" + End Module +End Namespace \ No newline at end of file diff --git a/SCrawler/API/PathPlugin/SiteSettings.vb b/SCrawler/API/PathPlugin/SiteSettings.vb new file mode 100644 index 0000000..ad6c15d --- /dev/null +++ b/SCrawler/API/PathPlugin/SiteSettings.vb @@ -0,0 +1,49 @@ +' 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.Plugin +Imports SCrawler.Plugin.Attributes +Namespace API.PathPlugin + + Friend Class SiteSettings : Inherits SiteSettingsBase + Friend Overrides ReadOnly Property Icon As Icon + Get + Return PersonalUtilities.Tools.ImageRenderer.GetIcon(PersonalUtilities.My.Resources.FolderOpenPic_Orange_16, EDP.ReturnValue) + End Get + End Property + Friend Overrides ReadOnly Property Image As Image + Get + Return PersonalUtilities.My.Resources.FolderOpenPic_Orange_16 + End Get + End Property + Friend Sub New() + MyBase.New(PluginName) + End Sub + Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider + Return New UserData + End Function + Friend Overrides Function IsMyUser(ByVal UserURL As String) As ExchangeOptions + Dim f As SFile = UserURL + If Not f.IsEmptyString AndAlso f.PathNoSeparator = UserURL.StringTrimEnd("\") AndAlso (f.Location = SFOLocation.Local Or f.Location = SFOLocation.Network) Then + Return New ExchangeOptions(Site, f) + Else + Return Nothing + End If + End Function + Friend Overrides Function Available(ByVal What As ISiteSettings.Download, ByVal Silent As Boolean) As Boolean + Return False + End Function + Friend Overrides Function IsMyImageVideo(ByVal URL As String) As ExchangeOptions + Return Nothing + End Function + Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider, ByVal Channel As Boolean) As String + Return String.Empty + End Function + End Class +End Namespace \ No newline at end of file diff --git a/SCrawler/API/PathPlugin/UserData.vb b/SCrawler/API/PathPlugin/UserData.vb new file mode 100644 index 0000000..f222cc5 --- /dev/null +++ b/SCrawler/API/PathPlugin/UserData.vb @@ -0,0 +1,45 @@ +' 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 +Namespace API.PathPlugin + Friend Class UserData : Inherits UserDataBase + Private Const DOWNLOAD_ERROR As String = "The path plugin only provides user paths." + Friend Overrides Property UserExists As Boolean + Get + Return FileExists + End Get + Set(ByVal e As Boolean) + MyBase.UserExists = e + End Set + End Property + Friend Overrides Property UserSuspended As Boolean + Get + Return False + End Get + Set(ByVal s As Boolean) + MyBase.UserSuspended = s + End Set + End Property + Friend Overrides Sub OpenSite(Optional ByVal e As ErrorsDescriber = Nothing) + OpenFolder() + End Sub + Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XML.XmlFile, ByVal Loading As Boolean) + End Sub + Protected Overrides Sub DownloadDataF(ByVal Token As Threading.CancellationToken) + Throw New InvalidOperationException(DOWNLOAD_ERROR) + End Sub + Protected Overrides Sub DownloadContent(ByVal Token As Threading.CancellationToken) + Throw New InvalidOperationException(DOWNLOAD_ERROR) + End Sub + 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 + Throw New InvalidOperationException(DOWNLOAD_ERROR) + End Function + End Class +End Namespace \ No newline at end of file diff --git a/SCrawler/API/PornHub/Declarations.vb b/SCrawler/API/PornHub/Declarations.vb index cf5897b..c046642 100644 --- a/SCrawler/API/PornHub/Declarations.vb +++ b/SCrawler/API/PornHub/Declarations.vb @@ -11,7 +11,6 @@ Namespace API.PornHub Friend Module Declarations #Region "Converters" Private ReadOnly UnicodeHexConverter As Func(Of String, String) = Function(Input) SymbolsConverter.UnicodeHex.Decode(Input, EDP.ReturnValue) - Friend ReadOnly HtmlConverter As Func(Of String, String) = Function(Input) SymbolsConverter.HTML.Decode(Input, EDP.ReturnValue) #End Region #Region "Declarations video" Friend ReadOnly RegexVideo_FlashVarsBlock As RParams = RParams.DM("(?<=flashvars_\['[nN]ext[vV]ideo'\];[\r\n]*?)(.+?)(?=;flashvars_\d+?)", 0, EDP.ReturnValue) diff --git a/SCrawler/API/PornHub/UserData.vb b/SCrawler/API/PornHub/UserData.vb index eace7f2..8c1e52f 100644 --- a/SCrawler/API/PornHub/UserData.vb +++ b/SCrawler/API/PornHub/UserData.vb @@ -59,7 +59,7 @@ Namespace API.PornHub URL = ParamsArray(0) ID = RegexReplace(URL, RegexVideo_Video_VideoKey) URL = String.Format(UrlPattern, URL.TrimStart("/")) - Title = HtmlConverter(ParamsArray(1)).StringRemoveWinForbiddenSymbols.StringTrim + Title = TitleHtmlConverter(ParamsArray(1)) End If Return Me End Function @@ -99,7 +99,6 @@ Namespace API.PornHub #Region "Person" Friend Property PersonType As String Friend Property NameTrue As String - Private _FriendlyName As String = String.Empty Friend Overrides Property FriendlyName As String Get If _FriendlyName.IsEmptyString Then Return NameTrue Else Return _FriendlyName @@ -315,7 +314,7 @@ Namespace API.PornHub If l3.ListExists(3) Then m.URL = l3(2) m.File = m.URL - n = HtmlConverter(l3(1)).StringRemoveWinForbiddenSymbols.StringTrim + n = TitleHtmlConverter(l3(1)) If MySettings.DownloadGifsAsMp4.Value Then m.File.Extension = "mp4" If Not n.IsEmptyString Then m.File.Name = n End If @@ -416,7 +415,7 @@ Namespace API.PornHub If albumName.IsEmptyString Then albumName = block.AlbumID.Split("/").LastOrDefault.StringTrim Else - albumName = HtmlConverter(albumName).StringRemoveWinForbiddenSymbols.StringTrim + albumName = TitleHtmlConverter(albumName) End If page = 1 Do While DownloadUserPhotos_PornHub(page, block.AlbumID, albumName, Token) : page += 1 : Loop diff --git a/SCrawler/API/Reddit/SiteSettings.vb b/SCrawler/API/Reddit/SiteSettings.vb index e16387c..df6aaf2 100644 --- a/SCrawler/API/Reddit/SiteSettings.vb +++ b/SCrawler/API/Reddit/SiteSettings.vb @@ -32,8 +32,9 @@ Namespace API.Reddit Friend Sub New() MyBase.New(RedditSite, "reddit.com") With Responser - If .Decoders.Count = 0 OrElse Not .Decoders.Contains(SymbolsConverter.Converters.Unicode) Then _ - .Decoders.Add(SymbolsConverter.Converters.Unicode) : .SaveSettings() + Dim d% = .Decoders.Count + .Decoders.ListAddList({SymbolsConverter.Converters.Unicode, SymbolsConverter.Converters.HTML}, LAP.NotContainsOnly) + If d <> .Decoders.Count Then .SaveSettings() End With SavedPostsUserName = New PropertyValue(String.Empty, GetType(String)) UseM3U8 = New PropertyValue(True) diff --git a/SCrawler/API/Reddit/UserData.vb b/SCrawler/API/Reddit/UserData.vb index f83ed61..71917d2 100644 --- a/SCrawler/API/Reddit/UserData.vb +++ b/SCrawler/API/Reddit/UserData.vb @@ -132,9 +132,9 @@ Namespace API.Reddit #End Region #Region "Download Overrides" Friend Overrides Sub DownloadData(ByVal Token As CancellationToken) - UserDescriptionReset() _CrossPosts.Clear() If Not IsSavedPosts AndAlso (IsChannel AndAlso Not ChannelInfo Is Nothing) Then + EnvirDownloadSet() If Not Responser Is Nothing Then Responser.Dispose() Responser = New Responser Responser.Copy(MySiteSettings.Responser) @@ -165,12 +165,15 @@ Namespace API.Reddit End With End If If DownloadTopCount.HasValue Then DownloadLimitCount = DownloadTopCount + Else + GetUserInfo() End If If SaveToCache AndAlso Not Responser.Decoders.Contains(SymbolsConverter.Converters.HTML) Then _ Responser.Decoders.Add(SymbolsConverter.Converters.HTML) DownloadDataChannel(String.Empty, Token) If ChannelInfo Is Nothing Then _TempPostsList.ListAddList(_TempMediaList.Select(Function(m) m.Post.ID), LNC) Else + GetUserInfo() DownloadDataUser(String.Empty, Token) End If End Sub @@ -205,7 +208,8 @@ Namespace API.Reddit If Not r.IsEmptyString Then Using w As EContainer = JsonDocument.Parse(r).XmlIfNothing If w.Count > 0 Then - If UserDescriptionNeedToUpdate() Then UserDescriptionUpdate(w.ItemF({"subredditAboutInfo", 0, "publicDescription"}).XmlIfNothingValue) + 'TODELETE: moved to 'GetUserInfo' 2023.2.5.0 + 'If UserDescriptionNeedToUpdate() Then UserDescriptionUpdate(w.ItemF({"subredditAboutInfo", 0, "publicDescription"}).XmlIfNothingValue) n = w.GetNode(JsonNodesJson) If Not n Is Nothing AndAlso n.Count > 0 Then For Each nn In n @@ -416,6 +420,37 @@ Namespace API.Reddit ProcessException(ex, Token, $"channel data downloading error [{URL}]") End Try End Sub + Private Sub GetUserInfo() + Try + If Not IsSavedPosts And ChannelInfo Is Nothing Then + Dim r$ = Responser.GetResponse($"https://reddit.com/{IIf(IsChannel, "r", "user")}/{Name}/about.json",, EDP.ReturnValue) + If Not r.IsEmptyString Then + Using j As EContainer = JsonDocument.Parse(r) + If Not j Is Nothing AndAlso j.Contains({"data", "subreddit"}) Then + With j({"data", "subreddit"}) + UserSiteNameUpdate(.Value("title")) + UserDescriptionUpdate(.Value("public_description")) + Dim dir As SFile = MyFile.CutPath + Dim __getFile As Action(Of String) = Sub(ByVal img As String) + If Not img.IsEmptyString Then + Dim f As SFile = UrlToFile(img) + If Not f.Name.IsEmptyString Then + If f.Extension.IsEmptyString Then f.Extension = "jpg" + f.Path = dir.Path + If Not f.Exists Then GetWebFile(img, f, EDP.ReturnValue) + End If + End If + End Sub + __getFile.Invoke(.Value("icon_img")) + __getFile.Invoke(.Value("banner_img")) + End With + End If + End Using + End If + End If + Catch ex As Exception + End Try + End Sub #End Region #Region "Download Base Functions" Private Function CreateImgurMedia(ByVal _URL As String, ByVal PostID As String, ByVal PostDate As String, diff --git a/SCrawler/API/Twitter/EditorExchangeOptions.vb b/SCrawler/API/Twitter/EditorExchangeOptions.vb index dddbf05..346a41f 100644 --- a/SCrawler/API/Twitter/EditorExchangeOptions.vb +++ b/SCrawler/API/Twitter/EditorExchangeOptions.vb @@ -11,17 +11,22 @@ Namespace API.Twitter Friend Property GifsDownload As Boolean Friend Property GifsSpecialFolder As String Friend Property GifsPrefix As String + Friend Property UseMD5Comparison As Boolean = False + Friend Property RemoveExistingDuplicates As Boolean = False Friend Sub New() End Sub Friend Sub New(ByVal s As SiteSettings) GifsDownload = s.GifsDownload.Value GifsSpecialFolder = s.GifsSpecialFolder.Value GifsPrefix = s.GifsPrefix.Value + UseMD5Comparison = s.UseMD5Comparison.Value End Sub Friend Sub New(ByVal u As UserData) GifsDownload = u.GifsDownload GifsSpecialFolder = u.GifsSpecialFolder GifsPrefix = u.GifsPrefix + UseMD5Comparison = u.UseMD5Comparison + RemoveExistingDuplicates = u.RemoveExistingDuplicates End Sub End Class End Namespace \ No newline at end of file diff --git a/SCrawler/API/Twitter/OptionsForm.Designer.vb b/SCrawler/API/Twitter/OptionsForm.Designer.vb index 3330cfa..1b2dd82 100644 --- a/SCrawler/API/Twitter/OptionsForm.Designer.vb +++ b/SCrawler/API/Twitter/OptionsForm.Designer.vb @@ -22,16 +22,21 @@ Namespace API.Twitter Private components As System.ComponentModel.IContainer Private Sub InitializeComponent() + Me.components = New System.ComponentModel.Container() Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel - Dim ActionButton1 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 resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(OptionsForm)) - Dim ActionButton2 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 TT_MAIN As System.Windows.Forms.ToolTip Me.CH_DOWN_GIFS = New System.Windows.Forms.CheckBox() Me.TXT_GIF_FOLDER = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_GIF_PREFIX = New PersonalUtilities.Forms.Controls.TextBoxExtended() + Me.CH_USE_MD5 = New System.Windows.Forms.CheckBox() + Me.CH_REMOVE_EXISTING_DUP = New System.Windows.Forms.CheckBox() CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer() TP_MAIN = New System.Windows.Forms.TableLayoutPanel() + TT_MAIN = New System.Windows.Forms.ToolTip(Me.components) CONTAINER_MAIN.ContentPanel.SuspendLayout() CONTAINER_MAIN.SuspendLayout() TP_MAIN.SuspendLayout() @@ -45,13 +50,13 @@ Namespace API.Twitter 'CONTAINER_MAIN.ContentPanel ' CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN) - CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(304, 84) + CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(304, 161) 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(304, 109) + CONTAINER_MAIN.Size = New System.Drawing.Size(304, 161) CONTAINER_MAIN.TabIndex = 0 CONTAINER_MAIN.TopToolStripPanelVisible = False ' @@ -60,19 +65,22 @@ Namespace API.Twitter 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.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!)) TP_MAIN.Controls.Add(Me.CH_DOWN_GIFS, 0, 0) TP_MAIN.Controls.Add(Me.TXT_GIF_FOLDER, 0, 1) TP_MAIN.Controls.Add(Me.TXT_GIF_PREFIX, 0, 2) + TP_MAIN.Controls.Add(Me.CH_USE_MD5, 0, 3) + TP_MAIN.Controls.Add(Me.CH_REMOVE_EXISTING_DUP, 0, 4) 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 = 4 + TP_MAIN.RowCount = 6 TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.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, 25.0!)) + TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_MAIN.Size = New System.Drawing.Size(304, 84) + TP_MAIN.Size = New System.Drawing.Size(304, 161) TP_MAIN.TabIndex = 0 ' 'CH_DOWN_GIFS @@ -89,10 +97,10 @@ Namespace API.Twitter ' 'TXT_GIF_FOLDER ' - ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image) - ActionButton1.Name = "Clear" - ActionButton1.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear - Me.TXT_GIF_FOLDER.Buttons.Add(ActionButton1) + ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image) + ActionButton3.Name = "Clear" + ActionButton3.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear + Me.TXT_GIF_FOLDER.Buttons.Add(ActionButton3) Me.TXT_GIF_FOLDER.CaptionText = "GIFs special folder" Me.TXT_GIF_FOLDER.CaptionToolTipText = "Put the GIFs in a special folder" Me.TXT_GIF_FOLDER.Dock = System.Windows.Forms.DockStyle.Fill @@ -103,10 +111,10 @@ Namespace API.Twitter ' 'TXT_GIF_PREFIX ' - ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image) - ActionButton2.Name = "Clear" - ActionButton2.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear - Me.TXT_GIF_PREFIX.Buttons.Add(ActionButton2) + ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image) + ActionButton4.Name = "Clear" + ActionButton4.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear + Me.TXT_GIF_PREFIX.Buttons.Add(ActionButton4) Me.TXT_GIF_PREFIX.CaptionText = "GIF prefix" Me.TXT_GIF_PREFIX.CaptionToolTipText = "This prefix will be added to the beginning of the filename" Me.TXT_GIF_PREFIX.Dock = System.Windows.Forms.DockStyle.Fill @@ -115,18 +123,45 @@ Namespace API.Twitter Me.TXT_GIF_PREFIX.Size = New System.Drawing.Size(296, 22) Me.TXT_GIF_PREFIX.TabIndex = 2 ' + 'CH_USE_MD5 + ' + Me.CH_USE_MD5.AutoSize = True + Me.CH_USE_MD5.Dock = System.Windows.Forms.DockStyle.Fill + Me.CH_USE_MD5.Location = New System.Drawing.Point(4, 88) + Me.CH_USE_MD5.Name = "CH_USE_MD5" + Me.CH_USE_MD5.Padding = New System.Windows.Forms.Padding(100, 0, 0, 0) + Me.CH_USE_MD5.Size = New System.Drawing.Size(296, 19) + Me.CH_USE_MD5.TabIndex = 3 + Me.CH_USE_MD5.Text = "Use MD5 comparison" + TT_MAIN.SetToolTip(Me.CH_USE_MD5, "Each image will be checked for existence using MD5") + Me.CH_USE_MD5.UseVisualStyleBackColor = True + ' + 'CH_REMOVE_EXISTING_DUP + ' + Me.CH_REMOVE_EXISTING_DUP.AutoSize = True + Me.CH_REMOVE_EXISTING_DUP.Dock = System.Windows.Forms.DockStyle.Fill + Me.CH_REMOVE_EXISTING_DUP.Location = New System.Drawing.Point(4, 114) + Me.CH_REMOVE_EXISTING_DUP.Name = "CH_REMOVE_EXISTING_DUP" + Me.CH_REMOVE_EXISTING_DUP.Padding = New System.Windows.Forms.Padding(100, 0, 0, 0) + Me.CH_REMOVE_EXISTING_DUP.Size = New System.Drawing.Size(296, 19) + Me.CH_REMOVE_EXISTING_DUP.TabIndex = 4 + Me.CH_REMOVE_EXISTING_DUP.Text = "Remove existing duplicates" + TT_MAIN.SetToolTip(Me.CH_REMOVE_EXISTING_DUP, "Existing files will be checked for duplicates and duplicates removed." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Works only" & + " on the first activation 'Use MD5 comparison'.") + Me.CH_REMOVE_EXISTING_DUP.UseVisualStyleBackColor = True + ' 'OptionsForm ' Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font - Me.ClientSize = New System.Drawing.Size(304, 109) + Me.ClientSize = New System.Drawing.Size(304, 161) Me.Controls.Add(CONTAINER_MAIN) Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle Me.Icon = Global.SCrawler.My.Resources.SiteResources.TwitterIcon_32 Me.MaximizeBox = False - Me.MaximumSize = New System.Drawing.Size(320, 148) + Me.MaximumSize = New System.Drawing.Size(320, 200) Me.MinimizeBox = False - Me.MinimumSize = New System.Drawing.Size(320, 148) + Me.MinimumSize = New System.Drawing.Size(320, 200) Me.Name = "OptionsForm" Me.ShowInTaskbar = False Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide @@ -144,5 +179,7 @@ Namespace API.Twitter Private WithEvents CH_DOWN_GIFS As CheckBox Private WithEvents TXT_GIF_FOLDER As PersonalUtilities.Forms.Controls.TextBoxExtended Private WithEvents TXT_GIF_PREFIX As PersonalUtilities.Forms.Controls.TextBoxExtended + Private WithEvents CH_USE_MD5 As CheckBox + Private WithEvents CH_REMOVE_EXISTING_DUP As CheckBox End Class End Namespace \ No newline at end of file diff --git a/SCrawler/API/Twitter/OptionsForm.resx b/SCrawler/API/Twitter/OptionsForm.resx index 27f385b..129abb5 100644 --- a/SCrawler/API/Twitter/OptionsForm.resx +++ b/SCrawler/API/Twitter/OptionsForm.resx @@ -124,7 +124,7 @@ False - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go @@ -132,7 +132,7 @@ AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go @@ -140,4 +140,16 @@ AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC + + False + + + 17, 17 + + + False + + + 17, 17 + \ No newline at end of file diff --git a/SCrawler/API/Twitter/OptionsForm.vb b/SCrawler/API/Twitter/OptionsForm.vb index 970e6d5..8cac46e 100644 --- a/SCrawler/API/Twitter/OptionsForm.vb +++ b/SCrawler/API/Twitter/OptionsForm.vb @@ -30,6 +30,8 @@ Namespace API.Twitter TXT_GIF_FOLDER.Tag = NameOf(SiteSettings.GifsSpecialFolder) TXT_GIF_PREFIX.Text = .GifsPrefix TXT_GIF_PREFIX.Tag = NameOf(SiteSettings.GifsPrefix) + CH_USE_MD5.Checked = .UseMD5Comparison + CH_REMOVE_EXISTING_DUP.Checked = .RemoveExistingDuplicates Try Dim p As PropertyOption @@ -59,6 +61,8 @@ Namespace API.Twitter .GifsDownload = CH_DOWN_GIFS.Checked .GifsSpecialFolder = TXT_GIF_FOLDER.Text .GifsPrefix = TXT_GIF_PREFIX.Text + .UseMD5Comparison = CH_USE_MD5.Checked + .RemoveExistingDuplicates = CH_REMOVE_EXISTING_DUP.Checked End With MyDefs.CloseForm() End Sub diff --git a/SCrawler/API/Twitter/SiteSettings.vb b/SCrawler/API/Twitter/SiteSettings.vb index 004574a..c5d2043 100644 --- a/SCrawler/API/Twitter/SiteSettings.vb +++ b/SCrawler/API/Twitter/SiteSettings.vb @@ -69,6 +69,8 @@ Namespace API.Twitter Throw New NotImplementedException("[GetFormat] is not available in the context of [TimersChecker]") End Function End Class + + Friend ReadOnly Property UseMD5Comparison As PropertyValue #End Region Friend Overrides ReadOnly Property Responser As Responser #End Region @@ -115,6 +117,7 @@ Namespace API.Twitter GifsSpecialFolder = New PropertyValue(String.Empty, GetType(String)) GifsPrefix = New PropertyValue("GIF_") GifStringChecker = New GifStringProvider + UseMD5Comparison = New PropertyValue(False) UserRegex = RParams.DMS("[htps:/]{7,8}.*?twitter.com/([^/]+)", 1) UrlPatternUser = "https://twitter.com/{0}" diff --git a/SCrawler/API/Twitter/UserData.vb b/SCrawler/API/Twitter/UserData.vb index 392ae7a..0557d44 100644 --- a/SCrawler/API/Twitter/UserData.vb +++ b/SCrawler/API/Twitter/UserData.vb @@ -7,13 +7,16 @@ ' This program is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY Imports System.Net +Imports System.Drawing 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 PersonalUtilities.Tools.ImageRenderer Imports UStates = SCrawler.API.Base.UserMedia.States +Imports UTypes = SCrawler.API.Base.UserMedia.Types Namespace API.Twitter Friend Class UserData : Inherits UserDataBase Private Const SinglePostUrl As String = "https://api.twitter.com/1.1/statuses/show.json?id={0}&tweet_mode=extended" @@ -21,12 +24,18 @@ Namespace API.Twitter Private Const Name_GifsDownload As String = "GifsDownload" Private Const Name_GifsSpecialFolder As String = "GifsSpecialFolder" Private Const Name_GifsPrefix As String = "GifsPrefix" + Private Const Name_UseMD5Comparison As String = "UseMD5Comparison" + Private Const Name_RemoveExistingDuplicates As String = "RemoveExistingDuplicates" + Private Const Name_StartMD5Checked As String = "StartMD5Checked" #End Region #Region "Declarations" Friend Property GifsDownload As Boolean Friend Property GifsSpecialFolder As String Friend Property GifsPrefix As String Private ReadOnly _DataNames As List(Of String) + Friend Property UseMD5Comparison As Boolean = False + Private StartMD5Checked As Boolean = False + Friend Property RemoveExistingDuplicates As Boolean = False #End Region #Region "Exchange options" Friend Overrides Function ExchangeOptionsGet() As Object @@ -38,6 +47,8 @@ Namespace API.Twitter GifsDownload = .GifsDownload GifsSpecialFolder = .GifsSpecialFolder GifsPrefix = .GifsPrefix + UseMD5Comparison = .UseMD5Comparison + RemoveExistingDuplicates = .RemoveExistingDuplicates End With End If End Sub @@ -55,10 +66,16 @@ Namespace API.Twitter Else GifsPrefix = Container.Value(Name_GifsPrefix) End If + UseMD5Comparison = Container.Value(Name_UseMD5Comparison).FromXML(Of Boolean)(False) + RemoveExistingDuplicates = Container.Value(Name_RemoveExistingDuplicates).FromXML(Of Boolean)(False) + StartMD5Checked = Container.Value(Name_StartMD5Checked).FromXML(Of Boolean)(False) Else Container.Add(Name_GifsDownload, GifsDownload.BoolToInteger) Container.Add(Name_GifsSpecialFolder, GifsSpecialFolder) Container.Add(Name_GifsPrefix, GifsPrefix) + Container.Add(Name_UseMD5Comparison, UseMD5Comparison.BoolToInteger) + Container.Add(Name_RemoveExistingDuplicates, RemoveExistingDuplicates.BoolToInteger) + Container.Add(Name_StartMD5Checked, StartMD5Checked.BoolToInteger) End If End Sub #End Region @@ -70,6 +87,7 @@ Namespace API.Twitter Else If _ContentList.Count > 0 Then _DataNames.ListAddList(_ContentList.Select(Function(c) c.File.File), LAP.ClearBeforeAdd, LAP.NotContainsOnly) DownloadData(String.Empty, Token) + If UseMD5Comparison Then ValidateMD5(Token) End If End Sub Private Overloads Sub DownloadData(ByVal POST As String, ByVal Token As CancellationToken) @@ -100,6 +118,30 @@ Namespace API.Twitter If Not r.IsEmptyString Then Using w As EContainer = JsonDocument.Parse(r) If w.ListExists Then + + If Not IsSavedPosts And POST.IsEmptyString And Not w.ItemF({0, "user"}) Is Nothing Then + With w.ItemF({0, "user"}) + If .Value("screen_name").StringToLower = Name Then + UserSiteNameUpdate(.Value("name")) + UserDescriptionUpdate(.Value("description")) + Dim __getImage As Action(Of String) = Sub(ByVal img As String) + If Not img.IsEmptyString Then + Dim __imgFile As SFile = UrlFile(img, True) + If Not __imgFile.Name.IsEmptyString Then + If __imgFile.Extension.IsEmptyString Then __imgFile.Extension = "jpg" + __imgFile.Path = MyFile.CutPath.Path + If Not __imgFile.Exists Then GetWebFile(img, __imgFile, EDP.None) + End If + End If + End Sub + Dim icon$ = .Value("profile_image_url_https") + If Not icon.IsEmptyString Then icon = icon.Replace("_normal", String.Empty) + __getImage.Invoke(.Value("profile_banner_url")) + __getImage.Invoke(icon) + End If + End With + End If + For Each nn In If(IsSavedPosts, w({"globalObjects", "tweets"}).XmlIfNothing, w) ThrowAny(Token) If nn.Count > 0 Then @@ -114,9 +156,6 @@ Namespace API.Twitter End If End If - If Not IsSavedPosts AndAlso UserDescriptionNeedToUpdate() AndAlso nn.Value({"user"}, "screen_name") = Name Then _ - UserDescriptionUpdate(nn.Value({"user"}, "description")) - 'Date Pattern: 'Sat Jan 01 01:10:15 +0000 2000 If nn.Contains("created_at") Then PostDate = nn("created_at").Value Else PostDate = String.Empty @@ -174,7 +213,7 @@ Namespace API.Twitter If Not dName.IsEmptyString AndAlso Not _DataNames.Contains(dName) Then _DataNames.Add(dName) _TempMediaList.ListAddValue(MediaFromData(m("media_url").Value, - PostID, PostDate, GetPictureOption(m), State), LNC) + PostID, PostDate, GetPictureOption(m), State, UTypes.Picture), LNC) End If End If Next @@ -190,7 +229,7 @@ Namespace API.Twitter Dim f$ = UrlFile(URL) If Not f.IsEmptyString AndAlso Not _DataNames.Contains(f) Then _DataNames.Add(f) - _TempMediaList.ListAddValue(MediaFromData(URL, PostID, PostDate,, State), LNC) + _TempMediaList.ListAddValue(MediaFromData(URL, PostID, PostDate,, State, UTypes.Video), LNC) End If Return True End If @@ -218,7 +257,7 @@ Namespace API.Twitter ff = UrlFile(url) If Not ff.IsEmptyString Then If GifsDownload And Not _DataNames.Contains(ff) Then - m = MediaFromData(url, PostID, PostDate,, State) + m = MediaFromData(url, PostID, PostDate,, State, UTypes.Video) f = m.File If Not f.IsEmptyString And Not GifsPrefix.IsEmptyString Then f.Name = $"{GifsPrefix}{f.Name}" : m.File = f If Not GifsSpecialFolder.IsEmptyString Then m.SpecialFolder = $"{GifsSpecialFolder}*" @@ -298,6 +337,131 @@ Namespace API.Twitter End Try End Sub #End Region +#Region "MD5 support" + Private Const VALIDATE_MD5_ERROR As String = "VALIDATE_MD5_ERROR" + Private Sub ValidateMD5(ByVal Token As CancellationToken) + Try + Dim missingMD5 As Predicate(Of UserMedia) = Function(d) (d.Type = UTypes.GIF Or d.Type = UTypes.Picture) And d.MD5.IsEmptyString + If UseMD5Comparison And _TempMediaList.Exists(missingMD5) Then + Dim i% + Dim data As UserMedia = Nothing + Dim hashList As New Dictionary(Of String, SFile) + Dim f As SFile + Dim ErrMD5 As New ErrorsDescriber(EDP.ReturnValue) + Dim __getMD5 As Func(Of UserMedia, Boolean, String) = + Function(ByVal __data As UserMedia, ByVal IsUrl As Boolean) As String + Try + Dim ImgFormat As Imaging.ImageFormat = Nothing + Dim hash$ = String.Empty + Dim __isGif As Boolean = False + If __data.Type = UTypes.GIF Then + ImgFormat = Imaging.ImageFormat.Gif + __isGif = True + ElseIf Not __data.File.IsEmptyString Then + ImgFormat = GetImageFormat(__data.File) + End If + If ImgFormat Is Nothing Then ImgFormat = Imaging.ImageFormat.Jpeg + If IsUrl Then + hash = ByteArrayToString(GetMD5(SFile.GetBytesFromNet(__data.URL_BASE.IfNullOrEmpty(__data.URL), ErrMD5), ImgFormat, ErrMD5)) + Else + hash = ByteArrayToString(GetMD5(SFile.GetBytes(__data.File, ErrMD5), ImgFormat, ErrMD5)) + End If + If hash.IsEmptyString And Not __isGif Then + If ImgFormat Is Imaging.ImageFormat.Jpeg Then ImgFormat = Imaging.ImageFormat.Png Else ImgFormat = Imaging.ImageFormat.Jpeg + If IsUrl Then + hash = ByteArrayToString(GetMD5(SFile.GetBytesFromNet(__data.URL_BASE.IfNullOrEmpty(__data.URL), ErrMD5), ImgFormat, ErrMD5)) + Else + hash = ByteArrayToString(GetMD5(SFile.GetBytes(__data.File, ErrMD5), ImgFormat, ErrMD5)) + End If + End If + Return hash + Catch + Return String.Empty + End Try + End Function + If Not StartMD5Checked Then + StartMD5Checked = True + If _ContentList.Exists(missingMD5) Then + Dim existingFiles As List(Of SFile) = SFile.GetFiles(MyFileSettings.CutPath, "*.jpg|*.jpeg|*.png|*.gif",, EDP.ReturnValue).ListIfNothing + Dim eIndx% + Dim eFinder As Predicate(Of SFile) = Function(ff) ff.File = data.File.File + If RemoveExistingDuplicates Then + RemoveExistingDuplicates = False + _ForceSaveUserInfo = True + If existingFiles.Count > 0 Then + Dim h$ + For i = existingFiles.Count - 1 To 0 Step -1 + h = __getMD5(New UserMedia With {.File = existingFiles(i)}, False) + If Not h.IsEmptyString Then + If hashList.ContainsKey(h) Then + MyMainLOG = $"[{ToStringForLog()}]: Removed image [{existingFiles(i).File}] (duplicate of [{hashList(h).File}])" + existingFiles(i).Delete(SFO.File, SFODelete.DeleteToRecycleBin, ErrMD5) + existingFiles.RemoveAt(i) + Else + hashList.Add(h, existingFiles(i)) + End If + End If + Next + End If + End If + For i = 0 To _ContentList.Count - 1 + data = _ContentList(i) + If (data.Type = UTypes.GIF Or data.Type = UTypes.Picture) Then + If data.MD5.IsEmptyString Then + ThrowAny(Token) + eIndx = existingFiles.FindIndex(eFinder) + If eIndx >= 0 Then + data.MD5 = __getMD5(New UserMedia With {.File = existingFiles(eIndx)}, False) + If Not data.MD5.IsEmptyString Then _ContentList(i) = data : _ForceSaveUserData = True + End If + End If + existingFiles.RemoveAll(eFinder) + End If + Next + If existingFiles.Count > 0 Then + For i = 0 To existingFiles.Count - 1 + f = existingFiles(i) + data = New UserMedia(f.File) With { + .State = UStates.Downloaded, + .Type = IIf(f.Extension = "gif", UTypes.GIF, UTypes.Picture), + .File = f + } + ThrowAny(Token) + data.MD5 = __getMD5(data, False) + If Not data.MD5.IsEmptyString Then _ContentList.Add(data) : _ForceSaveUserData = True + Next + existingFiles.Clear() + End If + End If + End If + + If _ContentList.Count > 0 Then + With _ContentList.Select(Function(d) d.MD5) + If .ListExists Then .ToList.ForEach(Sub(md5value) If Not hashList.ContainsKey(md5value) Then hashList.Add(md5value, New SFile)) + End With + End If + + For i = _TempMediaList.Count - 1 To 0 Step -1 + data = _TempMediaList(i) + If missingMD5(data) Then + ThrowAny(Token) + data.MD5 = __getMD5(data, True) + If Not data.MD5.IsEmptyString Then + If hashList.ContainsKey(data.MD5) Then + _TempMediaList.RemoveAt(i) + Else + hashList.Add(data.MD5, New SFile) + _TempMediaList(i) = data + End If + End If + End If + Next + End If + Catch ex As Exception + ProcessException(ex, Token, "ValidateMD5",, VALIDATE_MD5_ERROR) + End Try + End Sub +#End Region #Region "Get video static" Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal resp As Responser) As IEnumerable(Of UserMedia) Try @@ -310,7 +474,7 @@ Namespace API.Twitter Using j As EContainer = JsonDocument.Parse(r) If j.ListExists Then Dim u$ = GetVideoNodeURL(j) - If Not u.IsEmptyString Then Return {MediaFromData(u, PostID, String.Empty)} + If Not u.IsEmptyString Then Return {MediaFromData(u, PostID, String.Empty,,, UTypes.Video)} End If End Using End If @@ -359,10 +523,17 @@ Namespace API.Twitter End Function #End Region #Region "UrlFile" - Private Function UrlFile(ByVal URL As String) As String + Private Function UrlFile(ByVal URL As String, Optional ByVal GetWithoutExtension As Boolean = False) As String Try - Dim f As SFile = CStr(RegexReplace(LinkFormatterSecure(RegexReplace(URL.Replace("\", String.Empty), LinkPattern)), FilesPattern)) - If Not f.IsEmptyString Then Return f.File Else Return String.Empty + If Not URL.IsEmptyString Then + Dim f As SFile = CStr(RegexReplace(LinkFormatterSecure(RegexReplace(URL.Replace("\", String.Empty), LinkPattern)), FilesPattern)) + If f.IsEmptyString And GetWithoutExtension Then + URL = LinkFormatterSecure(RegexReplace(URL.Replace("\", String.Empty), LinkPattern)) + If Not URL.IsEmptyString Then f = New SFile With {.Name = URL.Split("/").LastOrDefault} + End If + If Not f.IsEmptyString Then Return f.File + End If + Return String.Empty Catch ex As Exception Return String.Empty End Try @@ -371,9 +542,10 @@ Namespace API.Twitter #Region "Create media" Private Shared Function MediaFromData(ByVal _URL As String, ByVal PostID As String, ByVal PostDate As String, Optional ByVal _PictureOption As String = Nothing, - Optional ByVal State As UStates = UStates.Unknown) As UserMedia + Optional ByVal State As UStates = UStates.Unknown, + Optional ByVal Type As UTypes = UTypes.Undefined) As UserMedia _URL = LinkFormatterSecure(RegexReplace(_URL.Replace("\", String.Empty), LinkPattern)) - Dim m As New UserMedia(_URL) With {.PictureOption = _PictureOption, .Post = New UserPost With {.ID = PostID}} + Dim m As New UserMedia(_URL) With {.PictureOption = _PictureOption, .Post = New UserPost With {.ID = PostID}, .Type = Type} If Not m.URL.IsEmptyString Then m.File = CStr(RegexReplace(m.URL, FilesPattern)) If Not m.PictureOption.IsEmptyString And Not m.File.IsEmptyString And Not m.URL.IsEmptyString Then m.URL = $"{m.URL.Replace($".{m.File.Extension}", String.Empty)}?format={m.File.Extension}&name={m.PictureOption}" @@ -391,20 +563,25 @@ Namespace API.Twitter #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 - With Responser - If .StatusCode = HttpStatusCode.NotFound Then - UserExists = False - ElseIf .StatusCode = HttpStatusCode.Unauthorized Then - UserSuspended = True - ElseIf .StatusCode = HttpStatusCode.BadRequest Then - MyMainLOG = "Twitter has invalid credentials" - ElseIf .StatusCode = HttpStatusCode.ServiceUnavailable Or .StatusCode = HttpStatusCode.InternalServerError Then - MyMainLOG = $"[{CInt(.StatusCode)}] Twitter is currently unavailable ({ToString()})" - Else - If Not FromPE Then LogError(ex, Message) : HasError = True - Return 0 - End If - End With + If AEquals(EObj, VALIDATE_MD5_ERROR) Then + If Not FromPE Then LogError(ex, Message) + Return 0 + Else + With Responser + If .StatusCode = HttpStatusCode.NotFound Then + UserExists = False + ElseIf .StatusCode = HttpStatusCode.Unauthorized Then + UserSuspended = True + ElseIf .StatusCode = HttpStatusCode.BadRequest Then + MyMainLOG = "Twitter has invalid credentials" + ElseIf .StatusCode = HttpStatusCode.ServiceUnavailable Or .StatusCode = HttpStatusCode.InternalServerError Then + MyMainLOG = $"[{CInt(.StatusCode)}] Twitter is currently unavailable ({ToString()})" + Else + If Not FromPE Then LogError(ex, Message) : HasError = True + Return 0 + End If + End With + End If Return 1 End Function #End Region diff --git a/SCrawler/API/UserDataBind.vb b/SCrawler/API/UserDataBind.vb index 8e88ef4..adcb318 100644 --- a/SCrawler/API/UserDataBind.vb +++ b/SCrawler/API/UserDataBind.vb @@ -370,7 +370,7 @@ 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 + Private ReadOnly RealUser As Predicate(Of IUserData) = Function(u) u.UserModel = UsageModel.Default And Not u.HOST.Key = PathPlugin.PluginKey Friend Overrides Sub OpenFolder() Try If Count > 0 Then diff --git a/SCrawler/API/XVIDEOS/Declarations.vb b/SCrawler/API/XVIDEOS/Declarations.vb index dcbdc58..4043f31 100644 --- a/SCrawler/API/XVIDEOS/Declarations.vb +++ b/SCrawler/API/XVIDEOS/Declarations.vb @@ -6,17 +6,17 @@ ' ' This program is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY +Imports SCrawler.API.Base Imports PersonalUtilities.Functions.RegularExpressions Namespace API.XVIDEOS Friend Module Declarations Friend Const XvideosSiteKey As String = "AndyProgram_XVIDEOS" - 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_VideoTitle As RParams = RParams.DMS("html5player.setVideoTitle\('(.+)(?='\);)", 1, EDP.ReturnValue, TitleHtmlConverter) 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("
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 + If Not UserURL.IsEmptyString AndAlso Domains.Count > 0 AndAlso Domains.Exists(Function(d) UserURL.ToLower.Contains(d.ToLower)) Then + Dim data As List(Of String) = RegexReplace(UserURL, UserRegex) + If data.ListExists(3) AndAlso Not data(2).IsEmptyString Then Return New ExchangeOptions(Site, data(2), data(1) = ChannelOption) End If Return Nothing End Function diff --git a/SCrawler/API/Xhamster/UserData.vb b/SCrawler/API/Xhamster/UserData.vb index fb3c5ff..f79fae2 100644 --- a/SCrawler/API/Xhamster/UserData.vb +++ b/SCrawler/API/Xhamster/UserData.vb @@ -38,7 +38,7 @@ Namespace API.Xhamster Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) _TempPhotoData.Clear() If DownloadVideos Then DownloadData(1, True, Token) - If DownloadImages Then + If Not IsChannel And DownloadImages Then DownloadData(1, False, Token) ReparsePhoto(Token) End If @@ -50,11 +50,16 @@ Namespace API.Xhamster Dim Type As UTypes = IIf(IsVideo, UTypes.VideoPre, UTypes.Picture) Dim mPages$ = IIf(IsVideo, "maxVideoPages", "maxPhotoPages") Dim listNode$() + Dim skipped As Boolean = False + Dim cBefore% = _TempMediaList.Count 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"}) + ElseIf IsChannel Then + URL = $"https://xhamster.com/channels/{Name}/newest{IIf(Page = 1, String.Empty, $"/{Page}")}" + listNode = {"trendingVideoListComponent", "models"} Else URL = $"https://xhamster.com/users/{Name}/{IIf(IsVideo, "videos", "photos")}{IIf(Page = 1, String.Empty, $"/{Page}")}" listNode = {If(IsVideo, "userVideoCollection", "userGalleriesCollection")} @@ -80,7 +85,7 @@ Namespace API.Xhamster If m.Post.Date.HasValue Then Select Case CheckDatesLimit(m.Post.Date.Value, Nothing) - Case DateResult.Skip : Continue For + Case DateResult.Skip : skipped = True : Continue For Case DateResult.Exit : Exit Sub End Select End If @@ -108,7 +113,7 @@ Namespace API.Xhamster End Using End If - If MaxPage > 0 AndAlso Page < MaxPage Then DownloadData(Page + 1, IsVideo, Token) + If (Not _TempMediaList.Count = cBefore Or skipped) And (IsChannel Or (MaxPage > 0 And Page < MaxPage)) Then DownloadData(Page + 1, IsVideo, Token) Catch ex As Exception ProcessException(ex, Token, $"data downloading error [{URL}]") End Try @@ -286,7 +291,7 @@ Namespace API.Xhamster .ID = j.Value("id"), .Date = AConvert(Of Date)(j.Value("created"), DateProvider, Nothing) }, - .PictureOption = j.Value("title").StringRemoveWinForbiddenSymbols, + .PictureOption = TitleHtmlConverter(j.Value("title")), .Object = New ExchObj } If PostDate.HasValue Then m.Post.Date = PostDate @@ -309,7 +314,7 @@ Namespace API.Xhamster 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 = TitleHtmlConverter(j.Value("titleLocalized")) If m.PictureOption.IsEmptyString Then m.PictureOption = m.Post.ID If setSpecialFolder Then m.SpecialFolder = m.PictureOption @@ -334,7 +339,7 @@ Namespace API.Xhamster Return If(Responser.Status = Net.WebExceptionStatus.ConnectionClosed, 1, 0) End Function #End Region -#Region "Idisposable support" +#Region "IDisposable support" Protected Overrides Sub Dispose(ByVal disposing As Boolean) If Not disposedValue And disposing Then _TempPhotoData.Clear() MyBase.Dispose(disposing) diff --git a/SCrawler/Download/Feed/DownloadFeedForm.vb b/SCrawler/Download/Feed/DownloadFeedForm.vb index 7689cdd..e519346 100644 --- a/SCrawler/Download/Feed/DownloadFeedForm.vb +++ b/SCrawler/Download/Feed/DownloadFeedForm.vb @@ -25,6 +25,8 @@ Namespace DownloadObjects Private FeedEndless As Boolean = False Private ReadOnly FileNotExist As New FPredicate(Of UserMediaD)(Function(d) Not d.Data.File.Exists) Private BttRefreshToolTipText As String = "Refresh data list" + Private CenterImage As Boolean = False + Private NumberOfVisibleImages As Integer = 1 #End Region #Region "Initializer" Friend Sub New() @@ -81,6 +83,25 @@ Namespace DownloadObjects DataRows = .FeedDataRows DataColumns = .FeedDataColumns FeedEndless = .FeedEndless + If .FeedCenterImage.Use Then + CenterImage = True + NumberOfVisibleImages = .FeedCenterImage + Else + CenterImage = False + NumberOfVisibleImages = 1 + End If + + If .FeedBackColor.Exists Then + BackColor = .FeedBackColor + Else + BackColor = SystemColors.Window + End If + If .FeedForeColor.Exists Then + ForeColor = .FeedForeColor + Else + ForeColor = SystemColors.WindowText + End If + Dim fsd As Boolean = .FeedStoreSessionsData ControlInvoke(ToolbarTOP, MENU_LOAD_SESSION, Sub() MENU_LOAD_SESSION.Visible = fsd @@ -107,7 +128,7 @@ Namespace DownloadObjects MyRange.HandlersSuspended = True MyRange.Limit = c MyRange.HandlersSuspended = False - If Not MyDefs.Initializing And rangeChanged Then RefillList() + If Not MyDefs.Initializing Then RefillList(False) End With End Sub #End Region @@ -376,9 +397,10 @@ Namespace DownloadObjects If d2.Count > 0 Then d.InsertRange(0, d2) : d2.Clear() End If Dim w% = GetWidth() + Dim h% = GetHeight() Dim p As New TPCELL(DataRows, DataColumns) Dim fmList As New List(Of FeedMedia) - d.ForEach(Sub(de) fmList.Add(New FeedMedia(de, w, AddressOf FeedMedia_MediaDeleted))) + d.ForEach(Sub(de) fmList.Add(New FeedMedia(de, w, h, AddressOf FeedMedia_MediaDeleted))) If fmList.Count > 0 Then fmList.ListDisposeRemoveAll(Function(fm) fm Is Nothing OrElse fm.HasError) If fmList.Count > 0 Then For i = 0 To fmList.Count - 1 @@ -420,6 +442,13 @@ Namespace DownloadObjects Private Function GetWidth() As Integer Return (TP_DATA.Width - PaddingE.GetOf({Me, TP_DATA}).Horizontal(2)) / DataColumns End Function + Private Function GetHeight() As Integer + If CenterImage And DataColumns = 1 Then + Return (TP_DATA.Height - PaddingE.GetOf({Me, TP_DATA}).Vertical(2)) / IIf(NumberOfVisibleImages > 0, NumberOfVisibleImages, 1) + Else + Return -1 + End If + End Function Private Sub DownloadFeedForm_ResizeEnd(sender As Object, e As EventArgs) Handles Me.ResizeEnd ResizeGrid() End Sub @@ -431,10 +460,11 @@ Namespace DownloadObjects With TP_DATA If .Controls.Count > 0 Then Dim w% = GetWidth() + Dim h% = GetHeight() Dim p As TableLayoutPanelCellPosition Dim rh As New Dictionary(Of Integer, List(Of Integer)) For Each cnt As FeedMedia In .Controls - cnt.Width = w + cnt.RerenderObject(w, h) p = .GetCellPosition(cnt) If Not rh.ContainsKey(p.Row) Then rh.Add(p.Row, New List(Of Integer)) rh(p.Row).Add(cnt.Height) diff --git a/SCrawler/Download/Feed/FeedMedia.vb b/SCrawler/Download/Feed/FeedMedia.vb index b684649..d9b79e3 100644 --- a/SCrawler/Download/Feed/FeedMedia.vb +++ b/SCrawler/Download/Feed/FeedMedia.vb @@ -29,19 +29,19 @@ Namespace DownloadObjects End Property Friend ReadOnly Property HasError As Boolean Friend ReadOnly File As SFile - Public Shadows Property Width As Integer + Public Shadows Property Width(Optional ByVal UpdateImage As Boolean = True) As Integer Get Return MyBase.Width End Get Set(ByVal w As Integer) If Size.Width <> w Then - Dim s As New Size(w, If(MyImage Is Nothing, VideoHeight, MyImage.FitToWidthF(w).Height)) + Dim s As New Size(w, If(MyImage Is Nothing, VideoHeight, If(UpdateImage, MyImage.FitToWidthF(w).Height, MyPicture.Height))) Dim objSize As Size = s - objSize.Height += (TP_MAIN.RowStyles(0).Height + PaddingE.GetOf({TP_MAIN}).Vertical(2)) + objSize.Height += ObjectsPaddingHeight MinimumSize = objSize MyBase.MaximumSize = objSize Size = objSize - If Not MyImage Is Nothing Then + If UpdateImage AndAlso Not MyImage Is Nothing Then With MyPicture .MinimumSize = Nothing .MaximumSize = Nothing @@ -53,6 +53,11 @@ Namespace DownloadObjects End If End Set End Property + Private ReadOnly Property ObjectsPaddingHeight + Get + Return TP_MAIN.RowStyles(0).Height + PaddingE.GetOf({TP_MAIN}).Vertical(2) + End Get + End Property Private ReadOnly UserKey As String Private ReadOnly Post As UserMedia Friend ReadOnly Property Checked As Boolean @@ -61,12 +66,56 @@ Namespace DownloadObjects End Get End Property Friend ReadOnly Property Information As String + Private Function GetImageResize(ByVal Width As Integer, ByVal Height As Integer) As Size + If Height > 0 Then + Dim h% = Height = ObjectsPaddingHeight + If h <= 0 Then h = Height + Dim s As Size = MyImage.FitToHeightF(h) + s = MyImage.FitToWidthF(s, Width, False) + If s.Height > MyImage.Height Then s = MyImage.Size + Return s + Else + Return MyImage.FitToWidthF(Width) + End If + End Function + Friend Sub RerenderObject(ByVal Width As Integer, ByVal Height As Integer) + If Not MyImage Is Nothing Then + Dim s As Size + If Height > 0 Then + s = GetImageResize(Width, Height) + With MyPicture + .MinimumSize = Nothing + .MaximumSize = Nothing + .Size = s + .MinimumSize = s + .MaximumSize = s + .Anchor = AnchorStyles.Top + End With + Me.Width(False) = Width + Else + Me.Width = Width + MyPicture.Anchor = AnchorStyles.Left + AnchorStyles.Top + End If + Else + Me.Width = Width + End If + End Sub + Private Sub ApplyColors() + If Settings.FeedBackColor.Exists Then + BackColor = Settings.FeedBackColor + LBL_INFO.BackColor = Settings.FeedBackColor + End If + If Settings.FeedForeColor.Exists Then + ForeColor = Settings.FeedForeColor + LBL_INFO.ForeColor = Settings.FeedForeColor + End If + End Sub #End Region #Region "Initializers" Public Sub New() InitializeComponent() End Sub - Friend Sub New(ByVal Media As UserMediaD, ByVal Width As Integer, ByVal Handler As MediaDeletedEventHandler) + Friend Sub New(ByVal Media As UserMediaD, ByVal Width As Integer, ByVal Height As Integer, ByVal Handler As MediaDeletedEventHandler) Try InitializeComponent() File = Media.Data.File @@ -92,14 +141,15 @@ Namespace DownloadObjects Select Case Media.Data.Type Case UserMedia.Types.Picture, UserMedia.Types.GIF MyImage = New ImageRenderer(File) - s = MyImage.FitToWidthF(Width) + Dim a As AnchorStyles = AnchorStyles.Top + If(Height > 0, 0, AnchorStyles.Left) + s = GetImageResize(Width, Height) h = s.Height MyPicture = New PictureBox With { .SizeMode = PictureBoxSizeMode.Zoom, .Image = MyImage, .InitialImage = .Image, .Dock = DockStyle.None, - .Anchor = AnchorStyles.Left + AnchorStyles.Top, + .Anchor = a, .Size = s, .MinimumSize = s, .MaximumSize = s, @@ -141,11 +191,11 @@ Namespace DownloadObjects If Settings.FeedAddDateToCaption Then info &= $" ({Media.Date.ToStringDate(ADateTime.Formats.BaseDateTime)})" LBL_INFO.Text = info - s = New Size(Width, h + TP_MAIN.RowStyles(0).Height + PaddingE.GetOf({TP_MAIN}).Vertical(2)) + s = New Size(Width, h + ObjectsPaddingHeight) Size = s MinimumSize = s MaximumSize = s - + ApplyColors() If Not Handler Is Nothing Then AddHandler Me.MediaDeleted, Handler Else Throw New ArgumentNullException With {.HelpLink = 1} diff --git a/SCrawler/Download/Groups/DownloadGroup.vb b/SCrawler/Download/Groups/DownloadGroup.vb index 5dafc8f..0d91b36 100644 --- a/SCrawler/Download/Groups/DownloadGroup.vb +++ b/SCrawler/Download/Groups/DownloadGroup.vb @@ -90,18 +90,7 @@ Namespace DownloadObjects.Groups End Sub Friend Sub New(ByVal e As EContainer) Me.New - If e.Attributes.Contains(New EAttribute(Name_Name)) Then - 'TODELETE: 2022.10.18.0 - NeedToSave = True - Name = e.Attribute(Name_Name) - Temporary = e.Attribute(Name_Temporary).Value.FromXML(Of Integer)(CInt(CheckState.Indeterminate)) - Favorite = e.Attribute(Name_Favorite).Value.FromXML(Of Integer)(CInt(CheckState.Indeterminate)) - ReadyForDownload = e.Attribute(Name_ReadyForDownload).Value.FromXML(Of Boolean)(True) - ReadyForDownloadIgnore = e.Attribute(Name_ReadyForDownloadIgnore).Value.FromXML(Of Boolean)(False) - If Not e.Value.IsEmptyString Then Labels.ListAddList(e.Value.Split("|"), LAP.NotContainsOnly) - Else - Import(e) - End If + Import(e) End Sub #End Region #Region "ToString" diff --git a/SCrawler/Download/TDownloader.vb b/SCrawler/Download/TDownloader.vb index b33fe3e..02a74d2 100644 --- a/SCrawler/Download/TDownloader.vb +++ b/SCrawler/Download/TDownloader.vb @@ -51,7 +51,7 @@ Namespace DownloadObjects If Not u.Name.IsEmptyString And Not u.Site.IsEmptyString Then User = Settings.GetUser(u) End If Data = New UserMedia(e(Name_Media), User) - [Date] = AConvert(Of Date)(e.Value(Name_Date), ParsersDataDateProvider, Now) + [Date] = AConvert(Of Date)(e.Value(Name_Date), DateTimeDefaultProvider, Now) Session = e.Value(Name_Session).FromXML(Of Integer)(0) Dim f As SFile = e.Value(Name_File) If f.Exists Then Data.File = f @@ -78,7 +78,7 @@ Namespace DownloadObjects Friend Function ToEContainer(Optional ByVal e As ErrorsDescriber = Nothing) As EContainer Implements IEContainerProvider.ToEContainer Return ListAddValue(New EContainer(Name_Data, String.Empty) From { Data.ToEContainer, - New EContainer(Name_Date, AConvert(Of String)([Date], ParsersDataDateProvider, String.Empty)), + New EContainer(Name_Date, AConvert(Of String)([Date], DateTimeDefaultProvider, String.Empty)), New EContainer(Name_Session, Session), New EContainer(Name_File, Data.File)}, If(Not User Is Nothing, DirectCast(User, UserDataBase).User.ToEContainer, Nothing), LAP.IgnoreICopier) diff --git a/SCrawler/Editors/ColorPicker.Designer.vb b/SCrawler/Editors/ColorPicker.Designer.vb new file mode 100644 index 0000000..500569b --- /dev/null +++ b/SCrawler/Editors/ColorPicker.Designer.vb @@ -0,0 +1,141 @@ +' 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 Editors + + Partial Public Class ColorPicker : Inherits System.Windows.Forms.UserControl + + 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() + Me.components = New System.ComponentModel.Container() + Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(ColorPicker)) + Dim TT_MAIN As System.Windows.Forms.ToolTip + Me.TP_MAIN = New System.Windows.Forms.TableLayoutPanel() + Me.LBL_CAPTION = New System.Windows.Forms.Label() + Me.LBL_COLORS = New System.Windows.Forms.Label() + Me.BTT_COLORS_FORE = New System.Windows.Forms.Button() + Me.BTT_COLORS_BACK = New System.Windows.Forms.Button() + Me.BTT_COLORS_CLEAR = New System.Windows.Forms.Button() + TT_MAIN = New System.Windows.Forms.ToolTip(Me.components) + Me.TP_MAIN.SuspendLayout() + Me.SuspendLayout() + ' + 'TP_MAIN + ' + Me.TP_MAIN.ColumnCount = 5 + Me.TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 105.0!)) + Me.TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + Me.TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 22.0!)) + Me.TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 22.0!)) + Me.TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 22.0!)) + Me.TP_MAIN.Controls.Add(Me.LBL_CAPTION, 0, 0) + Me.TP_MAIN.Controls.Add(Me.LBL_COLORS, 1, 0) + Me.TP_MAIN.Controls.Add(Me.BTT_COLORS_FORE, 2, 0) + Me.TP_MAIN.Controls.Add(Me.BTT_COLORS_BACK, 3, 0) + Me.TP_MAIN.Controls.Add(Me.BTT_COLORS_CLEAR, 4, 0) + Me.TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill + Me.TP_MAIN.Location = New System.Drawing.Point(0, 0) + Me.TP_MAIN.Margin = New System.Windows.Forms.Padding(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.Percent, 100.0!)) + Me.TP_MAIN.Size = New System.Drawing.Size(340, 28) + Me.TP_MAIN.TabIndex = 3 + ' + 'LBL_CAPTION + ' + Me.LBL_CAPTION.AutoSize = True + Me.LBL_CAPTION.Dock = System.Windows.Forms.DockStyle.Fill + Me.LBL_CAPTION.Location = New System.Drawing.Point(3, 0) + Me.LBL_CAPTION.Name = "LBL_CAPTION" + Me.LBL_CAPTION.Size = New System.Drawing.Size(99, 28) + Me.LBL_CAPTION.TabIndex = 0 + Me.LBL_CAPTION.TextAlign = System.Drawing.ContentAlignment.MiddleRight + ' + 'LBL_COLORS + ' + Me.LBL_COLORS.AutoSize = True + Me.LBL_COLORS.Dock = System.Windows.Forms.DockStyle.Fill + Me.LBL_COLORS.Location = New System.Drawing.Point(108, 3) + Me.LBL_COLORS.Margin = New System.Windows.Forms.Padding(3) + Me.LBL_COLORS.Name = "LBL_COLORS" + Me.LBL_COLORS.Size = New System.Drawing.Size(163, 22) + Me.LBL_COLORS.TabIndex = 1 + Me.LBL_COLORS.Text = "Here's what it looks like." + Me.LBL_COLORS.TextAlign = System.Drawing.ContentAlignment.MiddleCenter + ' + 'BTT_COLORS_FORE + ' + Me.BTT_COLORS_FORE.Dock = System.Windows.Forms.DockStyle.Fill + Me.BTT_COLORS_FORE.Location = New System.Drawing.Point(276, 2) + Me.BTT_COLORS_FORE.Margin = New System.Windows.Forms.Padding(2) + Me.BTT_COLORS_FORE.Name = "BTT_COLORS_FORE" + Me.BTT_COLORS_FORE.Size = New System.Drawing.Size(18, 24) + Me.BTT_COLORS_FORE.TabIndex = 2 + Me.BTT_COLORS_FORE.Tag = "F" + Me.BTT_COLORS_FORE.Text = "F" + TT_MAIN.SetToolTip(Me.BTT_COLORS_FORE, "Font color") + Me.BTT_COLORS_FORE.UseVisualStyleBackColor = True + ' + 'BTT_COLORS_BACK + ' + Me.BTT_COLORS_BACK.Dock = System.Windows.Forms.DockStyle.Fill + Me.BTT_COLORS_BACK.Location = New System.Drawing.Point(298, 2) + Me.BTT_COLORS_BACK.Margin = New System.Windows.Forms.Padding(2) + Me.BTT_COLORS_BACK.Name = "BTT_COLORS_BACK" + Me.BTT_COLORS_BACK.Size = New System.Drawing.Size(18, 24) + Me.BTT_COLORS_BACK.TabIndex = 3 + Me.BTT_COLORS_BACK.Tag = "C" + Me.BTT_COLORS_BACK.Text = "C" + TT_MAIN.SetToolTip(Me.BTT_COLORS_BACK, "Back color") + Me.BTT_COLORS_BACK.UseVisualStyleBackColor = True + ' + 'BTT_COLORS_CLEAR + ' + Me.BTT_COLORS_CLEAR.BackgroundImage = CType(resources.GetObject("BTT_COLORS_CLEAR.BackgroundImage"), System.Drawing.Image) + Me.BTT_COLORS_CLEAR.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom + Me.BTT_COLORS_CLEAR.Dock = System.Windows.Forms.DockStyle.Fill + Me.BTT_COLORS_CLEAR.Location = New System.Drawing.Point(320, 2) + Me.BTT_COLORS_CLEAR.Margin = New System.Windows.Forms.Padding(2) + Me.BTT_COLORS_CLEAR.Name = "BTT_COLORS_CLEAR" + Me.BTT_COLORS_CLEAR.Size = New System.Drawing.Size(18, 24) + Me.BTT_COLORS_CLEAR.TabIndex = 4 + Me.BTT_COLORS_CLEAR.Tag = "D" + TT_MAIN.SetToolTip(Me.BTT_COLORS_CLEAR, "Reset") + Me.BTT_COLORS_CLEAR.UseVisualStyleBackColor = True + ' + 'ColorPicker + ' + Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) + Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font + Me.Controls.Add(Me.TP_MAIN) + Me.Name = "ColorPicker" + Me.Size = New System.Drawing.Size(340, 28) + Me.TP_MAIN.ResumeLayout(False) + Me.TP_MAIN.PerformLayout() + Me.ResumeLayout(False) + + End Sub + Private WithEvents LBL_COLORS As Label + Private WithEvents BTT_COLORS_FORE As Button + Private WithEvents BTT_COLORS_BACK As Button + Private WithEvents BTT_COLORS_CLEAR As Button + Private WithEvents TP_MAIN As TableLayoutPanel + Private WithEvents LBL_CAPTION As Label + End Class +End Namespace \ No newline at end of file diff --git a/SCrawler/Editors/ColorPicker.resx b/SCrawler/Editors/ColorPicker.resx new file mode 100644 index 0000000..c6fe36e --- /dev/null +++ b/SCrawler/Editors/ColorPicker.resx @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + False + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go + tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX + AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC + + + \ No newline at end of file diff --git a/SCrawler/Editors/ColorPicker.vb b/SCrawler/Editors/ColorPicker.vb new file mode 100644 index 0000000..6d1226f --- /dev/null +++ b/SCrawler/Editors/ColorPicker.vb @@ -0,0 +1,113 @@ +' 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.ComponentModel +Imports PersonalUtilities.Forms +Imports PersonalUtilities.Functions.XML.Objects +Namespace Editors + Public Class ColorPicker : Implements IChangeDetectorCompatible + Private Event DataChanged As EventHandler Implements IChangeDetectorCompatible.DataChanged + Public Sub New() + InitializeComponent() + End Sub +#Region "Appearance" + + Public Property CaptionWidth As Integer + Get + Return TP_MAIN.ColumnStyles(0).Width + End Get + Set(ByVal w As Integer) + TP_MAIN.ColumnStyles(0).Width = w + End Set + End Property + Private ReadOnly ButtonsMarginDefault As New Padding(2) + + Public Property ButtonsMargin As Padding + Get + Return BTT_COLORS_CLEAR.Margin + End Get + Set(ByVal m As Padding) + BTT_COLORS_BACK.Margin = m + BTT_COLORS_FORE.Margin = m + BTT_COLORS_CLEAR.Margin = m + End Set + End Property + Private Function ShouldSerializeButtonsMargin() As Boolean + Return Not ButtonsMargin.Equals(ButtonsMarginDefault) + End Function + Private Sub ResetButtonsMargin() + ButtonsMargin = ButtonsMarginDefault + End Sub + + Public Property CaptionText As String + Get + Return LBL_CAPTION.Text + End Get + Set(ByVal t As String) + LBL_CAPTION.Text = t + End Set + End Property +#End Region +#Region "Colors" + Private BackColorDefault As Color = DefaultBackColor + Private _BackColorImpl As Color? = Nothing + Private Property BackColorImpl As Color? + Get + Return _BackColorImpl + End Get + Set(ByVal c As Color?) + _BackColorImpl = c + If _BackColorImpl.HasValue Then LBL_COLORS.BackColor = _BackColorImpl.Value Else LBL_COLORS.BackColor = BackColorDefault + End Set + End Property + Private ForeColorDefault As Color = DefaultForeColor + Private _ForeColorImpl As Color? = Nothing + Private Property ForeColorImpl As Color? + Get + Return _ForeColorImpl + End Get + Set(ByVal c As Color?) + _ForeColorImpl = c + If _ForeColorImpl.HasValue Then LBL_COLORS.ForeColor = _ForeColorImpl.Value Else LBL_COLORS.ForeColor = ForeColorDefault + End Set + End Property +#End Region +#Region "Get, Set" + Friend Sub ColorsSet(ByVal b As XMLValue(Of Color), ByVal f As XMLValue(Of Color), ByVal bDefault As Color, ByVal fDefault As Color) + BackColorDefault = bDefault + If b.Exists Then + BackColorImpl = b.Value + Else + BackColorImpl = Nothing + End If + ForeColorDefault = fDefault + If f.Exists Then + ForeColorImpl = f.Value + Else + ForeColorImpl = Nothing + End If + End Sub + Friend Sub ColorsGet(ByRef b As XMLValue(Of Color), ByRef f As XMLValue(Of Color)) + If BackColorImpl.HasValue Then b.Value = BackColorImpl.Value Else b.ValueF = Nothing + If ForeColorImpl.HasValue Then f.Value = ForeColorImpl.Value Else f.ValueF = Nothing + End Sub +#End Region +#Region "Buttons handlers" + Private Sub COLOR_BUTTONS_Click(ByVal Sender As Button, ByVal e As EventArgs) Handles BTT_COLORS_BACK.Click, + BTT_COLORS_FORE.Click, + BTT_COLORS_CLEAR.Click + Select Case CStr(Sender.Tag) + Case "F" : ForeColorImpl = AFontColor.SelectNewColor(ForeColorImpl, EDP.ReturnValue) + Case "C" : BackColorImpl = AFontColor.SelectNewColor(BackColorImpl, EDP.ReturnValue) + Case "D" : BackColorImpl = Nothing : ForeColorImpl = Nothing + End Select + RaiseEvent DataChanged(Me, Nothing) + End Sub +#End Region + End Class +End Namespace \ No newline at end of file diff --git a/SCrawler/Editors/GlobalSettingsForm.Designer.vb b/SCrawler/Editors/GlobalSettingsForm.Designer.vb index 84cf9e9..0ead2f7 100644 --- a/SCrawler/Editors/GlobalSettingsForm.Designer.vb +++ b/SCrawler/Editors/GlobalSettingsForm.Designer.vb @@ -24,16 +24,18 @@ Namespace Editors Private Sub InitializeComponent() Me.components = New System.ComponentModel.Container() Dim TP_BASIS As System.Windows.Forms.TableLayoutPanel - Dim ActionButton13 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() + 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(GlobalSettingsForm)) - Dim ActionButton14 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() + Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim TP_IMAGES As System.Windows.Forms.TableLayoutPanel - Dim ActionButton15 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() - Dim ActionButton16 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() - Dim ActionButton17 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() - Dim ActionButton18 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() - Dim ActionButton19 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() - Dim ActionButton20 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 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 ActionButton9 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() + Dim ActionButton10 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim TP_FILE_NAME As System.Windows.Forms.TableLayoutPanel Dim TP_FILE_PATTERNS As System.Windows.Forms.TableLayoutPanel Dim LBL_DATE_POS As System.Windows.Forms.Label @@ -46,14 +48,14 @@ Namespace Editors Dim TP_CHANNELS As System.Windows.Forms.TableLayoutPanel Dim TAB_BEHAVIOR As System.Windows.Forms.TabPage Dim TP_BEHAVIOR As System.Windows.Forms.TableLayoutPanel - Dim ActionButton21 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() - Dim ActionButton22 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() + Dim ActionButton11 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() + Dim ActionButton12 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim TP_OPEN_INFO As System.Windows.Forms.TableLayoutPanel Dim TP_OPEN_PROGRESS As System.Windows.Forms.TableLayoutPanel Dim TAB_DOWN As System.Windows.Forms.TabPage Dim TP_DOWNLOADING As System.Windows.Forms.TableLayoutPanel - Dim ActionButton23 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() - Dim ActionButton24 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() + Dim ActionButton13 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() + Dim ActionButton14 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim TP_MISSING_DATA As System.Windows.Forms.TableLayoutPanel Dim TAB_FEED As System.Windows.Forms.TabPage Dim TP_FEED As System.Windows.Forms.TableLayoutPanel @@ -71,6 +73,8 @@ Namespace Editors Me.CH_SHOW_GROUPS = New System.Windows.Forms.CheckBox() Me.CH_USERS_GROUPING = New System.Windows.Forms.CheckBox() Me.TXT_USER_AGENT = New PersonalUtilities.Forms.Controls.TextBoxExtended() + Me.TXT_USER_LIST_IMAGE = New PersonalUtilities.Forms.Controls.TextBoxExtended() + Me.COLORS_USERLIST = New SCrawler.Editors.ColorPicker() Me.OPT_FILE_NAME_REPLACE = New System.Windows.Forms.RadioButton() Me.OPT_FILE_NAME_ADD_DATE = New System.Windows.Forms.RadioButton() Me.CH_FILE_NAME_CHANGE = New System.Windows.Forms.CheckBox() @@ -99,6 +103,7 @@ Namespace Editors Me.CH_NOTIFY_CHANNELS = New System.Windows.Forms.CheckBox() Me.CH_NOTIFY_SAVED_POSTS = New System.Windows.Forms.CheckBox() Me.CH_DOWN_REPARSE_MISSING = New System.Windows.Forms.CheckBox() + Me.CH_NAME_SITE_FRIENDLY = New System.Windows.Forms.CheckBox() Me.TXT_CHANNELS_ROWS = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_CHANNELS_COLUMNS = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.CH_DOWN_IMAGES_NATIVE = New System.Windows.Forms.CheckBox() @@ -112,11 +117,14 @@ Namespace Editors Me.CH_DOWN_OPEN_PROGRESS = New System.Windows.Forms.CheckBox() Me.TXT_SCRIPT = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_DOWN_COMPLETE_SCRIPT = New PersonalUtilities.Forms.Controls.TextBoxExtended() + Me.CH_UNAME_UP = New System.Windows.Forms.CheckBox() Me.TXT_FEED_ROWS = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_FEED_COLUMNS = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.CH_FEED_ENDLESS = New System.Windows.Forms.CheckBox() Me.CH_FEED_ADD_SESSION = New System.Windows.Forms.CheckBox() Me.CH_FEED_ADD_DATE = New System.Windows.Forms.CheckBox() + Me.TXT_FEED_CENTER_IMAGE = New PersonalUtilities.Forms.Controls.TextBoxExtended() + Me.COLORS_FEED = New SCrawler.Editors.ColorPicker() Me.TAB_MAIN = New System.Windows.Forms.TabControl() Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer() TP_BASIS = New System.Windows.Forms.TableLayoutPanel() @@ -153,6 +161,7 @@ Namespace Editors CType(Me.TXT_MAX_JOBS_CHANNELS, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_IMGUR_CLIENT_ID, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_USER_AGENT, System.ComponentModel.ISupportInitialize).BeginInit() + CType(Me.TXT_USER_LIST_IMAGE, System.ComponentModel.ISupportInitialize).BeginInit() TP_FILE_NAME.SuspendLayout() TP_FILE_PATTERNS.SuspendLayout() TP_CHANNELS_IMGS.SuspendLayout() @@ -180,6 +189,7 @@ Namespace Editors TP_FEED_IMG_COUNT.SuspendLayout() CType(Me.TXT_FEED_ROWS, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_FEED_COLUMNS, System.ComponentModel.ISupportInitialize).BeginInit() + CType(Me.TXT_FEED_CENTER_IMAGE, System.ComponentModel.ISupportInitialize).BeginInit() TAB_NOTIFY.SuspendLayout() TP_NOTIFY_MAIN.SuspendLayout() Me.TAB_MAIN.SuspendLayout() @@ -199,13 +209,15 @@ Namespace Editors TP_BASIS.Controls.Add(Me.TXT_MAX_JOBS_CHANNELS, 0, 4) TP_BASIS.Controls.Add(Me.CH_CHECK_VER_START, 0, 5) TP_BASIS.Controls.Add(Me.TXT_IMGUR_CLIENT_ID, 0, 7) - TP_BASIS.Controls.Add(Me.CH_SHOW_GROUPS, 0, 8) - TP_BASIS.Controls.Add(Me.CH_USERS_GROUPING, 0, 9) + TP_BASIS.Controls.Add(Me.CH_SHOW_GROUPS, 0, 10) + TP_BASIS.Controls.Add(Me.CH_USERS_GROUPING, 0, 11) TP_BASIS.Controls.Add(Me.TXT_USER_AGENT, 0, 6) + TP_BASIS.Controls.Add(Me.TXT_USER_LIST_IMAGE, 0, 8) + TP_BASIS.Controls.Add(Me.COLORS_USERLIST, 0, 9) TP_BASIS.Dock = System.Windows.Forms.DockStyle.Fill TP_BASIS.Location = New System.Drawing.Point(3, 3) TP_BASIS.Name = "TP_BASIS" - TP_BASIS.RowCount = 11 + TP_BASIS.RowCount = 13 TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) @@ -214,20 +226,23 @@ Namespace Editors TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) + TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) + TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_BASIS.Size = New System.Drawing.Size(570, 279) + TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20.0!)) + TP_BASIS.Size = New System.Drawing.Size(570, 337) TP_BASIS.TabIndex = 0 ' 'TXT_GLOBAL_PATH ' - ActionButton13.BackgroundImage = CType(resources.GetObject("ActionButton13.BackgroundImage"), System.Drawing.Image) - ActionButton13.Name = "Open" - ActionButton14.BackgroundImage = CType(resources.GetObject("ActionButton14.BackgroundImage"), System.Drawing.Image) - ActionButton14.Name = "Clear" - Me.TXT_GLOBAL_PATH.Buttons.Add(ActionButton13) - Me.TXT_GLOBAL_PATH.Buttons.Add(ActionButton14) + ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image) + ActionButton1.Name = "Open" + ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image) + ActionButton2.Name = "Clear" + Me.TXT_GLOBAL_PATH.Buttons.Add(ActionButton1) + Me.TXT_GLOBAL_PATH.Buttons.Add(ActionButton2) Me.TXT_GLOBAL_PATH.CaptionText = "Data Path" Me.TXT_GLOBAL_PATH.CaptionToolTipEnabled = True Me.TXT_GLOBAL_PATH.CaptionToolTipText = "Root path for storing users' data" @@ -288,9 +303,9 @@ Namespace Editors ' 'TXT_COLLECTIONS_PATH ' - ActionButton15.BackgroundImage = CType(resources.GetObject("ActionButton15.BackgroundImage"), System.Drawing.Image) - ActionButton15.Name = "Clear" - Me.TXT_COLLECTIONS_PATH.Buttons.Add(ActionButton15) + ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image) + ActionButton3.Name = "Clear" + Me.TXT_COLLECTIONS_PATH.Buttons.Add(ActionButton3) Me.TXT_COLLECTIONS_PATH.CaptionText = "Collections folder" Me.TXT_COLLECTIONS_PATH.CaptionToolTipEnabled = True Me.TXT_COLLECTIONS_PATH.CaptionToolTipText = "Set collections folder name (name only)" @@ -302,10 +317,10 @@ Namespace Editors ' 'TXT_MAX_JOBS_USERS ' - ActionButton16.BackgroundImage = CType(resources.GetObject("ActionButton16.BackgroundImage"), System.Drawing.Image) - ActionButton16.Name = "Refresh" - ActionButton16.ToolTipText = "Set to default" - Me.TXT_MAX_JOBS_USERS.Buttons.Add(ActionButton16) + ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image) + ActionButton4.Name = "Refresh" + ActionButton4.ToolTipText = "Set to default" + Me.TXT_MAX_JOBS_USERS.Buttons.Add(ActionButton4) Me.TXT_MAX_JOBS_USERS.CaptionSizeType = System.Windows.Forms.SizeType.Percent Me.TXT_MAX_JOBS_USERS.CaptionText = "Maximum downloading tasks of users" Me.TXT_MAX_JOBS_USERS.CaptionWidth = 50.0R @@ -321,10 +336,10 @@ Namespace Editors ' 'TXT_MAX_JOBS_CHANNELS ' - ActionButton17.BackgroundImage = CType(resources.GetObject("ActionButton17.BackgroundImage"), System.Drawing.Image) - ActionButton17.Name = "Refresh" - ActionButton17.ToolTipText = "Set to default" - Me.TXT_MAX_JOBS_CHANNELS.Buttons.Add(ActionButton17) + ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image) + ActionButton5.Name = "Refresh" + ActionButton5.ToolTipText = "Set to default" + Me.TXT_MAX_JOBS_CHANNELS.Buttons.Add(ActionButton5) Me.TXT_MAX_JOBS_CHANNELS.CaptionSizeType = System.Windows.Forms.SizeType.Percent Me.TXT_MAX_JOBS_CHANNELS.CaptionText = "Maximum downloading tasks of channels" Me.TXT_MAX_JOBS_CHANNELS.CaptionWidth = 50.0R @@ -351,9 +366,9 @@ Namespace Editors ' 'TXT_IMGUR_CLIENT_ID ' - ActionButton18.BackgroundImage = CType(resources.GetObject("ActionButton18.BackgroundImage"), System.Drawing.Image) - ActionButton18.Name = "Clear" - Me.TXT_IMGUR_CLIENT_ID.Buttons.Add(ActionButton18) + ActionButton6.BackgroundImage = CType(resources.GetObject("ActionButton6.BackgroundImage"), System.Drawing.Image) + ActionButton6.Name = "Clear" + Me.TXT_IMGUR_CLIENT_ID.Buttons.Add(ActionButton6) Me.TXT_IMGUR_CLIENT_ID.CaptionText = "Imgur Client ID" Me.TXT_IMGUR_CLIENT_ID.Dock = System.Windows.Forms.DockStyle.Fill Me.TXT_IMGUR_CLIENT_ID.Location = New System.Drawing.Point(4, 204) @@ -365,10 +380,10 @@ Namespace Editors ' Me.CH_SHOW_GROUPS.AutoSize = True Me.CH_SHOW_GROUPS.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_SHOW_GROUPS.Location = New System.Drawing.Point(4, 233) + Me.CH_SHOW_GROUPS.Location = New System.Drawing.Point(4, 288) Me.CH_SHOW_GROUPS.Name = "CH_SHOW_GROUPS" Me.CH_SHOW_GROUPS.Size = New System.Drawing.Size(562, 19) - Me.CH_SHOW_GROUPS.TabIndex = 8 + Me.CH_SHOW_GROUPS.TabIndex = 10 Me.CH_SHOW_GROUPS.Text = "Show groups" TT_MAIN.SetToolTip(Me.CH_SHOW_GROUPS, "Grouping users by site") Me.CH_SHOW_GROUPS.UseVisualStyleBackColor = True @@ -377,24 +392,24 @@ Namespace Editors ' Me.CH_USERS_GROUPING.AutoSize = True Me.CH_USERS_GROUPING.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_USERS_GROUPING.Location = New System.Drawing.Point(4, 259) + Me.CH_USERS_GROUPING.Location = New System.Drawing.Point(4, 314) Me.CH_USERS_GROUPING.Name = "CH_USERS_GROUPING" Me.CH_USERS_GROUPING.Size = New System.Drawing.Size(562, 19) - Me.CH_USERS_GROUPING.TabIndex = 9 + Me.CH_USERS_GROUPING.TabIndex = 11 Me.CH_USERS_GROUPING.Text = "Use user grouping" TT_MAIN.SetToolTip(Me.CH_USERS_GROUPING, "Group users by groups and/or labels") Me.CH_USERS_GROUPING.UseVisualStyleBackColor = True ' 'TXT_USER_AGENT ' - ActionButton19.BackgroundImage = CType(resources.GetObject("ActionButton19.BackgroundImage"), System.Drawing.Image) - ActionButton19.Name = "Refresh" - ActionButton19.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh - ActionButton20.BackgroundImage = CType(resources.GetObject("ActionButton20.BackgroundImage"), System.Drawing.Image) - ActionButton20.Name = "Clear" - ActionButton20.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear - Me.TXT_USER_AGENT.Buttons.Add(ActionButton19) - Me.TXT_USER_AGENT.Buttons.Add(ActionButton20) + ActionButton7.BackgroundImage = CType(resources.GetObject("ActionButton7.BackgroundImage"), System.Drawing.Image) + ActionButton7.Name = "Refresh" + ActionButton7.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh + ActionButton8.BackgroundImage = CType(resources.GetObject("ActionButton8.BackgroundImage"), System.Drawing.Image) + ActionButton8.Name = "Clear" + ActionButton8.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear + Me.TXT_USER_AGENT.Buttons.Add(ActionButton7) + Me.TXT_USER_AGENT.Buttons.Add(ActionButton8) Me.TXT_USER_AGENT.CaptionText = "UserAgent" Me.TXT_USER_AGENT.CaptionToolTipEnabled = True Me.TXT_USER_AGENT.CaptionToolTipText = "Default user agent to use in requests" @@ -404,6 +419,38 @@ Namespace Editors Me.TXT_USER_AGENT.Size = New System.Drawing.Size(562, 22) Me.TXT_USER_AGENT.TabIndex = 6 ' + 'TXT_USER_LIST_IMAGE + ' + ActionButton9.BackgroundImage = CType(resources.GetObject("ActionButton9.BackgroundImage"), System.Drawing.Image) + ActionButton9.Name = "Open" + ActionButton9.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open + ActionButton10.BackgroundImage = CType(resources.GetObject("ActionButton10.BackgroundImage"), System.Drawing.Image) + ActionButton10.Name = "Clear" + ActionButton10.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear + Me.TXT_USER_LIST_IMAGE.Buttons.Add(ActionButton9) + Me.TXT_USER_LIST_IMAGE.Buttons.Add(ActionButton10) + Me.TXT_USER_LIST_IMAGE.CaptionText = "Userlist image" + Me.TXT_USER_LIST_IMAGE.CaptionToolTipEnabled = True + Me.TXT_USER_LIST_IMAGE.CaptionToolTipText = "Background image for user list" + Me.TXT_USER_LIST_IMAGE.Dock = System.Windows.Forms.DockStyle.Fill + Me.TXT_USER_LIST_IMAGE.Location = New System.Drawing.Point(4, 233) + Me.TXT_USER_LIST_IMAGE.Name = "TXT_USER_LIST_IMAGE" + Me.TXT_USER_LIST_IMAGE.Size = New System.Drawing.Size(562, 22) + Me.TXT_USER_LIST_IMAGE.TabIndex = 8 + ' + 'COLORS_USERLIST + ' + Me.COLORS_USERLIST.ButtonsMargin = New System.Windows.Forms.Padding(1, 2, 1, 2) + Me.COLORS_USERLIST.CaptionText = "Userlist colors" + Me.COLORS_USERLIST.CaptionWidth = 103 + Me.COLORS_USERLIST.Dock = System.Windows.Forms.DockStyle.Fill + Me.COLORS_USERLIST.Location = New System.Drawing.Point(1, 259) + Me.COLORS_USERLIST.Margin = New System.Windows.Forms.Padding(0) + Me.COLORS_USERLIST.Name = "COLORS_USERLIST" + Me.COLORS_USERLIST.Padding = New System.Windows.Forms.Padding(0, 0, 2, 0) + Me.COLORS_USERLIST.Size = New System.Drawing.Size(568, 25) + Me.COLORS_USERLIST.TabIndex = 9 + ' 'TP_FILE_NAME ' TP_FILE_NAME.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] @@ -415,13 +462,13 @@ Namespace Editors TP_FILE_NAME.Controls.Add(Me.OPT_FILE_NAME_ADD_DATE, 2, 0) TP_FILE_NAME.Controls.Add(Me.CH_FILE_NAME_CHANGE, 0, 0) TP_FILE_NAME.Dock = System.Windows.Forms.DockStyle.Fill - TP_FILE_NAME.Location = New System.Drawing.Point(1, 27) + TP_FILE_NAME.Location = New System.Drawing.Point(1, 53) TP_FILE_NAME.Margin = New System.Windows.Forms.Padding(0) TP_FILE_NAME.Name = "TP_FILE_NAME" TP_FILE_NAME.RowCount = 1 TP_FILE_NAME.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) TP_FILE_NAME.Size = New System.Drawing.Size(574, 30) - TP_FILE_NAME.TabIndex = 1 + TP_FILE_NAME.TabIndex = 2 ' 'OPT_FILE_NAME_REPLACE ' @@ -473,14 +520,14 @@ Namespace Editors TP_FILE_PATTERNS.Controls.Add(Me.OPT_FILE_DATE_START, 3, 0) TP_FILE_PATTERNS.Controls.Add(Me.OPT_FILE_DATE_END, 4, 0) TP_FILE_PATTERNS.Dock = System.Windows.Forms.DockStyle.Fill - TP_FILE_PATTERNS.Location = New System.Drawing.Point(1, 58) + TP_FILE_PATTERNS.Location = New System.Drawing.Point(1, 84) TP_FILE_PATTERNS.Margin = New System.Windows.Forms.Padding(0) TP_FILE_PATTERNS.Name = "TP_FILE_PATTERNS" TP_FILE_PATTERNS.RowCount = 1 TP_FILE_PATTERNS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) TP_FILE_PATTERNS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 29.0!)) TP_FILE_PATTERNS.Size = New System.Drawing.Size(574, 30) - TP_FILE_PATTERNS.TabIndex = 2 + TP_FILE_PATTERNS.TabIndex = 3 ' 'CH_FILE_DATE ' @@ -701,10 +748,10 @@ Namespace Editors ' Me.CH_FEED_STORE_SESSION_DATA.AutoSize = True Me.CH_FEED_STORE_SESSION_DATA.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_FEED_STORE_SESSION_DATA.Location = New System.Drawing.Point(4, 111) + Me.CH_FEED_STORE_SESSION_DATA.Location = New System.Drawing.Point(4, 166) Me.CH_FEED_STORE_SESSION_DATA.Name = "CH_FEED_STORE_SESSION_DATA" Me.CH_FEED_STORE_SESSION_DATA.Size = New System.Drawing.Size(568, 19) - Me.CH_FEED_STORE_SESSION_DATA.TabIndex = 4 + Me.CH_FEED_STORE_SESSION_DATA.TabIndex = 6 Me.CH_FEED_STORE_SESSION_DATA.Text = "Store session data" TT_MAIN.SetToolTip(Me.CH_FEED_STORE_SESSION_DATA, "If checked, session data will be stored in an xml file.") Me.CH_FEED_STORE_SESSION_DATA.UseVisualStyleBackColor = True @@ -787,15 +834,27 @@ Namespace Editors ' Me.CH_DOWN_REPARSE_MISSING.AutoSize = True Me.CH_DOWN_REPARSE_MISSING.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_DOWN_REPARSE_MISSING.Location = New System.Drawing.Point(4, 176) + Me.CH_DOWN_REPARSE_MISSING.Location = New System.Drawing.Point(4, 202) Me.CH_DOWN_REPARSE_MISSING.Name = "CH_DOWN_REPARSE_MISSING" Me.CH_DOWN_REPARSE_MISSING.Size = New System.Drawing.Size(568, 19) - Me.CH_DOWN_REPARSE_MISSING.TabIndex = 6 + Me.CH_DOWN_REPARSE_MISSING.TabIndex = 7 Me.CH_DOWN_REPARSE_MISSING.Text = "Trying to download missing posts using regular download" TT_MAIN.SetToolTip(Me.CH_DOWN_REPARSE_MISSING, "If missing posts exist, the missing posts will attempt to be downloaded via user " & "download") Me.CH_DOWN_REPARSE_MISSING.UseVisualStyleBackColor = True ' + 'CH_NAME_SITE_FRIENDLY + ' + Me.CH_NAME_SITE_FRIENDLY.AutoSize = True + Me.CH_NAME_SITE_FRIENDLY.Dock = System.Windows.Forms.DockStyle.Fill + Me.CH_NAME_SITE_FRIENDLY.Location = New System.Drawing.Point(4, 134) + Me.CH_NAME_SITE_FRIENDLY.Name = "CH_NAME_SITE_FRIENDLY" + Me.CH_NAME_SITE_FRIENDLY.Size = New System.Drawing.Size(562, 19) + Me.CH_NAME_SITE_FRIENDLY.TabIndex = 5 + Me.CH_NAME_SITE_FRIENDLY.Text = "Use the site name as a friendly name" + TT_MAIN.SetToolTip(Me.CH_NAME_SITE_FRIENDLY, "Use the user's site name as a friendly name") + Me.CH_NAME_SITE_FRIENDLY.UseVisualStyleBackColor = True + ' 'TP_CHANNELS_IMGS ' TP_CHANNELS_IMGS.ColumnCount = 2 @@ -847,7 +906,7 @@ Namespace Editors TAB_BASIS.Location = New System.Drawing.Point(4, 22) TAB_BASIS.Name = "TAB_BASIS" TAB_BASIS.Padding = New System.Windows.Forms.Padding(3) - TAB_BASIS.Size = New System.Drawing.Size(576, 285) + TAB_BASIS.Size = New System.Drawing.Size(576, 343) TAB_BASIS.TabIndex = 0 TAB_BASIS.Text = "Basis" ' @@ -857,7 +916,7 @@ Namespace Editors TAB_DEFAULTS.Location = New System.Drawing.Point(4, 22) TAB_DEFAULTS.Name = "TAB_DEFAULTS" TAB_DEFAULTS.Padding = New System.Windows.Forms.Padding(3) - TAB_DEFAULTS.Size = New System.Drawing.Size(576, 338) + TAB_DEFAULTS.Size = New System.Drawing.Size(576, 486) TAB_DEFAULTS.TabIndex = 1 TAB_DEFAULTS.Text = "Defaults" ' @@ -871,17 +930,19 @@ Namespace Editors TP_DEFS.Controls.Add(Me.CH_DOWN_IMAGES, 0, 2) TP_DEFS.Controls.Add(Me.CH_DEF_TEMP, 0, 1) TP_DEFS.Controls.Add(Me.CH_DOWN_IMAGES_NATIVE, 0, 4) + TP_DEFS.Controls.Add(Me.CH_NAME_SITE_FRIENDLY, 0, 5) TP_DEFS.Dock = System.Windows.Forms.DockStyle.Fill TP_DEFS.Location = New System.Drawing.Point(3, 3) TP_DEFS.Name = "TP_DEFS" - TP_DEFS.RowCount = 6 + TP_DEFS.RowCount = 7 + TP_DEFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_DEFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_DEFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_DEFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_DEFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_DEFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_DEFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_DEFS.Size = New System.Drawing.Size(570, 332) + TP_DEFS.Size = New System.Drawing.Size(570, 480) TP_DEFS.TabIndex = 0 ' 'CH_DOWN_IMAGES_NATIVE @@ -901,7 +962,7 @@ Namespace Editors TAB_DEFS_CHANNELS.Location = New System.Drawing.Point(4, 22) TAB_DEFS_CHANNELS.Name = "TAB_DEFS_CHANNELS" TAB_DEFS_CHANNELS.Padding = New System.Windows.Forms.Padding(3) - TAB_DEFS_CHANNELS.Size = New System.Drawing.Size(576, 338) + TAB_DEFS_CHANNELS.Size = New System.Drawing.Size(576, 486) TAB_DEFS_CHANNELS.TabIndex = 4 TAB_DEFS_CHANNELS.Text = "Channels" ' @@ -925,7 +986,7 @@ Namespace Editors TP_CHANNELS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_CHANNELS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_CHANNELS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_CHANNELS.Size = New System.Drawing.Size(570, 332) + TP_CHANNELS.Size = New System.Drawing.Size(570, 480) TP_CHANNELS.TabIndex = 0 ' 'TXT_CHANNEL_USER_POST_LIMIT @@ -953,7 +1014,7 @@ Namespace Editors TAB_BEHAVIOR.Controls.Add(TP_BEHAVIOR) TAB_BEHAVIOR.Location = New System.Drawing.Point(4, 22) TAB_BEHAVIOR.Name = "TAB_BEHAVIOR" - TAB_BEHAVIOR.Size = New System.Drawing.Size(576, 338) + TAB_BEHAVIOR.Size = New System.Drawing.Size(576, 486) TAB_BEHAVIOR.TabIndex = 5 TAB_BEHAVIOR.Text = "Behavior" ' @@ -984,17 +1045,17 @@ Namespace Editors TP_BEHAVIOR.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) TP_BEHAVIOR.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) TP_BEHAVIOR.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20.0!)) - TP_BEHAVIOR.Size = New System.Drawing.Size(576, 338) + TP_BEHAVIOR.Size = New System.Drawing.Size(576, 486) TP_BEHAVIOR.TabIndex = 0 ' 'TXT_FOLDER_CMD ' Me.TXT_FOLDER_CMD.AutoShowClearButton = True - ActionButton21.BackgroundImage = CType(resources.GetObject("ActionButton21.BackgroundImage"), System.Drawing.Image) - ActionButton21.Enabled = False - ActionButton21.Name = "Clear" - ActionButton21.Visible = False - Me.TXT_FOLDER_CMD.Buttons.Add(ActionButton21) + ActionButton11.BackgroundImage = CType(resources.GetObject("ActionButton11.BackgroundImage"), System.Drawing.Image) + ActionButton11.Enabled = False + ActionButton11.Name = "Clear" + ActionButton11.Visible = False + Me.TXT_FOLDER_CMD.Buttons.Add(ActionButton11) Me.TXT_FOLDER_CMD.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox Me.TXT_FOLDER_CMD.CaptionText = "Folder cmd" Me.TXT_FOLDER_CMD.CaptionToolTipEnabled = True @@ -1033,11 +1094,11 @@ Namespace Editors 'TXT_CLOSE_SCRIPT ' Me.TXT_CLOSE_SCRIPT.AutoShowClearButton = True - ActionButton22.BackgroundImage = CType(resources.GetObject("ActionButton22.BackgroundImage"), System.Drawing.Image) - ActionButton22.Enabled = False - ActionButton22.Name = "Clear" - ActionButton22.Visible = False - Me.TXT_CLOSE_SCRIPT.Buttons.Add(ActionButton22) + ActionButton12.BackgroundImage = CType(resources.GetObject("ActionButton12.BackgroundImage"), System.Drawing.Image) + ActionButton12.Enabled = False + ActionButton12.Name = "Clear" + ActionButton12.Visible = False + Me.TXT_CLOSE_SCRIPT.Buttons.Add(ActionButton12) Me.TXT_CLOSE_SCRIPT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox Me.TXT_CLOSE_SCRIPT.CaptionText = "Close cmd" Me.TXT_CLOSE_SCRIPT.CaptionToolTipEnabled = True @@ -1125,7 +1186,7 @@ Namespace Editors TAB_DOWN.Controls.Add(TP_DOWNLOADING) TAB_DOWN.Location = New System.Drawing.Point(4, 22) TAB_DOWN.Name = "TAB_DOWN" - TAB_DOWN.Size = New System.Drawing.Size(576, 338) + TAB_DOWN.Size = New System.Drawing.Size(576, 486) TAB_DOWN.TabIndex = 6 TAB_DOWN.Text = "Downloading" ' @@ -1134,17 +1195,19 @@ Namespace Editors TP_DOWNLOADING.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] TP_DOWNLOADING.ColumnCount = 1 TP_DOWNLOADING.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_DOWNLOADING.Controls.Add(TP_FILE_NAME, 0, 1) - TP_DOWNLOADING.Controls.Add(TP_FILE_PATTERNS, 0, 2) - TP_DOWNLOADING.Controls.Add(Me.TXT_SCRIPT, 0, 3) + TP_DOWNLOADING.Controls.Add(TP_FILE_NAME, 0, 2) + TP_DOWNLOADING.Controls.Add(TP_FILE_PATTERNS, 0, 3) + TP_DOWNLOADING.Controls.Add(Me.TXT_SCRIPT, 0, 4) TP_DOWNLOADING.Controls.Add(Me.CH_UDESCR_UP, 0, 0) - TP_DOWNLOADING.Controls.Add(Me.TXT_DOWN_COMPLETE_SCRIPT, 0, 4) - TP_DOWNLOADING.Controls.Add(TP_MISSING_DATA, 0, 5) - TP_DOWNLOADING.Controls.Add(Me.CH_DOWN_REPARSE_MISSING, 0, 6) + TP_DOWNLOADING.Controls.Add(Me.TXT_DOWN_COMPLETE_SCRIPT, 0, 5) + TP_DOWNLOADING.Controls.Add(TP_MISSING_DATA, 0, 6) + TP_DOWNLOADING.Controls.Add(Me.CH_DOWN_REPARSE_MISSING, 0, 7) + TP_DOWNLOADING.Controls.Add(Me.CH_UNAME_UP, 0, 1) TP_DOWNLOADING.Dock = System.Windows.Forms.DockStyle.Fill TP_DOWNLOADING.Location = New System.Drawing.Point(0, 0) TP_DOWNLOADING.Name = "TP_DOWNLOADING" - TP_DOWNLOADING.RowCount = 8 + TP_DOWNLOADING.RowCount = 9 + TP_DOWNLOADING.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_DOWNLOADING.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_DOWNLOADING.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30.0!)) TP_DOWNLOADING.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30.0!)) @@ -1153,17 +1216,17 @@ Namespace Editors TP_DOWNLOADING.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_DOWNLOADING.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_DOWNLOADING.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_DOWNLOADING.Size = New System.Drawing.Size(576, 338) - TP_DOWNLOADING.TabIndex = 0 + TP_DOWNLOADING.Size = New System.Drawing.Size(576, 486) + TP_DOWNLOADING.TabIndex = 1 ' 'TXT_SCRIPT ' - ActionButton23.BackgroundImage = CType(resources.GetObject("ActionButton23.BackgroundImage"), System.Drawing.Image) - ActionButton23.Name = "Open" - ActionButton24.BackgroundImage = CType(resources.GetObject("ActionButton24.BackgroundImage"), System.Drawing.Image) - ActionButton24.Name = "Clear" - Me.TXT_SCRIPT.Buttons.Add(ActionButton23) - Me.TXT_SCRIPT.Buttons.Add(ActionButton24) + ActionButton13.BackgroundImage = CType(resources.GetObject("ActionButton13.BackgroundImage"), System.Drawing.Image) + ActionButton13.Name = "Open" + ActionButton14.BackgroundImage = CType(resources.GetObject("ActionButton14.BackgroundImage"), System.Drawing.Image) + ActionButton14.Name = "Clear" + Me.TXT_SCRIPT.Buttons.Add(ActionButton13) + Me.TXT_SCRIPT.Buttons.Add(ActionButton14) Me.TXT_SCRIPT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox Me.TXT_SCRIPT.CaptionText = "Script" Me.TXT_SCRIPT.CaptionToolTipEnabled = True @@ -1171,12 +1234,12 @@ Namespace Editors "sing the script option." Me.TXT_SCRIPT.ChangeControlsEnableOnCheckedChange = False Me.TXT_SCRIPT.Dock = System.Windows.Forms.DockStyle.Fill - Me.TXT_SCRIPT.Location = New System.Drawing.Point(4, 92) + Me.TXT_SCRIPT.Location = New System.Drawing.Point(4, 118) Me.TXT_SCRIPT.Name = "TXT_SCRIPT" Me.TXT_SCRIPT.PlaceholderEnabled = True Me.TXT_SCRIPT.PlaceholderText = "Enter script path here..." Me.TXT_SCRIPT.Size = New System.Drawing.Size(568, 22) - Me.TXT_SCRIPT.TabIndex = 3 + Me.TXT_SCRIPT.TabIndex = 4 ' 'TXT_DOWN_COMPLETE_SCRIPT ' @@ -1186,12 +1249,12 @@ Namespace Editors Me.TXT_DOWN_COMPLETE_SCRIPT.CaptionToolTipText = "This command will be executed after all downloads are completed" Me.TXT_DOWN_COMPLETE_SCRIPT.CaptionWidth = 120.0R Me.TXT_DOWN_COMPLETE_SCRIPT.Dock = System.Windows.Forms.DockStyle.Fill - Me.TXT_DOWN_COMPLETE_SCRIPT.Location = New System.Drawing.Point(4, 121) + Me.TXT_DOWN_COMPLETE_SCRIPT.Location = New System.Drawing.Point(4, 147) Me.TXT_DOWN_COMPLETE_SCRIPT.Name = "TXT_DOWN_COMPLETE_SCRIPT" Me.TXT_DOWN_COMPLETE_SCRIPT.PlaceholderEnabled = True Me.TXT_DOWN_COMPLETE_SCRIPT.PlaceholderText = "Enter command here..." Me.TXT_DOWN_COMPLETE_SCRIPT.Size = New System.Drawing.Size(568, 22) - Me.TXT_DOWN_COMPLETE_SCRIPT.TabIndex = 4 + Me.TXT_DOWN_COMPLETE_SCRIPT.TabIndex = 5 ' 'TP_MISSING_DATA ' @@ -1202,21 +1265,32 @@ Namespace Editors TP_MISSING_DATA.Controls.Add(Me.CH_ADD_MISSING_TO_LOG, 0, 0) TP_MISSING_DATA.Controls.Add(Me.CH_ADD_MISSING_ERROS_TO_LOG, 1, 0) TP_MISSING_DATA.Dock = System.Windows.Forms.DockStyle.Fill - TP_MISSING_DATA.Location = New System.Drawing.Point(1, 147) + TP_MISSING_DATA.Location = New System.Drawing.Point(1, 173) TP_MISSING_DATA.Margin = New System.Windows.Forms.Padding(0) TP_MISSING_DATA.Name = "TP_MISSING_DATA" TP_MISSING_DATA.RowCount = 1 TP_MISSING_DATA.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) TP_MISSING_DATA.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 24.0!)) TP_MISSING_DATA.Size = New System.Drawing.Size(574, 25) - TP_MISSING_DATA.TabIndex = 5 + TP_MISSING_DATA.TabIndex = 6 + ' + 'CH_UNAME_UP + ' + Me.CH_UNAME_UP.AutoSize = True + Me.CH_UNAME_UP.Dock = System.Windows.Forms.DockStyle.Fill + Me.CH_UNAME_UP.Location = New System.Drawing.Point(4, 30) + Me.CH_UNAME_UP.Name = "CH_UNAME_UP" + Me.CH_UNAME_UP.Size = New System.Drawing.Size(568, 19) + Me.CH_UNAME_UP.TabIndex = 7 + Me.CH_UNAME_UP.Text = "Update user site name every time" + Me.CH_UNAME_UP.UseVisualStyleBackColor = True ' 'TAB_FEED ' TAB_FEED.Controls.Add(TP_FEED) TAB_FEED.Location = New System.Drawing.Point(4, 22) TAB_FEED.Name = "TAB_FEED" - TAB_FEED.Size = New System.Drawing.Size(576, 338) + TAB_FEED.Size = New System.Drawing.Size(576, 486) TAB_FEED.TabIndex = 7 TAB_FEED.Text = "Feed" ' @@ -1226,21 +1300,26 @@ Namespace Editors TP_FEED.ColumnCount = 1 TP_FEED.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) TP_FEED.Controls.Add(TP_FEED_IMG_COUNT, 0, 0) - TP_FEED.Controls.Add(Me.CH_FEED_ENDLESS, 0, 1) - TP_FEED.Controls.Add(Me.CH_FEED_ADD_SESSION, 0, 2) - TP_FEED.Controls.Add(Me.CH_FEED_ADD_DATE, 0, 3) - TP_FEED.Controls.Add(Me.CH_FEED_STORE_SESSION_DATA, 0, 4) + TP_FEED.Controls.Add(Me.CH_FEED_ENDLESS, 0, 3) + TP_FEED.Controls.Add(Me.CH_FEED_ADD_SESSION, 0, 4) + TP_FEED.Controls.Add(Me.CH_FEED_ADD_DATE, 0, 5) + TP_FEED.Controls.Add(Me.CH_FEED_STORE_SESSION_DATA, 0, 6) + TP_FEED.Controls.Add(Me.TXT_FEED_CENTER_IMAGE, 0, 1) + TP_FEED.Controls.Add(Me.COLORS_FEED, 0, 2) TP_FEED.Dock = System.Windows.Forms.DockStyle.Fill TP_FEED.Location = New System.Drawing.Point(0, 0) TP_FEED.Name = "TP_FEED" - TP_FEED.RowCount = 6 + TP_FEED.RowCount = 8 + TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) + TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_FEED.Size = New System.Drawing.Size(576, 338) + TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20.0!)) + TP_FEED.Size = New System.Drawing.Size(576, 486) TP_FEED.TabIndex = 0 ' 'TP_FEED_IMG_COUNT @@ -1296,10 +1375,10 @@ Namespace Editors ' Me.CH_FEED_ENDLESS.AutoSize = True Me.CH_FEED_ENDLESS.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_FEED_ENDLESS.Location = New System.Drawing.Point(4, 33) + Me.CH_FEED_ENDLESS.Location = New System.Drawing.Point(4, 88) Me.CH_FEED_ENDLESS.Name = "CH_FEED_ENDLESS" Me.CH_FEED_ENDLESS.Size = New System.Drawing.Size(568, 19) - Me.CH_FEED_ENDLESS.TabIndex = 1 + Me.CH_FEED_ENDLESS.TabIndex = 3 Me.CH_FEED_ENDLESS.Text = "Endless feed" Me.CH_FEED_ENDLESS.UseVisualStyleBackColor = True ' @@ -1307,10 +1386,10 @@ Namespace Editors ' Me.CH_FEED_ADD_SESSION.AutoSize = True Me.CH_FEED_ADD_SESSION.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_FEED_ADD_SESSION.Location = New System.Drawing.Point(4, 59) + Me.CH_FEED_ADD_SESSION.Location = New System.Drawing.Point(4, 114) Me.CH_FEED_ADD_SESSION.Name = "CH_FEED_ADD_SESSION" Me.CH_FEED_ADD_SESSION.Size = New System.Drawing.Size(568, 19) - Me.CH_FEED_ADD_SESSION.TabIndex = 2 + Me.CH_FEED_ADD_SESSION.TabIndex = 4 Me.CH_FEED_ADD_SESSION.Text = "Add the session number to the post title" Me.CH_FEED_ADD_SESSION.UseVisualStyleBackColor = True ' @@ -1318,19 +1397,51 @@ Namespace Editors ' Me.CH_FEED_ADD_DATE.AutoSize = True Me.CH_FEED_ADD_DATE.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_FEED_ADD_DATE.Location = New System.Drawing.Point(4, 85) + Me.CH_FEED_ADD_DATE.Location = New System.Drawing.Point(4, 140) Me.CH_FEED_ADD_DATE.Name = "CH_FEED_ADD_DATE" Me.CH_FEED_ADD_DATE.Size = New System.Drawing.Size(568, 19) - Me.CH_FEED_ADD_DATE.TabIndex = 3 + Me.CH_FEED_ADD_DATE.TabIndex = 5 Me.CH_FEED_ADD_DATE.Text = "Add the date to the post title" Me.CH_FEED_ADD_DATE.UseVisualStyleBackColor = True ' + 'TXT_FEED_CENTER_IMAGE + ' + Me.TXT_FEED_CENTER_IMAGE.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox + Me.TXT_FEED_CENTER_IMAGE.CaptionSizeType = System.Windows.Forms.SizeType.Percent + Me.TXT_FEED_CENTER_IMAGE.CaptionText = "Center images in grid (number of visible images)" + Me.TXT_FEED_CENTER_IMAGE.CaptionToolTipEnabled = True + Me.TXT_FEED_CENTER_IMAGE.CaptionToolTipText = "Don't fit images to the grid, but center them and set the number of visible image" & + "s." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Only works when the number of columns is 1." + Me.TXT_FEED_CENTER_IMAGE.CaptionWidth = 50.0R + Me.TXT_FEED_CENTER_IMAGE.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown + Me.TXT_FEED_CENTER_IMAGE.Dock = System.Windows.Forms.DockStyle.Fill + Me.TXT_FEED_CENTER_IMAGE.Location = New System.Drawing.Point(4, 33) + Me.TXT_FEED_CENTER_IMAGE.Margin = New System.Windows.Forms.Padding(3, 3, 2, 3) + Me.TXT_FEED_CENTER_IMAGE.Name = "TXT_FEED_CENTER_IMAGE" + Me.TXT_FEED_CENTER_IMAGE.NumberMaximum = New Decimal(New Integer() {50, 0, 0, 0}) + Me.TXT_FEED_CENTER_IMAGE.NumberMinimum = New Decimal(New Integer() {1, 0, 0, 0}) + Me.TXT_FEED_CENTER_IMAGE.Size = New System.Drawing.Size(569, 22) + Me.TXT_FEED_CENTER_IMAGE.TabIndex = 1 + Me.TXT_FEED_CENTER_IMAGE.Text = "1" + Me.TXT_FEED_CENTER_IMAGE.TextBoxTextAlign = System.Windows.Forms.HorizontalAlignment.Center + ' + 'COLORS_FEED + ' + Me.COLORS_FEED.ButtonsMargin = New System.Windows.Forms.Padding(1, 2, 1, 2) + Me.COLORS_FEED.CaptionText = "Feed colors" + Me.COLORS_FEED.Dock = System.Windows.Forms.DockStyle.Fill + Me.COLORS_FEED.Location = New System.Drawing.Point(1, 59) + Me.COLORS_FEED.Margin = New System.Windows.Forms.Padding(0) + Me.COLORS_FEED.Name = "COLORS_FEED" + Me.COLORS_FEED.Size = New System.Drawing.Size(574, 25) + Me.COLORS_FEED.TabIndex = 2 + ' 'TAB_NOTIFY ' TAB_NOTIFY.Controls.Add(TP_NOTIFY_MAIN) TAB_NOTIFY.Location = New System.Drawing.Point(4, 22) TAB_NOTIFY.Name = "TAB_NOTIFY" - TAB_NOTIFY.Size = New System.Drawing.Size(576, 338) + TAB_NOTIFY.Size = New System.Drawing.Size(576, 486) TAB_NOTIFY.TabIndex = 8 TAB_NOTIFY.Text = "Notifications" ' @@ -1357,7 +1468,7 @@ Namespace Editors TP_NOTIFY_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_NOTIFY_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_NOTIFY_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_NOTIFY_MAIN.Size = New System.Drawing.Size(576, 338) + TP_NOTIFY_MAIN.Size = New System.Drawing.Size(576, 486) TP_NOTIFY_MAIN.TabIndex = 0 ' 'TAB_MAIN @@ -1373,7 +1484,7 @@ Namespace Editors Me.TAB_MAIN.Location = New System.Drawing.Point(0, 0) Me.TAB_MAIN.Name = "TAB_MAIN" Me.TAB_MAIN.SelectedIndex = 0 - Me.TAB_MAIN.Size = New System.Drawing.Size(584, 311) + Me.TAB_MAIN.Size = New System.Drawing.Size(584, 369) Me.TAB_MAIN.TabIndex = 1 ' 'CONTAINER_MAIN @@ -1382,13 +1493,13 @@ Namespace Editors 'CONTAINER_MAIN.ContentPanel ' Me.CONTAINER_MAIN.ContentPanel.Controls.Add(Me.TAB_MAIN) - Me.CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(584, 311) + Me.CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(584, 369) Me.CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill Me.CONTAINER_MAIN.LeftToolStripPanelVisible = False Me.CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0) Me.CONTAINER_MAIN.Name = "CONTAINER_MAIN" Me.CONTAINER_MAIN.RightToolStripPanelVisible = False - Me.CONTAINER_MAIN.Size = New System.Drawing.Size(584, 336) + Me.CONTAINER_MAIN.Size = New System.Drawing.Size(584, 394) Me.CONTAINER_MAIN.TabIndex = 0 Me.CONTAINER_MAIN.TopToolStripPanelVisible = False ' @@ -1396,15 +1507,15 @@ Namespace Editors ' Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font - Me.ClientSize = New System.Drawing.Size(584, 336) + Me.ClientSize = New System.Drawing.Size(584, 394) Me.Controls.Add(Me.CONTAINER_MAIN) Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle Me.Icon = Global.SCrawler.My.Resources.Resources.SettingsIcon_48 Me.KeyPreview = True Me.MaximizeBox = False - Me.MaximumSize = New System.Drawing.Size(600, 375) + Me.MaximumSize = New System.Drawing.Size(600, 433) Me.MinimizeBox = False - Me.MinimumSize = New System.Drawing.Size(600, 375) + Me.MinimumSize = New System.Drawing.Size(600, 433) Me.Name = "GlobalSettingsForm" Me.ShowInTaskbar = False Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide @@ -1420,6 +1531,7 @@ Namespace Editors CType(Me.TXT_MAX_JOBS_CHANNELS, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_IMGUR_CLIENT_ID, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_USER_AGENT, System.ComponentModel.ISupportInitialize).EndInit() + CType(Me.TXT_USER_LIST_IMAGE, System.ComponentModel.ISupportInitialize).EndInit() TP_FILE_NAME.ResumeLayout(False) TP_FILE_NAME.PerformLayout() TP_FILE_PATTERNS.ResumeLayout(False) @@ -1457,6 +1569,7 @@ Namespace Editors TP_FEED_IMG_COUNT.ResumeLayout(False) CType(Me.TXT_FEED_ROWS, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_FEED_COLUMNS, System.ComponentModel.ISupportInitialize).EndInit() + CType(Me.TXT_FEED_CENTER_IMAGE, System.ComponentModel.ISupportInitialize).EndInit() TAB_NOTIFY.ResumeLayout(False) TP_NOTIFY_MAIN.ResumeLayout(False) TP_NOTIFY_MAIN.PerformLayout() @@ -1526,5 +1639,11 @@ Namespace Editors Private WithEvents CH_NOTIFY_CHANNELS As CheckBox Private WithEvents CH_DOWN_REPARSE_MISSING As CheckBox Private WithEvents TXT_USER_AGENT As PersonalUtilities.Forms.Controls.TextBoxExtended + Private WithEvents TXT_USER_LIST_IMAGE As PersonalUtilities.Forms.Controls.TextBoxExtended + Private WithEvents TXT_FEED_CENTER_IMAGE As PersonalUtilities.Forms.Controls.TextBoxExtended + Private WithEvents CH_NAME_SITE_FRIENDLY As CheckBox + Private WithEvents CH_UNAME_UP As CheckBox + Private WithEvents COLORS_USERLIST As ColorPicker + Private WithEvents COLORS_FEED As ColorPicker End Class End Namespace \ No newline at end of file diff --git a/SCrawler/Editors/GlobalSettingsForm.resx b/SCrawler/Editors/GlobalSettingsForm.resx index 99f7914..2220944 100644 --- a/SCrawler/Editors/GlobalSettingsForm.resx +++ b/SCrawler/Editors/GlobalSettingsForm.resx @@ -121,7 +121,7 @@ False - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP @@ -132,7 +132,7 @@ cMaRN0UdBBkAAAAASUVORK5CYII= - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go @@ -143,7 +143,7 @@ False - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go @@ -151,7 +151,7 @@ AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE @@ -167,7 +167,7 @@ VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg== - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE @@ -183,7 +183,7 @@ VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg== - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go @@ -197,7 +197,7 @@ 17, 17 - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE @@ -213,7 +213,26 @@ VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg== - + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go + tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX + AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP + WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP + aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+ + 5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8 + vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB + cMaRN0UdBBkAAAAASUVORK5CYII= + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go @@ -230,15 +249,6 @@ False - - False - - - False - - - 17, 17 - This is a global setting for newly added users only. This parameter specifies how the video will be stored in the users' download path. @@ -266,34 +276,19 @@ You can find more detailed information about the missing posts in the form that False - - False - False False - - False - False False - - False - - - False - - - False - - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go @@ -301,7 +296,7 @@ You can find more detailed information about the missing posts in the form that AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go @@ -321,13 +316,7 @@ You can find more detailed information about the missing posts in the form that False - - False - - - False - - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP @@ -338,7 +327,7 @@ You can find more detailed information about the missing posts in the form that cMaRN0UdBBkAAAAASUVORK5CYII= - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go @@ -355,12 +344,6 @@ You can find more detailed information about the missing posts in the form that False - - False - - - False - False @@ -370,7 +353,4 @@ You can find more detailed information about the missing posts in the form that False - - False - \ No newline at end of file diff --git a/SCrawler/Editors/GlobalSettingsForm.vb b/SCrawler/Editors/GlobalSettingsForm.vb index 52edccf..861a762 100644 --- a/SCrawler/Editors/GlobalSettingsForm.vb +++ b/SCrawler/Editors/GlobalSettingsForm.vb @@ -33,6 +33,8 @@ Namespace Editors CH_CHECK_VER_START.Checked = .CheckUpdatesAtStart TXT_USER_AGENT.Text = .UserAgent TXT_IMGUR_CLIENT_ID.Text = .ImgurClientID + TXT_USER_LIST_IMAGE.Text = .UserListImage.Value + COLORS_USERLIST.ColorsSet(.UserListBackColor, .UserListForeColor, SystemColors.Window, SystemColors.WindowText) CH_SHOW_GROUPS.Checked = .ShowGroups CH_USERS_GROUPING.Checked = .UseGrouping 'Behavior @@ -61,8 +63,10 @@ Namespace Editors CH_DOWN_IMAGES.Checked = .DefaultDownloadImages CH_DOWN_VIDEOS.Checked = .DefaultDownloadVideos CH_DOWN_IMAGES_NATIVE.Checked = .DownloadNativeImageFormat + CH_NAME_SITE_FRIENDLY.Checked = .UserSiteNameAsFriendly 'Downloading CH_UDESCR_UP.Checked = .UpdateUserDescriptionEveryTime + CH_UNAME_UP.Checked = .UserSiteNameUpdateEveryTime TXT_SCRIPT.Checked = .ScriptData.Attribute TXT_SCRIPT.Text = .ScriptData.Value TXT_DOWN_COMPLETE_SCRIPT.Text = .DownloadsCompleteCommand @@ -90,6 +94,10 @@ Namespace Editors 'Feed TXT_FEED_ROWS.Value = .FeedDataRows.Value TXT_FEED_COLUMNS.Value = .FeedDataColumns.Value + TXT_FEED_CENTER_IMAGE.Checked = .FeedCenterImage.Use + TXT_FEED_CENTER_IMAGE.Value = .FeedCenterImage.Value + TXT_FEED_CENTER_IMAGE.Enabled = .FeedDataColumns = 1 + COLORS_FEED.ColorsSet(.FeedBackColor, .FeedForeColor, SystemColors.Window, SystemColors.WindowText) CH_FEED_ENDLESS.Checked = .FeedEndless CH_FEED_ADD_SESSION.Checked = .FeedAddSessionToCaption CH_FEED_ADD_DATE.Checked = .FeedAddDateToCaption @@ -151,6 +159,8 @@ Namespace Editors .UserAgent.Value = TXT_USER_AGENT.Text DefaultUserAgent = TXT_USER_AGENT.Text .ImgurClientID.Value = TXT_IMGUR_CLIENT_ID.Text + .UserListImage.Value = TXT_USER_LIST_IMAGE.Text + COLORS_USERLIST.ColorsGet(.UserListBackColor, .UserListForeColor) .ShowGroups.Value = CH_SHOW_GROUPS.Checked .UseGrouping.Value = CH_USERS_GROUPING.Checked 'Behavior @@ -179,8 +189,10 @@ Namespace Editors .DefaultDownloadImages.Value = CH_DOWN_IMAGES.Checked .DefaultDownloadVideos.Value = CH_DOWN_VIDEOS.Checked .DownloadNativeImageFormat.Value = CH_DOWN_IMAGES_NATIVE.Checked + .UserSiteNameAsFriendly.Value = CH_NAME_SITE_FRIENDLY.Checked 'Downloading .UpdateUserDescriptionEveryTime.Value = CH_UDESCR_UP.Checked + .UserSiteNameUpdateEveryTime.Value = CH_UNAME_UP.Checked .ScriptData.Value = TXT_SCRIPT.Text .ScriptData.Attribute.Value = TXT_SCRIPT.Checked .DownloadsCompleteCommand.Value = TXT_DOWN_COMPLETE_SCRIPT.Text @@ -202,6 +214,8 @@ Namespace Editors 'Channels .ChannelsImagesRows.Value = CInt(TXT_CHANNELS_ROWS.Value) .ChannelsImagesColumns.Value = CInt(TXT_CHANNELS_COLUMNS.Value) + .FeedCenterImage.Use = TXT_FEED_CENTER_IMAGE.Checked + .FeedCenterImage.Value = TXT_FEED_CENTER_IMAGE.Value .FromChannelDownloadTop.Value = CInt(TXT_CHANNEL_USER_POST_LIMIT.Value) .FromChannelDownloadTopUse.Value = TXT_CHANNEL_USER_POST_LIMIT.Checked .FromChannelCopyImageToUser.Value = CH_COPY_CHANNEL_USER_IMAGE.Checked @@ -210,12 +224,15 @@ Namespace Editors 'Feed .FeedDataRows.Value = CInt(TXT_FEED_ROWS.Value) .FeedDataColumns.Value = CInt(TXT_FEED_COLUMNS.Value) + COLORS_FEED.ColorsGet(.FeedBackColor, .FeedForeColor) .FeedEndless.Value = CH_FEED_ENDLESS.Checked .FeedAddSessionToCaption.Value = CH_FEED_ADD_SESSION.Checked .FeedAddDateToCaption.Value = CH_FEED_ADD_DATE.Checked .FeedStoreSessionsData.Value = CH_FEED_STORE_SESSION_DATA.Checked FeedParametersChanged = .FeedDataRows.ChangesDetected Or .FeedDataColumns.ChangesDetected Or - .FeedEndless.ChangesDetected Or .FeedStoreSessionsData.ChangesDetected + .FeedEndless.ChangesDetected Or .FeedStoreSessionsData.ChangesDetected Or + .FeedBackColor.ChangesDetected Or .FeedForeColor.ChangesDetected Or + .FeedCenterImage.ChangesDetected .EndUpdate() End With @@ -264,5 +281,14 @@ Namespace Editors CH_NOTIFY_CHANNELS.Enabled = b CH_NOTIFY_SAVED_POSTS.Enabled = b End Sub + Private Sub TXT_USER_LIST_IMAGE_ActionOnButtonClick(ByVal Sender As ActionButton, e As ActionButtonEventArgs) Handles TXT_USER_LIST_IMAGE.ActionOnButtonClick + If Sender.DefaultButton = ADB.Open Then + Dim f As SFile = SFile.SelectFiles(TXT_USER_LIST_IMAGE.Text, False, "Select a new image for the user list:", "Pictures|*.jpg;*.jpeg;*.png").FirstOrDefault + If Not f.IsEmptyString Then TXT_USER_LIST_IMAGE.Text = f + End If + End Sub + Private Sub TXT_FEED_COLUMNS_ActionOnValueChanged(sender As Object, e As EventArgs) Handles TXT_FEED_COLUMNS.ActionOnValueChanged + TXT_FEED_CENTER_IMAGE.Enabled = TXT_FEED_COLUMNS.Value = 1 + End Sub End Class End Namespace \ No newline at end of file diff --git a/SCrawler/Editors/UserCreatorForm.vb b/SCrawler/Editors/UserCreatorForm.vb index ae0d63a..e224e5d 100644 --- a/SCrawler/Editors/UserCreatorForm.vb +++ b/SCrawler/Editors/UserCreatorForm.vb @@ -80,6 +80,8 @@ Namespace Editors Return TXT_SCRIPT.Text End Get End Property + Private FriendlyNameIsSiteName As Boolean = False + Private FriendlyNameChanged As Boolean = False #End Region #Region "Exchange, Path, Labels" Friend Property MyExchangeOptions As Object = Nothing @@ -248,7 +250,18 @@ Namespace Editors TXT_SPEC_FOLDER.Buttons.Clear() TXT_SPEC_FOLDER.Buttons.UpdateButtonsPositions() With UserInstance + If .HOST.Key = PathPlugin.PluginKey Then TXT_SPEC_FOLDER.Enabled = False TXT_USER_FRIENDLY.Text = .FriendlyName + FriendlyNameIsSiteName = DirectCast(.Self, UserDataBase).FriendlyNameIsSiteName + If FriendlyNameIsSiteName Then + With TXT_USER_FRIENDLY + .ControlChangeColor(True, False) + .Buttons.AddRange({New ActionButton With {.Text = "F", .ToolTipText = "Name set by you"}, + New ActionButton With {.Text = "S", .ToolTipText = "Name from site"}, + New ActionButton(ADB.Clear)}) + .ClearTextByButtonClear = False + End With + End If CH_FAV.Checked = .Favorite CH_TEMP.Checked = .Temporary CH_PARSE_USER_MEDIA.Checked = .ParseUserMediaOnly @@ -275,6 +288,7 @@ Namespace Editors .MyFieldsChecker.EndLoaderOperations() .EndLoaderOperations() End With + FriendlyNameChanged = False Catch ex As Exception MyDef.InvokeLoaderError(ex) End Try @@ -336,7 +350,19 @@ Namespace Editors If Not UserInstance Is Nothing Then With DirectCast(UserInstance, UserDataBase) .User = User - .FriendlyName = TXT_USER_FRIENDLY.Text + Dim setFriendly As Boolean = True + If FriendlyNameIsSiteName Then + If Not FriendlyNameChanged Then + setFriendly = False + Else + setFriendly = MsgBoxE({"Are you sure you want to set the site name as the friendly name?" & vbCr & + $"Friendly name: { .FriendlyNameOrig}" & vbCr & + $"Site name: { .UserSiteName}" & vbCr & + $"Your choice: {TXT_USER_FRIENDLY.Text}", "Friendly name change"}, vbExclamation,,, + {"Confirm", New Messaging.MsgBoxButton("Decline", "Friendly name will not be changed")}) = 0 + End If + End If + If setFriendly Then .FriendlyName = TXT_USER_FRIENDLY.Text .Favorite = CH_FAV.Checked .Temporary = CH_TEMP.Checked .ReadyForDownload = CH_READY_FOR_DOWN.Checked @@ -346,7 +372,7 @@ Namespace Editors 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) + With DirectCast(UserInstance, UserDataBind) If .Count > 0 Then .Collections.ForEach(Sub(c) c.Labels.ListAddList(UserLabels, l)) End With Else @@ -387,6 +413,10 @@ CloseForm: If Not s.UserName.IsEmptyString Then Dim i% = Settings.Plugins.FindIndex(Function(p) p.Key = s.HostKey) If i >= 0 Then + If s.HostKey = PathPlugin.PluginKey Then + TXT_SPEC_FOLDER.Text = s.UserName + s.UserName = s.UserName.CSFileP.Segments.LastOrDefault + End If CMB_SITE.SelectedIndex = i CH_IS_CHANNEL.Checked = s.IsChannel TXT_USER.Text = s.UserName @@ -408,6 +438,30 @@ CloseForm: 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 TXT_USER_FRIENDLY_ActionOnTextChanged(sender As Object, e As EventArgs) Handles TXT_USER_FRIENDLY.ActionOnTextChanged + If Not MyDef.Initializing Then FriendlyNameChanged = True + End Sub + Private Sub TXT_USER_FRIENDLY_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_USER_FRIENDLY.ActionOnButtonClick + If Sender.DefaultButton = ADB.Clear Then + TXT_USER_FRIENDLY.Clear() + FriendlyNameIsSiteName = False + FriendlyNameChanged = False + TXT_USER_FRIENDLY.ControlChangeColor(SystemColors.Window, SystemColors.WindowText) + Else + Select Case Sender.Text + Case "F" + TXT_USER_FRIENDLY.Text = DirectCast(UserInstance, UserDataBase).FriendlyNameOrig + FriendlyNameIsSiteName = False + FriendlyNameChanged = False + TXT_USER_FRIENDLY.ControlChangeColor(SystemColors.Window, SystemColors.WindowText) + Case "S" + TXT_USER_FRIENDLY.Text = DirectCast(UserInstance, UserDataBase).UserSiteName + FriendlyNameIsSiteName = True + FriendlyNameChanged = False + TXT_USER_FRIENDLY.ControlChangeColor(True, False) + End Select + End If + 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 diff --git a/SCrawler/ListImagesLoader.vb b/SCrawler/ListImagesLoader.vb index 53a5cef..cef565a 100644 --- a/SCrawler/ListImagesLoader.vb +++ b/SCrawler/ListImagesLoader.vb @@ -139,6 +139,8 @@ Friend Class ListImagesLoader End If End With MyList.EndUpdate() + Else + UpdateInProgress = False End If Else MsgBoxE({"User list update aborted. Click the 'Refresh' button to refresh the user list.", "Update user list"}, vbExclamation) @@ -195,9 +197,9 @@ Friend Class ListImagesLoader ElseIf CheckUserCollection(User) Then .BackColor = Color.LightSkyBlue .ForeColor = Color.MidnightBlue - ElseIf Not IsInit Then - .BackColor = SystemColors.Window - .ForeColor = SystemColors.WindowText + Else 'If Not IsInit Then + .BackColor = Settings.UserListBackColorF + .ForeColor = Settings.UserListForeColorF End If End With Return LVI diff --git a/SCrawler/MainFrame.vb b/SCrawler/MainFrame.vb index bca82a2..3580c5e 100644 --- a/SCrawler/MainFrame.vb +++ b/SCrawler/MainFrame.vb @@ -10,6 +10,7 @@ Imports System.Threading Imports System.ComponentModel Imports PersonalUtilities.Forms Imports PersonalUtilities.Functions.Messaging +Imports PersonalUtilities.Tools Imports SCrawler.API Imports SCrawler.API.Base Imports SCrawler.Editors @@ -36,7 +37,8 @@ Public Class MainFrame With Settings.Plugins If .Count > 0 Then For i% = 0 To .Count - 1 - MENU_SETTINGS.DropDownItems.Insert(MENU_SETTINGS.DropDownItems.Count - 2, .Item(i).Settings.GetSettingsButton) + If Not .Item(i).Key = PathPlugin.PluginKey Then _ + MENU_SETTINGS.DropDownItems.Insert(MENU_SETTINGS.DropDownItems.Count - 2, .Item(i).Settings.GetSettingsButton) Next End If End With @@ -88,6 +90,7 @@ Public Class MainFrame LIST_PROFILES.ShowGroups = .UseGrouping ApplyViewPattern(.ViewMode.Value) AddHandler .Labels.NewLabelAdded, AddressOf UpdateLabelsGroups + UpdateImageColor() UserListLoader = New ListImagesLoader(LIST_PROFILES) RefillList() UpdateLabelsGroups() @@ -116,6 +119,7 @@ Public Class MainFrame Await .Automation.Start(True) End With UpdatePauseButtonsVisibility() + MainFrameObj.UpdateLogButton() GoTo EndFunction FormClosingInvoker: Close() @@ -190,6 +194,25 @@ CloseResume: If Not _DisableClosingScript And Not _VideoDownloadingMode Then ExecuteCommand(Settings.ClosingCommand) If Not MyMainLOG.IsEmptyString Then SaveLogToFile() End Sub + Private Sub MainFrame_ResizeEnd(sender As Object, e As EventArgs) Handles Me.ResizeEnd + If Not _UFinit Then UpdateImageColor() + End Sub + Private Sub UpdateImageColor() + Try + If Settings.UserListImage.Value.Exists Then + Using ir As New ImageRenderer(Settings.UserListImage) : LIST_PROFILES.BackgroundImage = ir.FitToWidth(LIST_PROFILES.Width) : End Using + Else + LIST_PROFILES.BackgroundImage = Nothing + End If + With Settings + If Not .UserListBackColorF = LIST_PROFILES.BackColor Or Not .UserListForeColorF = LIST_PROFILES.ForeColor Then + LIST_PROFILES.BackColor = .UserListBackColorF + LIST_PROFILES.ForeColor = .UserListForeColorF + End If + End With + Catch ex As Exception + End Try + End Sub Private Sub MainFrame_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown Dim b As Boolean = True Select Case e.KeyCode @@ -272,6 +295,7 @@ CloseResume: LIST_PROFILES.ShowGroups = .UseGrouping If f.FeedParametersChanged And Not MyFeed Is Nothing Then MyFeed.UpdateSettings() UpdateSilentButtons() + UpdateImageColor() End If End Using End With @@ -339,8 +363,11 @@ CloseResume: .ScriptUse = f.ScriptUse .ScriptData = f.ScriptData If Not f.MyExchangeOptions Is Nothing Then DirectCast(.Self, UserDataBase).ExchangeOptionsSet(f.MyExchangeOptions) - Settings.Labels.Add(LabelsKeeper.NoParsedUser) - .Self.Labels.ListAddList(f.UserLabels.ListAddValue(LabelsKeeper.NoParsedUser), LAP.ClearBeforeAdd, LAP.NotContainsOnly) + If Not .HOST.Key = PathPlugin.PluginKey Then + Settings.Labels.Add(LabelsKeeper.NoParsedUser) + f.UserLabels.ListAddValue(LabelsKeeper.NoParsedUser) + End If + .Self.Labels.ListAddList(f.UserLabels, LAP.ClearBeforeAdd, LAP.NotContainsOnly) .UpdateUserInformation() End If End With @@ -882,6 +909,23 @@ CloseResume: Else __ModelAskForDecision = True End If + + If (users.Count = 1 AndAlso Not users(0).IsCollection AndAlso users(0).HOST.Key = PathPlugin.PluginKey) OrElse + (users.Count = 2 AndAlso users.All(Function(u) u.IsCollection OrElse u.HOST.Key = PathPlugin.PluginKey)) Then + __modelUser = UsageModel.Virtual + If Added Then + __modelCollection = UsageModel.Virtual + Else + i = users.FindIndex(_col_user) + If i >= 0 Then + __modelCollection = users(i).CollectionModel + Else + __modelCollection = UsageModel.Virtual + End If + End If + __ModelAskForDecision = False + End If + If __ModelAskForDecision Then Select Case MsgBoxE({"How do you want to add users to the collection?", MsgTitle}, vbQuestion,,, { @@ -909,7 +953,7 @@ CloseResume: For Each user As UserDataBase In users If Not user.IsCollection Then Try - user.User.UserModel = __modelUser + user.User.UserModel = IIf(user.HOST.Key = PathPlugin.PluginKey, UsageModel.Virtual, __modelUser) user.User.CollectionModel = __modelCollection userCollection.Add(user) RemoveUserFromList(user) @@ -1006,10 +1050,10 @@ CloseResume: 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) + colName = CurrDir.Segments.LastOrDefault + Dim vu As IEnumerable(Of IUserData) = .Where(Function(vuu) vuu.UserModel = UsageModel.Virtual Or vuu.HOST.Key = PathPlugin.PluginKey) If vu.ListExists Then - If MsgBoxE({"This collection contains virtual users." & vbCr & + If MsgBoxE({"This collection contains virtual users and/or paths." & 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}, @@ -1017,17 +1061,29 @@ CloseResume: End If End If End With + ElseIf .HOST.Key = PathPlugin.PluginKey Then + MsgBoxE({"This is the path (not user). The paths cannot be changed.", MsgTitle}, vbCritical) + Exit Sub Else CurrDir = .Self.File.CutPath(1) End If Dim NewDest As SFile = SFile.SelectPath(CurrDir, $"Select a new destination for {IIf(_IsCollection, "collection", "user")} [{ .Self}]") + Dim NewDest2 As SFile 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 + NewDest2 = $"{NewDest.PathWithSeparator}{CurrDir.Segments.LastOrDefault().StringAppend("\", String.Empty)}" + Dim choice% = MsgBoxE(New MMessage($"You are changing the user's [{ .Self}] destination" & vbCr & + $"Current destination: {CurrDir.PathNoSeparator}" & vbCr & + $"New destination [1]: {NewDest.PathNoSeparator}" & vbCr & + $"New destination [2]: {NewDest2.PathWithSeparator}", + MsgTitle, + {New MsgBoxButton("Confirm [1] (Enter)", "Move the data to the destination [1]."), + New MsgBoxButton("Confirm [2]", "Move the data to the destination [2].") With {.KeyCode = Keys.D2}, + "Cancel"}, + MsgBoxStyle.Exclamation) With {.AppendKeyCode = False}) + If choice < 2 Then + If choice = 1 Then NewDest = NewDest2 If Not NewDest.IsEmptyString AndAlso (Not NewDest.Exists(SFO.Path, False) OrElse ( diff --git a/SCrawler/MainMod.vb b/SCrawler/MainMod.vb index 40b2587..9502652 100644 --- a/SCrawler/MainMod.vb +++ b/SCrawler/MainMod.vb @@ -104,7 +104,7 @@ Friend Module MainMod Friend UserListLoader As ListImagesLoader Friend MyProgressForm As ActiveDownloadingProgress Friend MainFrameObj As MainFrameObjects - Friend ReadOnly ParsersDataDateProvider As New ADateTime(ADateTime.Formats.BaseDateTime) + Friend ReadOnly DateTimeDefaultProvider As New ADateTime(ADateTime.Formats.BaseDateTime) Friend ReadOnly FeedVideoLengthProvider As New ADateTime("hh\:mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan} Friend ReadOnly UserExistsPredicate As New FPredicate(Of IUserData)(Function(u) u.Exists) Friend ReadOnly LogConnector As New LogHost diff --git a/SCrawler/My Project/AssemblyInfo.vb b/SCrawler/My Project/AssemblyInfo.vb index 4a27b16..9ecdba6 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 f6f08d5..ea05cb6 100644 --- a/SCrawler/PluginsEnvironment/Hosts/PluginHost.vb +++ b/SCrawler/PluginsEnvironment/Hosts/PluginHost.vb @@ -83,7 +83,8 @@ Namespace Plugin.Hosts 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)} + New PluginHost(New API.XVIDEOS.SiteSettings, _XML, GlobalPath, _Temp, _Imgs, _Vids), + New PluginHost(New API.PathPlugin.SiteSettings, _XML, GlobalPath, _Temp, _Imgs, _Vids)} End Function Friend Shared Function GetPluginsHosts(ByRef _XML As XmlFile, ByVal GlobalPath As SFile, ByRef _Temp As XMLValue(Of Boolean), ByRef _Imgs As XMLValue(Of Boolean), diff --git a/SCrawler/SCrawler.vbproj b/SCrawler/SCrawler.vbproj index f0fe311..73a7be6 100644 --- a/SCrawler/SCrawler.vbproj +++ b/SCrawler/SCrawler.vbproj @@ -175,6 +175,9 @@ + + + @@ -270,6 +273,12 @@ Form + + ColorPicker.vb + + + UserControl + @@ -465,6 +474,9 @@ CollectionEditorForm.vb + + ColorPicker.vb + GlobalSettingsForm.vb diff --git a/SCrawler/SettingsCLS.vb b/SCrawler/SettingsCLS.vb index 3244e2c..cd3e7a9 100644 --- a/SCrawler/SettingsCLS.vb +++ b/SCrawler/SettingsCLS.vb @@ -116,6 +116,8 @@ Friend Class SettingsCLS : Implements IDisposable ChangeReadyForDownOnTempChange = New XMLValue(Of Boolean)("ChangeReadyForDownOnTempChange", True, MyXML, n) DownloadNativeImageFormat = New XMLValue(Of Boolean)("DownloadNativeImageFormat", True, MyXML, n) ReparseMissingInTheRoutine = New XMLValue(Of Boolean)("ReparseMissingInTheRoutine", False, MyXML, n) + UserSiteNameAsFriendly = New XMLValue(Of Boolean)("UserSiteNameAsFriendly", False, MyXML, n) + UserSiteNameUpdateEveryTime = New XMLValue(Of Boolean)("UserSiteNameUpdateEveryTime", False, MyXML, n) Plugins.AddRange(PluginHost.GetMyHosts(MyXML, GlobalPath.Value, DefaultTemporary, DefaultDownloadImages, DefaultDownloadVideos)) Dim tmpPluginList As IEnumerable(Of PluginHost) = PluginHost.GetPluginsHosts(MyXML, GlobalPath.Value, DefaultTemporary, @@ -126,6 +128,11 @@ Friend Class SettingsCLS : Implements IDisposable FastProfilesLoading = New XMLValue(Of Boolean)("FastProfilesLoading", True, MyXML) MaxLargeImageHeight = New XMLValue(Of Integer)("MaxLargeImageHeight", 150, MyXML) MaxSmallImageHeight = New XMLValue(Of Integer)("MaxSmallImageHeight", 15, MyXML) + UserListBackColor = New XMLValue(Of Color) + UserListBackColor.SetExtended("UserListBackColor",, MyXML) + UserListForeColor = New XMLValue(Of Color) + UserListForeColor.SetExtended("UserListForeColor",, MyXML) + UserListImage = New XMLValue(Of SFile)("UserListImage",, MyXML) DownloadOpenInfo = New XMLValueAttribute(Of Boolean, Boolean)("DownloadOpenInfo", "OpenAgain", False, False, MyXML) DownloadOpenProgress = New XMLValueAttribute(Of Boolean, Boolean)("DownloadOpenProgress", "OpenAgain", False, False, MyXML) DownloadsCompleteCommand = New XMLValueAttribute(Of String, Boolean)("DownloadsCompleteCommand", "Use",,, MyXML) @@ -169,10 +176,15 @@ Friend Class SettingsCLS : Implements IDisposable n = {"Feed"} FeedDataColumns = New XMLValue(Of Integer)("DataColumns", 1, MyXML, n) FeedDataRows = New XMLValue(Of Integer)("DataRows", 10, MyXML, n) + FeedCenterImage = New XMLValueUse(Of Integer)("FeedCenterImage", 1,, MyXML, n) FeedEndless = New XMLValue(Of Boolean)("Endless", True, MyXML, n) FeedAddDateToCaption = New XMLValue(Of Boolean)("AddDateToCaption", True, MyXML, n) FeedAddSessionToCaption = New XMLValue(Of Boolean)("AddSessionToCaption", False, MyXML, n) FeedStoreSessionsData = New XMLValue(Of Boolean)("StoreSessionsData", True, MyXML, n) + FeedBackColor = New XMLValue(Of Color) + FeedBackColor.SetExtended("FeedColorBack",, MyXML, n) + FeedForeColor = New XMLValue(Of Color) + FeedForeColor.SetExtended("FeedColorFore",, MyXML, n) n = {"Users"} FromChannelDownloadTop = New XMLValue(Of Integer)("FromChannelDownloadTop", 10, MyXML, n) @@ -197,7 +209,6 @@ Friend Class SettingsCLS : Implements IDisposable n = {"Notifications"} ShowNotifications = New XMLValue(Of Boolean)("ShowNotifications", True, MyXML, n) - ShowNotifications.ReplaceByValue("ShowNotifications") 'TODELETE: 2022.9.24.0 ShowNotificationsDownProfiles = New XMLValue(Of Boolean)("Profiles", True, MyXML, n) ShowNotificationsDownAutoDownloader = New XMLValue(Of Boolean)("AutoDownloader", True, MyXML, n) ShowNotificationsDownChannels = New XMLValue(Of Boolean)("Channels", True, MyXML, n) @@ -247,63 +258,148 @@ Friend Class SettingsCLS : Implements IDisposable #Region "USERS" Friend Sub LoadUsers() Try - Users.Clear() + Users.ListClearDispose + UsersList.Clear() If UsersSettingsFile.Exists Then Using x As New XmlFile(UsersSettingsFile, Protector.Modes.All, False) With {.AllowSameNames = True} x.LoadData() - If x.Count > 0 Then x.ForEach(Sub(xx) UsersList.Add(xx)) + UsersList.ListAddList(x, LAP.IgnoreICopier) End Using - UsersCompatibilityCheck() - Dim PNC As Func(Of UserInfo, Boolean) = Function(u) Not u.IncludedInCollection And Not u.Protected - Dim NeedUpdate As Boolean = False - 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 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 Or f.IsVirtual, 1, 2) - If Not f.Protected AndAlso SFile.GetPath(f.File.CutPath(m - 1).Path).Exists(SFO.Path, False) Then - If Not d.ContainsKey(f.CollectionName) Then - d.Add(f.CollectionName, New List(Of UserInfo) From {f}) - Else - d(f.CollectionName).Add(f) - End If - Return f - Else - If Not f.Protected Then NeedUpdate = True : UsersList.Remove(f) - Return Nothing - End If - End Function, True) - Dim v% - If d.Count > 0 Then - 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 - d.Clear() - End If - End If - If UsersList.LongCount(PNC) > 0 Then UsersList.Where(PNC).ToList.ForEach(Sub(u) Users.Add(UserDataBase.GetInstance(u, False))) + Dim NeedUpdate As Boolean = False + Dim i%, indx%, c% + Dim UsersListInitialCount% = UsersList.Count + Dim iUser As UserInfo + Dim userFileExists As Boolean + Dim __plugins As List(Of KeyValuePair(Of String, String)) + + If UsersList.Count > 0 Then + __plugins = Plugins.Select(Function(p) New KeyValuePair(Of String, String)(p.Key, p.Name)).ToList + For i% = UsersList.Count - 1 To 0 Step -1 + iUser = UsersList(i) + With iUser + 'Check plugins + If .Plugin.IsEmptyString Then + If .Site.IsEmptyString Then + MyMainLOG = $"The corresponding plugin was not found for the user [{ .Name}]. The user was removed from SCrawler." + Else + indx = __plugins.FindIndex(Function(p) p.Value.ToLower = .Site.ToLower) + If indx >= 0 Then + .Plugin = __plugins(indx).Key + .Site = __plugins(indx).Value + NeedUpdate = True + Else + .Protected = True + MyMainLOG = $"The corresponding plugin was not found for the user [{ .Name}]." + End If + End If + Else + If Not __plugins.Exists(Function(p) p.Key.ToLower = .Plugin.ToLower) Then + .Protected = True + MyMainLOG = $"The corresponding plugin was not found for the user [{ .Plugin}:{ .Site}: { .Name}]." + End If + End If + + 'Check paths + c = IIf((Not .IncludedInCollection Or (.Merged Or .IsVirtual)) And Not .Plugin = PathPlugin.PluginKey, 1, 2) + userFileExists = SFile.GetPath(.File.CutPath(c - 1).Path).Exists(SFO.Path, False) + If Not .IsProtected Then + If userFileExists Then + If .LastSeen.HasValue Then .LastSeen = Nothing : NeedUpdate = True + Else + .LastSeen = Now + MyMainLOG = $"The user [{ .Site}: { .Name}] was not found. " & + $"It will be removed from SCrawler on { .LastSeen.Value.ToStringDate(DateTimeDefaultProvider)}." + NeedUpdate = True + End If + ElseIf userFileExists Then + If .Protected Then + If Not .LastSeen.HasValue Then .LastSeen = Now : NeedUpdate = True + MyMainLOG = $"The corresponding plugin was not found for the user [{ .Site}: { .Name}]. " & + $"It will be removed from SCrawler on { .LastSeen.Value.ToStringDate(DateTimeDefaultProvider)}." + Else + If .LastSeen.HasValue Then .LastSeen = Nothing : NeedUpdate = True + End If + ElseIf If(.LastSeen, Now).AddDays(30) < Now Then + UsersList.RemoveAt(i) + MyMainLOG = $"The user [{ .Site}: { .Name}] was not found and was removed from SCrawler." + NeedUpdate = True + Continue For + End If + End With + UsersList(i) = iUser + Next + + If UsersList.Count > 0 Then + With UsersList + 'Create collections + Dim d As New Dictionary(Of String, List(Of UserInfo)) + .Where(Function(u) u.IncludedInCollection And Not u.IsProtected).ListIfNothing. + ListForEachCopy(Of List(Of UserInfo))(Function(ByVal u As UserInfo, ByVal ii As Integer) As UserInfo + If Not d.ContainsKey(u.CollectionName) Then + d.Add(u.CollectionName, New List(Of UserInfo) From {u}) + Else + d(u.CollectionName).Add(u) + End If + Return u + End Function, True, EDP.ThrowException) + If d.Count > 0 Then + For Each kv As KeyValuePair(Of String, List(Of UserInfo)) In d + Users.Add(New UserDataBind(kv.Key)) + With DirectCast(Users.Last, UserDataBind) + MainFrameObj.CollectionHandler(.Self) + For i = 0 To kv.Value.Count - 1 : .Self.Add(kv.Value(i), False) : Next + End With + Next + d.Clear() + End If + + 'Create users + .Where(Function(u) Not u.IncludedInCollection And Not u.IsProtected). + ListIfNothing.ListForEach(Sub(u, ii) Users.Add(UserDataBase.GetInstance(u, False))) + End With + End If End If + If Users.Count > 0 Then + 'Load user data Dim t As New List(Of Task) For Each user As IUserData In Users : t.Add(Task.Run(AddressOf user.LoadUserInformation)) : Next Task.WaitAll(t.ToArray) t.Clear() - Dim du As List(Of UserInfo) = (From u As IUserData In Users - Where Not u.IsCollection AndAlso Not u.FileExists AndAlso Not DirectCast(u, UserDataBase).User.Protected - Select DirectCast(u, UserDataBase).User).ToList - If du.ListExists Then du.ForEach(Sub(u) UsersList.Remove(u)) : du.Clear() - Users.ListDisposeRemoveAll(Function(ByVal u As IUserData) As Boolean - If Not DirectCast(u, UserDataBase).User.Protected Then + + 'Users final check + Dim findWrongUser As Func(Of UserInfo, Boolean) = Function(ByVal u As UserInfo) As Boolean + Dim uIndex% = UsersList.IndexOf(u) + If uIndex >= 0 Then + Dim uu As UserInfo = UsersList(indx) + If Not uu.LastSeen.HasValue Then + uu.LastSeen = Now + NeedUpdate = True + UsersList(indx) = uu + MyMainLOG = $"The user [{uu.Site}: {uu.Name}] was not found. " & + $"It will be removed from SCrawler on {uu.LastSeen.Value.ToStringDate(DateTimeDefaultProvider)}." + End If + End If + Return uIndex >= 0 + End Function + Users.ListDisposeRemoveAll(Function(ByVal u As UserDataBase) As Boolean + If Not u.User.IsProtected Then If u.IsCollection Then With DirectCast(u, UserDataBind) If .Count > 0 Then + Dim __del As Boolean For i% = .Count - 1 To 0 Step -1 + __del = False If Not .Item(i).FileExists Then - .Item(i).Delete() + With DirectCast(.Item(i), UserDataBase).User + If Not findWrongUser(.Self) Then + __del = True + MyMainLOG = $"The user [{ .Site}: { .Name}] was not found and was removed from SCrawler." + End If + End With + If __del Then .Item(i).Delete() + .Item(i).Dispose() .Collections.RemoveAt(i) End If Next @@ -311,14 +407,22 @@ Friend Class SettingsCLS : Implements IDisposable Return Not .FileExists End With Else - Return Not u.FileExists + If Not u.FileExists Then + If Not findWrongUser(u.User) Then MyMainLOG = $"The user [{u.User.Site}: {u.User.Name}] was not found." + Return True + Else + Return False + End If End If Else Return False End If End Function) End If - If NeedUpdate Then UpdateUsersList() + + If NeedUpdate Or Not UsersList.Count = UsersListInitialCount Then + If UsersList.Count = 0 Then UsersSettingsFile.Delete() Else UpdateUsersList() + End If End If If Users.Count > 0 Then Labels.AddRange(Users.SelectMany(Function(u) u.Labels), False) @@ -327,51 +431,6 @@ Friend Class SettingsCLS : Implements IDisposable Catch ex As Exception End Try End Sub - Private Sub UsersCompatibilityCheck() - With UsersList - Dim user As UserInfo - Dim uKeysList As List(Of String) = Nothing - If Plugins.Count > 0 Then uKeysList = Plugins.Select(Function(p) p.Key).ListIfNothing - If uKeysList Is Nothing Then uKeysList = New List(Of String) - Dim i% - If .Count > 0 AndAlso (uKeysList.Count = 0 OrElse - .Exists(Function(u) u.Site.Length = 1 Or u.Plugin.IsEmptyString Or Not uKeysList.Contains(u.Plugin))) Then - Dim indx% - Dim c As Boolean = False - For i = 0 To .Count - 1 - user = .Item(i) - With user - If .Site.Length = 1 Then - Select Case .Site - Case "1" : .Site = Reddit.RedditSite : c = True - Case "2" : .Site = Twitter.TwitterSite : c = True - Case "3" : .Site = Instagram.InstagramSite : c = True - Case "4" : .Site = RedGifs.RedGifsSite : c = True - End Select - End If - If Not .Site.IsEmptyString Then - If .Plugin.IsEmptyString Then - indx = Plugins.FindIndex(Function(p) p.Settings.Name.ToLower = .Site.ToLower) - If indx >= 0 Then .Plugin = Plugins(indx).Settings.Key : c = True Else .Protected = True - Else - indx = Plugins.FindIndex(Function(p) p.Key = .Plugin) - If indx < 0 Then .Protected = True - End If - End If - .UpdateUserFile() - End With - .Item(i) = user - Next - If c Then UpdateUsersList() - Else - For i = 0 To .Count - 1 - user = .Item(i) - user.UpdateUserFile() - .Item(i) = user - Next - End If - End With - End Sub Private _UserListUpdateRequired As Boolean = False Friend ReadOnly Property UserListUpdateRequired As Boolean Get @@ -546,6 +605,8 @@ Friend Class SettingsCLS : Implements IDisposable Friend ReadOnly Property ChangeReadyForDownOnTempChange As XMLValue(Of Boolean) Friend ReadOnly Property DownloadNativeImageFormat As XMLValue(Of Boolean) Friend ReadOnly Property ReparseMissingInTheRoutine As XMLValue(Of Boolean) + Friend ReadOnly Property UserSiteNameAsFriendly As XMLValue(Of Boolean) + Friend ReadOnly Property UserSiteNameUpdateEveryTime As XMLValue(Of Boolean) #End Region #Region "User data" Friend ReadOnly Property FromChannelDownloadTop As XMLValue(Of Integer) @@ -563,6 +624,19 @@ Friend Class SettingsCLS : Implements IDisposable Friend ReadOnly Property FastProfilesLoading As XMLValue(Of Boolean) Friend ReadOnly Property MaxLargeImageHeight As XMLValue(Of Integer) Friend ReadOnly Property MaxSmallImageHeight As XMLValue(Of Integer) + Friend ReadOnly Property UserListBackColor As XMLValue(Of Color) + Friend ReadOnly Property UserListBackColorF As Color + Get + Return If(UserListBackColor.Exists, UserListBackColor.Value, SystemColors.Window) + End Get + End Property + Friend ReadOnly Property UserListForeColor As XMLValue(Of Color) + Friend ReadOnly Property UserListForeColorF As Color + Get + Return If(UserListForeColor.Exists, UserListForeColor.Value, SystemColors.WindowText) + End Get + End Property + Friend ReadOnly Property UserListImage As XMLValue(Of SFile) Friend ReadOnly Property DownloadOpenInfo As XMLValueAttribute(Of Boolean, Boolean) Friend ReadOnly Property DownloadOpenProgress As XMLValueAttribute(Of Boolean, Boolean) Friend ReadOnly Property DownloadsCompleteCommand As XMLValueAttribute(Of String, Boolean) @@ -622,10 +696,13 @@ Friend Class SettingsCLS : Implements IDisposable #Region "Feed properties" Friend ReadOnly Property FeedDataColumns As XMLValue(Of Integer) Friend ReadOnly Property FeedDataRows As XMLValue(Of Integer) + Friend ReadOnly Property FeedCenterImage As XMLValueUse(Of Integer) Friend ReadOnly Property FeedEndless As XMLValue(Of Boolean) Friend ReadOnly Property FeedAddDateToCaption As XMLValue(Of Boolean) Friend ReadOnly Property FeedAddSessionToCaption As XMLValue(Of Boolean) Friend ReadOnly Property FeedStoreSessionsData As XMLValue(Of Boolean) + Friend ReadOnly Property FeedBackColor As XMLValue(Of Color) + Friend ReadOnly Property FeedForeColor As XMLValue(Of Color) #End Region #Region "New version properties" Friend ReadOnly Property CheckUpdatesAtStart As XMLValue(Of Boolean) diff --git a/SCrawler/UserInfo.vb b/SCrawler/UserInfo.vb index ece6c05..392aa3f 100644 --- a/SCrawler/UserInfo.vb +++ b/SCrawler/UserInfo.vb @@ -25,6 +25,7 @@ Partial Friend Module MainMod Friend Const Name_IsChannel As String = "IsChannel" Friend Const Name_SpecialPath As String = "SpecialPath" Friend Const Name_SpecialCollectionPath As String = "SpecialCollectionPath" + Private Const Name_LastSeen As String = "LastSeen" #End Region #Region "Declarations" Friend Name As String @@ -49,6 +50,12 @@ Partial Friend Module MainMod Friend CollectionModel As UsageModel Friend IsChannel As Boolean Friend [Protected] As Boolean + Friend ReadOnly Property IsProtected As Boolean + Get + Return [Protected] Or (LastSeen.HasValue AndAlso LastSeen.Value.AddDays(30) < Now) + End Get + End Property + Friend LastSeen As Date? Friend ReadOnly Property DownloadOption As DownOptions Get If IsChannel Then @@ -77,6 +84,8 @@ Partial Friend Module MainMod 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) + If Not x.Attribute(Name_LastSeen).Value.IsEmptyString Then LastSeen = AConvert(Of Date)(x.Attribute(Name_LastSeen).Value, DateTimeDefaultProvider, Nothing) + UpdateUserFile() End Sub Friend Sub New(ByVal c As Reddit.Channel) Name = c.Name @@ -145,7 +154,8 @@ Partial Friend Module MainMod New EAttribute(Name_Merged, Merged.BoolToInteger), New EAttribute(Name_IsChannel, IsChannel.BoolToInteger), New EAttribute(Name_SpecialPath, SpecialPath.PathWithSeparator), - New EAttribute(Name_SpecialCollectionPath, SpecialCollectionPath.PathWithSeparator)}) + New EAttribute(Name_SpecialCollectionPath, SpecialCollectionPath.PathWithSeparator), + New EAttribute(Name_LastSeen, AConvert(Of String)(LastSeen, DateTimeDefaultProvider, String.Empty))}) End Function #End Region #Region "IComparable Support" @@ -159,7 +169,8 @@ Partial Friend Module MainMod #End Region #Region "IEquatable Support" Friend Overloads Function Equals(ByVal Other As UserInfo) As Boolean Implements IEquatable(Of UserInfo).Equals - Return Site.StringToLower = Other.Site.StringToLower And Name.StringToLower = Other.Name.StringToLower + Return Site.StringToLower = Other.Site.StringToLower And Name.StringToLower = Other.Name.StringToLower And + (Not Plugin = PathPlugin.PluginKey Or SpecialPath = Other.SpecialPath) End Function Public Overloads Overrides Function Equals(ByVal Obj As Object) As Boolean Return Equals(DirectCast(Obj, UserInfo))