From f1ba2ecd77676cdb24f4f4bccfd3c9304a04dbf3 Mon Sep 17 00:00:00 2001 From: Andy <88590076+AAndyProgram@users.noreply.github.com> Date: Sun, 23 Jan 2022 05:34:09 +0300 Subject: [PATCH] 2.0.0.2 Site settings have been expanded, some functions and dependencies have been changed. Removed unused elements in UserDataBase, added additional xml fields, added error executor. Created a basic download function. Added Instagram saved posts and 429 bypass. Added channel statistics. Added site redgifs. Updated sites algorithms. Other improvements. Updated downloader algorithm. --- CONTRIBUTING.md | 15 +- Changelog.md | 22 + README.md | 23 +- SCrawler.sln | 5 - SCrawler/API/Base/SiteSettings.vb | 47 +- SCrawler/API/Base/Structures.vb | 16 + SCrawler/API/Base/UserDataBase.vb | 162 +- SCrawler/API/Imgur/Envir.vb | 22 +- SCrawler/API/Instagram/Declarations.vb | 2 +- SCrawler/API/Instagram/ProfileSaved.vb | 44 + SCrawler/API/Instagram/UserData.vb | 491 ++++-- SCrawler/API/Reddit/Channel.vb | 37 + SCrawler/API/Reddit/ChannelsCollection.vb | 3 +- SCrawler/API/Reddit/Declarations.vb | 4 +- SCrawler/API/Reddit/M3U8.vb | 2 +- SCrawler/API/Reddit/ProfileSaved.vb | 24 +- SCrawler/API/Reddit/UserData.vb | 96 +- SCrawler/API/Redgifs/Declarations.vb | 22 + SCrawler/API/Redgifs/UserData.vb | 90 ++ SCrawler/API/Twitter/UserData.vb | 128 +- SCrawler/API/UserDataBind.vb | 26 +- SCrawler/Channels/ChannelViewForm.vb | 59 +- .../Channels/ChannelsStatsForm.Designer.vb | 112 ++ SCrawler/Channels/ChannelsStatsForm.resx | 1383 +++++++++++++++++ SCrawler/Channels/ChannelsStatsForm.vb | 84 + SCrawler/Content/Icons/BookmarkIcon_32.ico | Bin 0 -> 18686 bytes SCrawler/Content/Pictures/HeartPic_32.png | Bin 0 -> 525 bytes SCrawler/DownloadSavedPostsForm.Designer.vb | 336 ++++ SCrawler/DownloadSavedPostsForm.resx | 492 ++++++ SCrawler/DownloadSavedPostsForm.vb | 157 ++ SCrawler/DownloadedInfoForm.Designer.vb | 25 +- SCrawler/DownloadedInfoForm.resx | 18 + SCrawler/DownloadedInfoForm.vb | 9 + SCrawler/Editors/CollectionEditorForm.vb | 37 +- .../Editors/GlobalSettingsForm.Designer.vb | 1054 ++++++------- SCrawler/Editors/GlobalSettingsForm.resx | 12 - SCrawler/Editors/GlobalSettingsForm.vb | 91 +- SCrawler/Editors/LabelsForm.Designer.vb | 36 +- SCrawler/Editors/LabelsForm.resx | 6 +- SCrawler/Editors/LabelsForm.vb | 19 +- SCrawler/Editors/SiteDefaults.vb | 102 ++ SCrawler/Editors/SiteEditorForm.vb | 35 +- SCrawler/Editors/SiteSelectionForm.vb | 24 +- SCrawler/Editors/UserCreatorForm.Designer.vb | 78 +- SCrawler/Editors/UserCreatorForm.resx | 3 - SCrawler/Editors/UserCreatorForm.vb | 15 +- SCrawler/MainFrame.Designer.vb | 116 +- SCrawler/MainFrame.resx | 204 +++ SCrawler/MainFrame.vb | 146 +- SCrawler/MainMod.vb | 9 +- SCrawler/My Project/AssemblyInfo.vb | 6 +- SCrawler/My Project/Resources.Designer.vb | 10 + SCrawler/My Project/Resources.resx | 31 +- SCrawler/SCrawler.vbproj | 25 + SCrawler/SettingsCLS.vb | 20 +- SCrawler/TDownloader.vb | 314 ++-- 56 files changed, 5056 insertions(+), 1293 deletions(-) create mode 100644 SCrawler/API/Instagram/ProfileSaved.vb create mode 100644 SCrawler/API/Redgifs/Declarations.vb create mode 100644 SCrawler/API/Redgifs/UserData.vb create mode 100644 SCrawler/Channels/ChannelsStatsForm.Designer.vb create mode 100644 SCrawler/Channels/ChannelsStatsForm.resx create mode 100644 SCrawler/Channels/ChannelsStatsForm.vb create mode 100644 SCrawler/Content/Icons/BookmarkIcon_32.ico create mode 100644 SCrawler/Content/Pictures/HeartPic_32.png create mode 100644 SCrawler/DownloadSavedPostsForm.Designer.vb create mode 100644 SCrawler/DownloadSavedPostsForm.resx create mode 100644 SCrawler/DownloadSavedPostsForm.vb create mode 100644 SCrawler/Editors/SiteDefaults.vb diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f2be5e6..d70102f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributor's Guide -I welcome pull requests! Follow these steps to contribute: +I welcome requests! Follow these steps to contribute: 1. Find an [issue](https://github.com/AAndyProgram/SCrawler/issues) that needs assistance. 2. Let me know you are working on it by posting a comment on the issue. @@ -21,11 +21,22 @@ I welcome pull requests! Follow these steps to contribute: 2. If you don't find anything, create a new issue with your request. I usually reply as soon as possible (within the next few hours). - If I'm interested in a site you want to add, it may be added in future releases. - If the site has an API that does not require authorization, it may be added in the coming releases. - - You can make it faster by posting a link to the API. I don't use OAuth authentication in my application, so if it's not too hard to make a new parsing algorithm without OAuth authorization, I can start developing it in the coming days. Otherwise, I need time to figure out how to do it. + - You can make it faster by posting a link to the API. **I don't use OAuth authentication** in my application, so if it's not too hard to make a new parsing algorithm **without OAuth** authorization, I can start developing it in the coming days. Otherwise, I need time to figure out how to do it. - If the site does not have an API that does not require authorization, this may take some time. + - If you will be posting request urls **without OAuth** authentication, I might consider adding your site if I have time. - If I'm **not** interested in the site you want to add, you can pay to have it added by making a donation of approximately $10. **But before that, you still need to create an issue. If I'm not interested, you can offer me a deal to develop it for money. I'll check the site you want to add, check the availability of the API and tell you how much time I need to develop it and the price. If you agree, I will do it.** [![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/andyprogram) # Sites I will never develop - Facebook + +# Sites requested by users + +- TikTok + - API for receiving data without authorization was not found. Therefore, I don't have time to start developing this site parsing algorithm. If anyone knows of requests that may collect data without OAuth authentication, please let me know. + +# Contact me + +[Element messenger](https://element.io/): @andyprogram:matrix.org +https://matrix.to/#/@andyprogram:matrix.org \ No newline at end of file diff --git a/Changelog.md b/Changelog.md index e5616e3..9594669 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,25 @@ +# 2.0.0.2 + +**This is the last release that supports program settings of version 1.0.0.4 and lower. Compatibility of program settings with version 1.0.0.4 and lower will be removed in future releases. It is strongly recommended that you upgrade to this release before future releases. Otherwise, you will have to configure the program settings again. If your program version is 1.0.1.0 or higher, you should not pay attention to this message.** + +- Added + - Tray icon + - Close program to tray + - Close confirmation dialog + - **Separated thread for downloading Instagram profiles** + - **Wait timers to bypass Instagram error "Too Many Requests" (429)** + - **Downloading saved Instagram posts** *(requires a second InstaHash)* + - Downloading saved posts (from Reddit and Instagram) form + - Tray notification when download is complete (Instagram notification separate from other) + - Downloading not downloaded Instagram posts when a 429 error is encountered and/or the user stops downloading + - Separate progress bar for downloading Instagram profiles + - Clear information about downloaded profiles of the current session in the "Download info form" + - Increased the number of Instagram posts (from 12 to 50) received per request + - Channels' statistics + - **RedGisf profiles support** +- Fixed + - The program was showing incorrect information about the total numbers of images and videos downloaded when a Reddit user was created from a channel + # 2.0.0.1 - Added diff --git a/README.md b/README.md index 1058ee7..f17a3d8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Social networks crawler -Program for downloading photo and video from Reddit, Twitter and Instagram +A program to download photo and video from Reddit, Twitter, Instagram, [etc](#supported-sites). Do you like this program? Consider adding to my coffee fund by making a donation to show your support. :) @@ -11,23 +11,30 @@ Do you like this program? Consider adding to my coffee fund by making a donation - Reddit images; - Reddit galleries of images; - Redgifs hosted videos (https://www.redgifs.com/); - - Reddit hosted videos (downloading Reddit hosted video is going through ffmpeg); + - Reddit hosted videos (downloading Reddit hosted video is going through ffmpeg (**ffmpeg only works with the x64 program**)); - Twitter images and videos; - Instagram images and videos. - Parse [channel and view data](https://github.com/AAndyProgram/SCrawler/wiki/Channels). -- Download [saved Reddit posts](https://github.com/AAndyProgram/SCrawler/wiki/Home#saved-posts). +- Download [saved Reddit and Instagram posts](https://github.com/AAndyProgram/SCrawler/wiki/Home#saved-posts). - Add users from parsed channel. - Labeling users. - Filter exists users by label or group. - Selection of media types you want to download (images only, videos only, both) +# Supported sites + +- Reddit +- Twitter +- Instagram +- RedGifs + # How does it works: ## Reddit The program parses all user posts, obtain MD5 images hash and compares them with existing ones to remove duplicates. Then the media will be downloaded. -## Twitter and Instagram +## Other sites The program parses all user posts and compares file names with existing ones to remove duplicates. Then the media will be downloaded. @@ -42,7 +49,7 @@ Read [here](https://github.com/AAndyProgram/SCrawler/blob/main/CONTRIBUTING.md#h - Windows 7, 8, 9, 10, 11 with NET Framework 4.6.1 or higher - Authorization cookies and tokens for Twitter (if you want to download data from Twitter) - Authorization cookies Instagram (if you want to download data from Instagram) -- ffmpeg library for downloading videos hosted on Reddit (you can download it from the [official repo](https://github.com/GyanD/codexffmpeg/releases/tag/2021-01-12-git-ca21cb1e36) or [from my first release](https://github.com/AAndyProgram/SCrawler/releases/download/1.0.0.0/ffmpeg.zip)) +- ffmpeg library for downloading videos hosted on Reddit (you can download it from the [official repo](https://github.com/GyanD/codexffmpeg/releases/tag/2021-01-12-git-ca21cb1e36) or [from my first release](https://github.com/AAndyProgram/SCrawler/releases/download/1.0.0.0/ffmpeg.zip)). **ffmpeg only works with the x64 version of the program.** - **Don't put program in the ```Program Files``` system folder (this is portable program and program settings are stored in the program folder)** - **Just unzip the program archive to any folder, copy the file ```ffmpeg.exe``` into it and enjoy. :)** @@ -69,6 +76,7 @@ You can add users by patterns: - https://twitter.com/SomeUserName - https://reddit.com/user/SomeUserName - https://reddit.com/r/SomeSubredditName +- https://www.redgifs.com/users/SomeUserName - u/SomeUserName - r/SomeSubredditName - SomeUserName (in this case, you need to select the user's site) @@ -83,3 +91,8 @@ Read more about adding users and subreddits [here](https://github.com/AAndyProgr Create a shortcut for the program. Open shortcut properties. In the ```Shortcut``` tab, in the ```Target``` field, just add the letter ```v``` at the end across the space. Example: ```D:\Programs\SCrawler\SCrawler.exe v``` + +# Contact me + +[Element messenger](https://element.io/): @andyprogram:matrix.org +https://matrix.to/#/@andyprogram:matrix.org \ No newline at end of file diff --git a/SCrawler.sln b/SCrawler.sln index a51dee8..b95a325 100644 --- a/SCrawler.sln +++ b/SCrawler.sln @@ -11,13 +11,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ProjectSection(SolutionItems) = preProject .gitignore = .gitignore Changelog.md = Changelog.md - Info\InstaAlgo.txt = Info\InstaAlgo.txt - Info\InstagramInfo.txt = Info\InstagramInfo.txt README.md = README.md - Info\RedditUrlsInfo.txt = Info\RedditUrlsInfo.txt ToDo.txt = ToDo.txt - Info\TwitterNewAlgo.txt = Info\TwitterNewAlgo.txt - Info\TwitterUrlsInfo.txt = Info\TwitterUrlsInfo.txt EndProjectSection EndProject Global diff --git a/SCrawler/API/Base/SiteSettings.vb b/SCrawler/API/Base/SiteSettings.vb index 32db4b1..2652bb9 100644 --- a/SCrawler/API/Base/SiteSettings.vb +++ b/SCrawler/API/Base/SiteSettings.vb @@ -25,7 +25,9 @@ Namespace API.Base _Path.Value = NewFile End Set End Property +#Region "Instagram" Friend ReadOnly Property InstaHash As XMLValue(Of String) + Friend ReadOnly Property InstaHash_SP As XMLValue(Of String) Friend ReadOnly Property InstaHashUpdateRequired As XMLValue(Of Boolean) Friend ReadOnly Property InstagramDownloadingErrorDate As XMLValue(Of Date) Friend Property InstagramLastApplyingValue As Integer? = Nothing @@ -40,7 +42,18 @@ Namespace API.Base End With End Get End Property - Friend Property InstagramTooManyRequestsReadyForCatch As Boolean = True + Friend ReadOnly Property InstagramLastDownloadDate As XMLValue(Of Date) + Friend ReadOnly Property InstagramLastRequestsCount As XMLValue(Of Integer) + Private InstagramTooManyRequestsReadyForCatch As Boolean = True + Friend Function GetInstaWaitDate() As Date + With InstagramDownloadingErrorDate + If .ValueF.Exists Then + Return .ValueF.Value.AddMinutes(If(InstagramLastApplyingValue, 10)) + Else + Return Now + End If + End With + End Function Friend Sub InstagramTooManyRequests(ByVal Catched As Boolean) With InstagramDownloadingErrorDate If Catched Then @@ -55,9 +68,14 @@ Namespace API.Base Else .ValueF = Nothing InstagramLastApplyingValue = Nothing + InstagramTooManyRequestsReadyForCatch = True End If End With End Sub + Friend ReadOnly Property RequestsWaitTimer As XMLValue(Of Integer) + Friend ReadOnly Property RequestsWaitTimerTaskCount As XMLValue(Of Integer) + Friend ReadOnly Property SleepTimerOnPostsLimit As XMLValue(Of Integer) +#End Region Friend ReadOnly Property Temporary As XMLValue(Of Boolean) Friend ReadOnly Property DownloadImages As XMLValue(Of Boolean) Friend ReadOnly Property DownloadVideos As XMLValue(Of Boolean) @@ -98,6 +116,7 @@ Namespace API.Base Responser.CookiesDomain = "reddit.com" Responser.Decoders.Add(SymbolsConverter.Converters.Unicode) Case Sites.Instagram : Responser.CookiesDomain = "instagram.com" + Case Sites.RedGifs : Responser.CookiesDomain = "redgifs.com" End Select Responser.SaveSettings() End If @@ -126,20 +145,30 @@ Namespace API.Base GetUserMediaOnly = New XMLValue(Of Boolean) End If + CreateProp(InstaHashUpdateRequired, Sites.Instagram, "InstaHashUpdateRequired", True, _XML, n) + CreateProp(InstaHash, Sites.Instagram, "InstaHash", String.Empty, _XML, n) + If Site = Sites.Instagram AndAlso (InstaHash.IsEmptyString Or InstaHashUpdateRequired) AndAlso Responser.Cookies.ListExists Then GatherInstaHash() + CreateProp(InstaHash_SP, Sites.Instagram, "InstaHashSavedPosts", String.Empty, _XML, n) + CreateProp(InstagramLastDownloadDate, Sites.Instagram, "LastDownloadDate", Now.AddDays(-1), _XML, n) + CreateProp(InstagramLastRequestsCount, Sites.Instagram, "LastRequestsCount", 0, _XML, n) + CreateProp(RequestsWaitTimer, Sites.Instagram, "RequestsWaitTimer", 1000, _XML, n) + CreateProp(RequestsWaitTimerTaskCount, Sites.Instagram, "RequestsWaitTimerTaskCount", 1, _XML, n) + CreateProp(SleepTimerOnPostsLimit, Sites.Instagram, "SleepTimerOnPostsLimit", 60000, _XML, n) If Site = Sites.Instagram Then - InstaHash = New XMLValue(Of String)("InstaHash", String.Empty, _XML, n) - InstaHashUpdateRequired = New XMLValue(Of Boolean)("InstaHashUpdateRequired", True, _XML, n) - If (InstaHash.IsEmptyString Or InstaHashUpdateRequired) And Responser.Cookies.ListExists Then GatherInstaHash() InstagramDownloadingErrorDate = New XMLValue(Of Date) With {.ToStringFunction = Function(ss, vv) AConvert(Of String)(vv, Nothing)} InstagramDownloadingErrorDate.SetExtended("InstagramDownloadingErrorDate", Now.AddYears(-10), _XML, n) Else - InstaHash = New XMLValue(Of String) - InstaHashUpdateRequired = New XMLValue(Of Boolean) + InstagramDownloadingErrorDate = New XMLValue(Of Date) End If - If Site = Sites.Reddit Then - SavedPostsUserName = New XMLValue(Of String)("SavedPostsUserName", String.Empty, _XML, n) + + SavedPostsUserName = New XMLValue(Of String)("SavedPostsUserName", String.Empty, _XML, n) + End Sub + Private Sub CreateProp(Of T)(ByRef p As XMLValue(Of T), ByVal s As Sites, + ByVal p_Name As String, ByVal p_Value As T, ByRef x As XmlFile, ByVal n() As String) + If Site = s Then + p = New XMLValue(Of T)(p_Name, p_Value, x, n) Else - SavedPostsUserName = New XMLValue(Of String) + p = New XMLValue(Of T) End If End Sub Friend Sub Update() diff --git a/SCrawler/API/Base/Structures.vb b/SCrawler/API/Base/Structures.vb index 05e6498..41657ad 100644 --- a/SCrawler/API/Base/Structures.vb +++ b/SCrawler/API/Base/Structures.vb @@ -85,5 +85,21 @@ Namespace API.Base Return v End Function End Structure + Friend Structure Sizes : Implements IComparable(Of Sizes) + Friend Value As Integer + Friend Data As String + Friend ReadOnly HasError As Boolean + Friend Sub New(ByVal _Value As String, ByVal _Data As String) + Try + Value = _Value + Data = _Data + Catch ex As Exception + HasError = True + End Try + End Sub + Friend Function CompareTo(ByVal Other As Sizes) As Integer Implements IComparable(Of Sizes).CompareTo + Return Value.CompareTo(Other.Value) * -1 + End Function + End Structure End Module End Namespace \ No newline at end of file diff --git a/SCrawler/API/Base/UserDataBase.vb b/SCrawler/API/Base/UserDataBase.vb index 4c12542..d9c382c 100644 --- a/SCrawler/API/Base/UserDataBase.vb +++ b/SCrawler/API/Base/UserDataBase.vb @@ -7,9 +7,12 @@ ' This program is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY Imports PersonalUtilities.Functions.XML +Imports PersonalUtilities.Forms.Toolbars Imports System.IO +Imports System.Net Imports System.Threading -Imports UState = SCrawler.API.Base.UserMedia.States +Imports UStates = SCrawler.API.Base.UserMedia.States +Imports UTypes = SCrawler.API.Base.UserMedia.Types Namespace API.Base Friend MustInherit Class UserDataBase : Implements IUserData Friend Const UserFileAppender As String = "User" @@ -77,10 +80,17 @@ Namespace API.Base #End Region #Region "Declarations" Friend MustOverride Property Site As Sites Implements IContentProvider.Site + Protected _Progress As MyProgress + Friend Overridable Property Progress As MyProgress + Get + If _Progress Is Nothing Then Return MainProgress Else Return _Progress + End Get + Set(ByVal p As MyProgress) + _Progress = p + End Set + End Property Friend User As UserInfo Friend Property IsSavedPosts As Boolean - Protected Const NonExistendUserHelp As String = "404" - Protected Const SuspendedUserHelp As String = "403" Friend Overridable Property UserExists As Boolean = True Implements IUserData.Exists Friend Overridable Property UserSuspended As Boolean = False Implements IUserData.Suspended Friend Overridable Property Name As String Implements IContentProvider.Name @@ -288,7 +298,7 @@ BlockNullPicture: #End Region #Region "Information" Protected _CountVideo As Integer = 0 - Protected _CountPictures As Integer = 0 + Protected Property _CountPictures As Integer = 0 Friend Overridable Property LastUpdated As Date? Friend ReadOnly Property TotalContentCount As Integer Get @@ -339,7 +349,7 @@ BlockNullPicture: Friend ReadOnly Property LVIKey As String Implements IUserData.LVIKey Get If Not _IsCollection Then - Return $"{Interaction.Switch(Site = Sites.Reddit, "R", Site = Sites.Twitter, "T", Site = Sites.Instagram, "I")}_{Name}" + Return $"{Site.ToString.ToUpper.Substring(0, 1)}_{Name}" Else Return $"CCCC_{CollectionName}" End If @@ -436,6 +446,7 @@ BlockNullPicture: End If Case Sites.Twitter : Return New Twitter.UserData(u, _LoadUserInformation) Case Sites.Instagram : Return New Instagram.UserData(u, _LoadUserInformation) + Case Sites.RedGifs : Return New RedGifs.UserData(u, _LoadUserInformation) Case Else : Throw New ArgumentOutOfRangeException("Site", $"Site [{u.Site}] information does not recognized by loader") End Select End Function @@ -469,6 +480,7 @@ BlockNullPicture: DataMerging = x.Value(Name_DataMerging).FromXML(Of Boolean)(False) ChangeCollectionName(x.Value(Name_CollectionName), False) Labels.ListAddList(x.Value(Name_LabelsName).StringToList(Of String, List(Of String))("|", EDP.ReturnValue), LAP.NotContainsOnly, LAP.ClearBeforeAdd) + LoadUserInformation_OptionalFields(x, True) End Using UpdateDataFiles() End If @@ -506,6 +518,8 @@ BlockNullPicture: x.Add(Name_LabelsName, Labels.ListToString(, "|", EDP.ReturnValue)) x.Add(Name_DataMerging, DataMerging.BoolToInteger) + LoadUserInformation_OptionalFields(x, False) + x.Save(MyFile) End Using If Not IsSavedPosts Then Settings.UpdateUsersList(User) @@ -513,16 +527,15 @@ BlockNullPicture: LogError(ex, "user information saving error") End Try End Sub + ''' : Loading; : Saving + Protected MustOverride Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean) #End Region #Region "User data" Friend Overridable Overloads Sub LoadContentInformation() - UpdateDataFiles() - LoadContentInformation(_ContentList, MyFileData) - End Sub - Private Overloads Sub LoadContentInformation(ByRef _CLIST As List(Of UserMedia), ByVal f As SFile) Try - If Not f.Exists Then Exit Sub - Using x As New XmlFile(f, Protector.Modes.All, False) With {.XmlReadOnly = True, .AllowSameNames = True} + UpdateDataFiles() + If Not MyFileData.Exists Then Exit Sub + Using x As New XmlFile(MyFileData, Protector.Modes.All, False) With {.XmlReadOnly = True, .AllowSameNames = True} x.LoadData() If x.Count > 0 Then Dim fs$ = MyFile.CutPath.PathWithSeparator @@ -538,7 +551,7 @@ BlockNullPicture: End If End Function For Each v As EContainer In x - _CLIST.Add(New UserMedia With { + _ContentList.Add(New UserMedia With { .Type = AConvert(Of Integer)(v.Attribute(Name_MediaType).Value, 0), .URL = v.Attribute(Name_MediaURL).Value, .URL_BASE = v.Value, @@ -556,14 +569,14 @@ BlockNullPicture: LogError(ex, "history loading error") End Try End Sub - Friend Sub UpdateContentInformation(ByRef _CLIST As List(Of UserMedia), ByVal f As SFile) + Friend Sub UpdateContentInformation() Try UpdateDataFiles() - If f.IsEmptyString Then Exit Sub - f.Exists(SFO.Path) + If MyFileData.IsEmptyString Then Exit Sub + MyFileData.Exists(SFO.Path) Using x As New XmlFile With {.AllowSameNames = True, .Name = "Data"} - If _CLIST.Count > 0 Then - For Each i As UserMedia In _CLIST + If _ContentList.Count > 0 Then + For Each i As UserMedia In _ContentList x.Add(New EContainer("MediaData", i.URL_BASE, {New EAttribute(Name_MediaType, CInt(i.Type)), New EAttribute(Name_MediaURL, i.URL), @@ -631,9 +644,9 @@ BlockNullPicture: ThrowAny(Token) If _TempMediaList.Count > 0 Then - If Not DownloadImages Then _TempMediaList.RemoveAll(Function(m) m.Type = UserMedia.Types.GIF Or m.Type = UserMedia.Types.Picture) - If Not DownloadVideos Then _TempMediaList.RemoveAll(Function(m) m.Type = UserMedia.Types.Video Or - m.Type = UserMedia.Types.VideoPre Or m.Type = UserMedia.Types.m3u8) + If Not DownloadImages Then _TempMediaList.RemoveAll(Function(m) m.Type = UTypes.GIF Or m.Type = UTypes.Picture) + If Not DownloadVideos Then _TempMediaList.RemoveAll(Function(m) m.Type = UTypes.Video Or + m.Type = UTypes.VideoPre Or m.Type = UTypes.m3u8) End If ReparseVideo(Token) @@ -642,14 +655,14 @@ BlockNullPicture: _ContentNew.ListAddList(_TempMediaList, LAP.ClearBeforeAdd) DownloadContent(Token) ThrowIfDisposed() - _ContentList.ListAddList(_ContentNew.Where(Function(c) c.State = UState.Downloaded), LNC) - _CountPictures = _ContentList.LongCount(Function(c) c.Type = UserMedia.Types.Picture) - _CountVideo = _ContentList.LongCount(Function(c) c.Type = UserMedia.Types.Video) + _ContentList.ListAddList(_ContentNew.Where(Function(c) c.State = UStates.Downloaded), LNC) + _CountPictures = _ContentList.LongCount(Function(c) c.Type = UTypes.Picture) + _CountVideo = _ContentList.LongCount(Function(c) c.Type = UTypes.Video) If DownloadedPictures + DownloadedVideos > 0 Or EnvirChanged.Invoke Then If __SaveData Then LastUpdated = Now If Labels.Contains(LabelsKeeper.NoParsedUser) Then Labels.Remove(LabelsKeeper.NoParsedUser) - UpdateContentInformation(_ContentList, MyFileData) + UpdateContentInformation() Else _CountVideo = 0 _CountPictures = 0 @@ -660,8 +673,10 @@ BlockNullPicture: UpdateUserInformation() End If ThrowIfDisposed() - _DownloadedPicturesTotal += _DownloadedPicturesSession - _DownloadedVideosTotal += _DownloadedVideosSession + If Not CreatedByChannel Then + _DownloadedPicturesTotal += _DownloadedPicturesSession + _DownloadedVideosTotal += _DownloadedVideosSession + End If If UpPic Or EnvirChanged.Invoke Then Raise_OnUserUpdated() Catch oex As OperationCanceledException When Token.IsCancellationRequested MyMainLOG = $"{Site} - {Name}: downloading canceled" @@ -692,6 +707,99 @@ BlockNullPicture: Protected MustOverride Sub DownloadDataF(ByVal Token As CancellationToken) Protected MustOverride Sub ReparseVideo(ByVal Token As CancellationToken) Protected MustOverride Sub DownloadContent(ByVal Token As CancellationToken) + Protected Sub DownloadContentDefault(ByVal Token As CancellationToken) + Try + Dim i% + Dim dCount% = 0, dTotal% = 0 + ThrowAny(Token) + If _ContentNew.Count > 0 Then + _ContentNew.RemoveAll(Function(c) c.URL.IsEmptyString) + If _ContentNew.Count > 0 Then + MyFile.Exists(SFO.Path) + Dim MyDir$ = MyFile.CutPath.PathNoSeparator + Dim vsf As Boolean = SeparateVideoFolderF + Dim __isVideo As Boolean + Dim f As SFile + Dim v As UserMedia + Using w As New WebClient + If vsf Then SFileShares.SFileExists($"{MyDir}\Video\", SFO.Path) + Progress.TotalCount += _ContentNew.Count + For i = 0 To _ContentNew.Count - 1 + ThrowAny(Token) + v = _ContentNew(i) + v.State = UStates.Tried + If v.File.IsEmptyString Then + f = v.URL + Else + f = v.File + End If + f.Separator = "\" + f.Path = MyDir + + If v.URL_BASE.IsEmptyString Then v.URL_BASE = v.URL + + If Not v.File.IsEmptyString And Not v.URL_BASE.IsEmptyString Then + Try + __isVideo = v.Type = UTypes.Video Or f.Extension = "mp4" + + If f.Extension.IsEmptyString Then + Select Case v.Type + Case UTypes.Picture : f.Extension = "jpg" + Case UTypes.Video : f.Extension = "mp4" + Case UTypes.GIF : f.Extension = "gif" + End Select + End If + + If __isVideo And vsf Then f.Path = $"{f.PathWithSeparator}Video" + w.DownloadFile(v.URL_BASE, f.ToString) + + If __isVideo Then + v.Type = UTypes.Video + DownloadedVideos += 1 + _CountVideo += 1 + Else + v.Type = UTypes.Picture + DownloadedPictures += 1 + _CountPictures += 1 + End If + + v.File = ChangeFileNameByProvider(f, v) + v.State = UStates.Downloaded + dCount += 1 + Catch wex As Exception + ErrorDownloading(f, v.URL_BASE) + End Try + Else + v.State = UStates.Skipped + End If + _ContentNew(i) = v + If DownloadTopCount.HasValue AndAlso dCount >= DownloadTopCount.Value Then + Progress.Perform(_ContentNew.Count - dTotal) + Exit Sub + Else + dTotal += 1 + Progress.Perform() + End If + Next + End Using + End If + End If + Catch oex As OperationCanceledException When Token.IsCancellationRequested + Catch dex As ObjectDisposedException When Disposed + Catch ex As Exception + LogError(ex, "content downloading error") + HasError = True + End Try + End Sub + ''' Request DownloadingException + Protected Sub ProcessException(ByVal ex As Exception, ByVal Token As CancellationToken, ByVal Message As String, Optional ByVal RDE As Boolean = True) + If Not ((TypeOf ex Is OperationCanceledException And Token.IsCancellationRequested) Or + (TypeOf ex Is ObjectDisposedException And Disposed)) Then + If RDE AndAlso DownloadingException(ex, Message, True) = 0 Then LogError(ex, Message) : HasError = True + End If + End Sub + ''' 0 - Execute LogError and set HasError + Protected MustOverride Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False) As Integer Protected Function ChangeFileNameByProvider(ByVal f As SFile, ByVal m As UserMedia) As SFile Dim ff As SFile = Nothing Try @@ -1020,7 +1128,7 @@ BlockNullPicture: ''' 0 - Nothing removed
''' 1 - User removed
''' 2 - Collection removed
- ''' 3 - Collection splitted + ''' 3 - Collection split ''' Function Delete() As Integer Function MoveFiles(ByVal CollectionName As String) As Boolean diff --git a/SCrawler/API/Imgur/Envir.vb b/SCrawler/API/Imgur/Envir.vb index 8ad3466..a1bed01 100644 --- a/SCrawler/API/Imgur/Envir.vb +++ b/SCrawler/API/Imgur/Envir.vb @@ -46,8 +46,7 @@ Namespace API.Imgur End If Return Nothing Catch ex As Exception - If Not e.Exists Then e = New ErrorsDescriber(EDP.ReturnValue + EDP.SendInLog) - Return ErrorsDescriber.Execute(e, ex, $"[API.Imgur.Envir.GetGallery({URL})]", Nothing) + Return DownloadingException(ex, $"[API.Imgur.Envir.GetGallery({URL})]", Nothing, e) End Try End Function Friend Shared Function GetImage(ByVal URL As String, Optional ByVal e As ErrorsDescriber = Nothing) As String @@ -64,8 +63,7 @@ Namespace API.Imgur End If Return String.Empty Catch ex As Exception - If Not e.Exists Then e = New ErrorsDescriber(EDP.ReturnValue + EDP.SendInLog) - Return ErrorsDescriber.Execute(e, ex, $"[API.Imgur.Envir.GetImage({URL})]", String.Empty) + Return DownloadingException(ex, $"[API.Imgur.Envir.GetImage({URL})]", String.Empty, e) End Try End Function Friend Shared Function GetVideoInfo(ByVal URL As String) As IEnumerable(Of UserMedia) @@ -83,5 +81,21 @@ Namespace API.Imgur Return ErrorsDescriber.Execute(EDP.ShowMainMsg + EDP.SendInLog, ex, "Imgur standalone downloader: fetch media error") End Try End Function + Private Shared Function DownloadingException(ByVal ex As Exception, ByVal Message As String, + ByVal NullArg As Object, ByVal e As ErrorsDescriber) As Object + If TypeOf ex Is WebException Then + Dim obj As HttpWebResponse = TryCast(DirectCast(ex, WebException).Response, HttpWebResponse) + If Not obj Is Nothing Then + If obj.StatusCode = HttpStatusCode.NotFound Then + Return NullArg + ElseIf obj.StatusCode = HttpStatusCode.Unauthorized Then + MyMainLOG = "Imgur credentials expired" + Return NullArg + End If + End If + End If + If Not e.Exists Then e = New ErrorsDescriber(EDP.ReturnValue + EDP.SendInLog) + Return ErrorsDescriber.Execute(e, ex, Message, NullArg) + End Function End Class End Namespace \ No newline at end of file diff --git a/SCrawler/API/Instagram/Declarations.vb b/SCrawler/API/Instagram/Declarations.vb index 2ec5b3a..fa8376a 100644 --- a/SCrawler/API/Instagram/Declarations.vb +++ b/SCrawler/API/Instagram/Declarations.vb @@ -8,7 +8,7 @@ ' but WITHOUT ANY WARRANTY Namespace API.Instagram Friend Module Declarations - Friend ReadOnly FilesPattern As New RegexStructure("[^\./]+?\.\w+", True, False, 2,,,, String.Empty, EDP.ReturnValue) + Friend ReadOnly FilesPattern As New RegexStructure(".+?([^/\?]+?\.[\w\d]{3,4})(?=(\?|\Z))",,,, 1,,, String.Empty, EDP.ReturnValue) Friend ReadOnly Property DateProvider As New JsonDate Friend Class JsonDate : Implements ICustomProvider Friend Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider, diff --git a/SCrawler/API/Instagram/ProfileSaved.vb b/SCrawler/API/Instagram/ProfileSaved.vb new file mode 100644 index 0000000..241d689 --- /dev/null +++ b/SCrawler/API/Instagram/ProfileSaved.vb @@ -0,0 +1,44 @@ +' Copyright (C) 2022 Andy +' 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 System.Threading +Imports PersonalUtilities.Forms.Toolbars +Namespace API.Instagram + Friend NotInheritable Class ProfileSaved + Friend Shared ReadOnly Property DataPath As SFile = $"{Settings(Sites.Instagram).Path.PathNoSeparator}\!Saved\" + Private Sub New() + End Sub + Friend Shared Sub Download(ByRef Bar As MyProgress, ByVal Token As CancellationToken) + Try + Dim u As New UserInfo(Settings(Sites.Instagram).SavedPostsUserName.Value, Sites.Instagram) With {.SpecialPath = DataPath} + u.UpdateUserFile() + Using user As New UserData(u,, False) + DirectCast(user.Self, UserDataBase).IsSavedPosts = True + user.Progress = Bar + If Not user.FileExists Then user.UpdateUserInformation() + If Settings(Sites.Instagram).InstagramLastDownloadDate.Value < Now.AddMinutes(60) Then + user.RequestsCount = Settings(Sites.Instagram).InstagramLastRequestsCount + End If + user.DownloadData(Token) + Bar.InformationTemporary = $"Images: {user.DownloadedPictures}; Videos: {user.DownloadedVideos}" + With Settings + .BeginUpdate() + With .Site(Sites.Instagram) + .InstagramLastDownloadDate.Value = Now + .InstagramLastRequestsCount.Value = user.RequestsCount + End With + .EndUpdate() + End With + End Using + Catch ex As Exception + ErrorsDescriber.Execute(EDP.SendInLog, ex, "[API.Instagram.ProfileSaved.Download]") + End Try + End Sub + End Class +End Namespace \ No newline at end of file diff --git a/SCrawler/API/Instagram/UserData.vb b/SCrawler/API/Instagram/UserData.vb index 207e0aa..3278ae1 100644 --- a/SCrawler/API/Instagram/UserData.vb +++ b/SCrawler/API/Instagram/UserData.vb @@ -7,103 +7,275 @@ ' This program is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY Imports PersonalUtilities.Functions.XML +Imports PersonalUtilities.Functions.Messaging Imports PersonalUtilities.Tools.WebDocuments.JSON +Imports PersonalUtilities.Forms.Toolbars Imports SCrawler.API.Base Imports System.Threading Imports System.Net -Imports UStates = SCrawler.API.Base.UserMedia.States Imports UTypes = SCrawler.API.Base.UserMedia.Types Namespace API.Instagram Friend Class UserData : Inherits UserDataBase + Private Const MaxPostsCount As Integer = 200 + Private Const Name_LastCursor As String = "LastCursor" + Private Const Name_FirstLoadingDone As String = "FirstLoadingDone" Friend Overrides Property Site As Sites = Sites.Instagram + Friend Overrides Property Progress As MyProgress + Get + If Not _Progress Is Nothing Then Return _Progress Else Return MainProgressInst + End Get + Set(ByVal p As MyProgress) + _Progress = p + End Set + End Property + Private ReadOnly _SavedPostsIDs As New List(Of String) + Private LastCursor As String = String.Empty + Private FirstLoadingDone As Boolean = True ''' Video downloader initializer Private Sub New() End Sub ''' Default initializer - Friend Sub New(ByVal u As UserInfo, Optional ByVal _LoadUserInformation As Boolean = True) + Friend Sub New(ByVal u As UserInfo, Optional ByVal _LoadUserInformation As Boolean = True, Optional ByVal InvokeImageHandler As Boolean = True) + MyBase.New(InvokeImageHandler) User = u If _LoadUserInformation Then LoadUserInformation() End Sub + Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean) + If Loading Then + LastCursor = Container.Value(Name_LastCursor) + FirstLoadingDone = Container.Value(Name_FirstLoadingDone).FromXML(Of Boolean)(False) + Else + Container.Add(Name_LastCursor, LastCursor) + Container.Add(Name_FirstLoadingDone, FirstLoadingDone.BoolToInteger) + End If + End Sub Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) - DownloadData(String.Empty, Token) + Try + _InstaHash = String.Empty + HasError = False + If Not LastCursor.IsEmptyString Then + DownloadData(LastCursor, Token) + ThrowAny(Token) + If Not HasError Then FirstLoadingDone = True + End If + If Not HasError Then + DownloadData(String.Empty, Token) + ThrowAny(Token) + If Not HasError Then FirstLoadingDone = True + End If + If FirstLoadingDone Then LastCursor = String.Empty + If IsSavedPosts Then DownloadPosts(Token) + If WaitNotificationMode = WNM.SkipTemp Or WaitNotificationMode = WNM.SkipCurrent Then WaitNotificationMode = WNM.Notify + Catch ex As Exception + ProcessException(ex, Token, "[API.Instagram.UserData.DownloadDataF", False) + End Try End Sub Private _InstaHash As String = String.Empty +#Region "429 bypass" + Friend RequestsCount As Integer = 0 + Friend Enum WNM As Integer + Notify = 0 + SkipCurrent = 1 + SkipAll = 2 + SkipTemp = 3 + End Enum + Friend WaitNotificationMode As WNM = WNM.Notify + Private Caught429 As Boolean = False + Private ProgressTempSet As Boolean = False + Private Const InstAborted As String = "InstAborted" + Private Function Ready() As Boolean + With Settings(Sites.Instagram) + If Not .InstagramReadyForDownload Then + If WaitNotificationMode = WNM.Notify Then + Dim m As New MMessage("Instagram [too many requests] error." & vbCr & + $"The program suggests waiting {If(Settings(Sites.Instagram).InstagramLastApplyingValue, 0)} minutes." & vbCr & + "What do you want to do?", "Waiting for Instagram download...", + { + New MsgBoxButton("Wait") With {.ToolTip = "Wait and ask again when the error is found."}, + New MsgBoxButton("Wait (disable current") With {.ToolTip = "Wait and skip future prompts while downloading the current profile."}, + New MsgBoxButton("Abort") With {.ToolTip = "Abort operation"}, + New MsgBoxButton("Wait (disable all)") With {.ToolTip = "Wait and skip future prompts while downloading the current session."} + }, + vbExclamation) With {.ButtonsPerRow = 2, .DefaultButton = 0, .CancelButton = 2} + Select Case MsgBoxE(m).Index + Case 1 : WaitNotificationMode = WNM.SkipCurrent + Case 2 : Throw New OperationCanceledException("Instagram download operation aborted") With {.HelpLink = InstAborted} + Case 3 : WaitNotificationMode = WNM.SkipAll + Case Else : WaitNotificationMode = WNM.SkipTemp + End Select + End If + If Not ProgressTempSet Then Progress.InformationTemporary = $"Waiting until {Settings(Sites.Instagram).GetInstaWaitDate().ToString(ParsersDataDateProvider)}" + ProgressTempSet = True + Return False + Else + Return True + End If + End With + End Function + Private Sub ReconfigureAwaiter() + If WaitNotificationMode = WNM.SkipTemp Then WaitNotificationMode = WNM.Notify + If Caught429 Then Caught429 = False : RequestsCount = 0 + ProgressTempSet = False + End Sub + Private Sub NextRequest(ByVal StartWait As Boolean) + With Settings(Sites.Instagram) + If StartWait And (RequestsCount Mod .RequestsWaitTimerTaskCount.Value) = 0 Then Thread.Sleep(.RequestsWaitTimer) + If RequestsCount >= MaxPostsCount - 5 Then Thread.Sleep(.SleepTimerOnPostsLimit) + End With + End Sub +#End Region Private Overloads Sub DownloadData(ByVal Cursor As String, ByVal Token As CancellationToken) Dim URL$ = String.Empty + Dim _DownloadComplete As Boolean = False + LastCursor = Cursor Try - Dim n As EContainer, nn As EContainer, node As EContainer - Dim HasNextPage As Boolean = False - Dim EndCursor$ = String.Empty - Dim PostID$ = String.Empty, PostDate$ = String.Empty + Do While Not _DownloadComplete + If Not Ready() Then Thread.Sleep(10000) : ThrowAny(Token) : Continue Do + ReconfigureAwaiter() - 'Check environment - If Cursor.IsEmptyString And _InstaHash.IsEmptyString Then _InstaHash = Settings(Sites.Instagram).InstaHash - If _InstaHash.IsEmptyString Then Throw New ArgumentNullException("InstHash", "Query hash is null") - If ID.IsEmptyString Then GetUserId() - If ID.IsEmptyString Then Throw New ArgumentException("User ID is not detected", "ID") + Try + Dim n As EContainer, nn As EContainer, node As EContainer + Dim HasNextPage As Boolean = False + Dim EndCursor$ = String.Empty + Dim PostID$ = String.Empty, PostDate$ = String.Empty - 'Create query - Dim vars$ = "{""id"":" & ID & ",""first"":12,""after"":""" & Cursor & """}" - vars = SymbolsConverter.ASCII.EncodeSymbolsOnly(vars) - URL = $"https://www.instagram.com/graphql/query/?query_hash={_InstaHash}&variables={vars}" + NextRequest(True) - 'Get response - Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException) - Settings(Sites.Instagram).InstagramTooManyRequests(False) - ThrowAny(Token) + 'Check environment + If Cursor.IsEmptyString And _InstaHash.IsEmptyString Then _ + _InstaHash = If(IsSavedPosts, Settings(Sites.Instagram).InstaHash_SP, Settings(Sites.Instagram).InstaHash).Value + If _InstaHash.IsEmptyString Then Throw New ArgumentNullException(IIf(IsSavedPosts, "InstaHashSavedPosts", "InstaHash"), "Query hash is null") + If ID.IsEmptyString Then GetUserId() + If ID.IsEmptyString Then Throw New ArgumentException("User ID is not detected", "ID") - 'Data - If Not r.IsEmptyString Then - Using j As EContainer = JsonDocument.Parse(r).XmlIfNothing - n = j.ItemF({"data", "user", 0}).XmlIfNothing - If n.Count > 0 Then - If n.Contains("page_info") Then - With n("page_info") - HasNextPage = .Value("has_next_page").FromXML(Of Boolean)(False) - EndCursor = .Value("end_cursor") - End With - End If - n = n("edges").XmlIfNothing - If n.Count > 0 Then - For Each nn In n - ThrowAny(Token) - node = nn(0).XmlIfNothing + 'Create query + Dim vars$ = "{""id"":" & ID & ",""first"":50,""after"":""" & Cursor & """}" + vars = SymbolsConverter.ASCII.EncodeSymbolsOnly(vars) + URL = $"https://www.instagram.com/graphql/query/?query_hash={_InstaHash}&variables={vars}" - PostID = node.Value("id") - If Not PostID.IsEmptyString And _TempPostsList.Contains(PostID) Then Exit Sub - _TempPostsList.Add(PostID) - PostDate = node.Value("taken_at_timestamp") + 'Get response + Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException) + Settings(Sites.Instagram).InstagramTooManyRequests(False) + RequestsCount += 1 + ThrowAny(Token) - ObtainMedia(node, PostID, PostDate) - Next - End If + 'Data + If Not r.IsEmptyString Then + Using j As EContainer = JsonDocument.Parse(r).XmlIfNothing + n = j.ItemF({"data", "user", 0}).XmlIfNothing + If n.Count > 0 Then + If n.Contains("page_info") Then + With n("page_info") + HasNextPage = .Value("has_next_page").FromXML(Of Boolean)(False) + EndCursor = .Value("end_cursor") + End With + End If + n = n("edges").XmlIfNothing + If n.Count > 0 Then + For Each nn In n + ThrowAny(Token) + node = nn(0).XmlIfNothing + If IsSavedPosts Then + PostID = node.Value("shortcode") + If Not PostID.IsEmptyString Then + If _TempPostsList.Contains(PostID) Then Exit Sub Else _SavedPostsIDs.Add(PostID) + End If + Else + PostID = node.Value("id") + If Not PostID.IsEmptyString And _TempPostsList.Contains(PostID) Then Exit Sub + _TempPostsList.Add(PostID) + PostDate = node.Value("taken_at_timestamp") + ObtainMedia(node, PostID, PostDate) + End If + Next + End If + Else + If j.Value("status") = "ok" AndAlso j({"data", "user"}).XmlIfNothing.Count = 0 AndAlso _TempMediaList.Count = 0 Then + Settings(Sites.Instagram).InstaHashUpdateRequired.Value = True + UserExists = False + _DownloadComplete = True + Exit Sub + End If + End If + End Using Else - If j.Value("status") = "ok" AndAlso j({"data", "user"}).XmlIfNothing.Count = 0 AndAlso _TempMediaList.Count = 0 Then - Settings(Sites.Instagram).InstaHashUpdateRequired.Value = True - UserExists = False - Exit Sub - End If + _DownloadComplete = True + Exit Sub End If - End Using - End If - If HasNextPage And Not EndCursor.IsEmptyString Then DownloadData(EndCursor, Token) - Catch oex As OperationCanceledException When Token.IsCancellationRequested - Catch dex As ObjectDisposedException When Disposed - Catch ex As Exception - If Responser.StatusCode = HttpStatusCode.NotFound Then - UserExists = False - ElseIf Responser.StatusCode = HttpStatusCode.BadRequest Then - MyMainLOG = "Instagram credentials have expired" - Settings(Sites.Instagram).InstaHashUpdateRequired.Value = True - ElseIf Responser.StatusCode = 429 Then - Settings(Sites.Instagram).InstagramTooManyRequests(True) - Else - Settings(Sites.Instagram).InstaHashUpdateRequired.Value = True - LogError(ex, $"data downloading error [{URL}]") - End If - HasError = True - Finally - _InstaHash = String.Empty + _DownloadComplete = True + If HasNextPage And Not EndCursor.IsEmptyString Then DownloadData(EndCursor, Token) + Catch oex As OperationCanceledException When Token.IsCancellationRequested + Exit Do + Catch dex As ObjectDisposedException When Disposed + Exit Do + Catch ex As Exception + If DownloadingException(ex, $"data downloading error [{URL}]") = 1 Then Continue Do Else Exit Do + End Try + Loop + Catch oex2 As OperationCanceledException When Token.IsCancellationRequested Or oex2.HelpLink = InstAborted + If oex2.HelpLink = InstAborted Then HasError = True + Catch DoEx As Exception + ProcessException(DoEx, Token, $"data downloading error [{URL}]") + End Try + End Sub + Private Sub DownloadPosts(ByVal Token As CancellationToken) + Dim URL$ = String.Empty + Dim _DownloadComplete As Boolean = False + Dim _Index% = 0 + Try + Do While Not _DownloadComplete + If Not Ready() Then Thread.Sleep(10000) : ThrowAny(Token) : Continue Do + ReconfigureAwaiter() + + Try + Dim r$ + Dim j As EContainer, jj As EContainer + Dim _MediaObtained As Boolean + If _SavedPostsIDs.Count > 0 And _Index <= _SavedPostsIDs.Count - 1 Then + Dim e As New ErrorsDescriber(EDP.ThrowException) + For i% = _Index To _SavedPostsIDs.Count - 1 + _Index = i + URL = $"https://instagram.com/p/{_SavedPostsIDs(i)}/?__a=1" + ThrowAny(Token) + NextRequest((i + 1 Mod 5) = 0) + ThrowAny(Token) + r = Responser.GetResponse(URL,, e) + Settings(Sites.Instagram).InstagramTooManyRequests(False) + RequestsCount += 1 + If Not r.IsEmptyString Then + j = JsonDocument.Parse(r) + If Not j Is Nothing Then + _MediaObtained = False + If j.Contains({"graphql", "shortcode_media"}) Then + With j({"graphql", "shortcode_media"}).XmlIfNothing + If .Count > 0 Then ObtainMedia(.Self, _SavedPostsIDs(i), String.Empty) : _MediaObtained = True + End With + End If + If Not _MediaObtained AndAlso j.Contains("items") Then + With j("items") + If .Count > 0 Then + For Each jj In .Self : ObtainMedia2(jj, _SavedPostsIDs(i)) : Next + End If + End With + End If + j.Dispose() + End If + End If + Next + _DownloadComplete = True + End If + Catch oex As OperationCanceledException When Token.IsCancellationRequested + Exit Do + Catch dex As ObjectDisposedException When Disposed + Exit Do + Catch ex As Exception + If DownloadingException(ex, $"downloading saved posts error [{URL}]") = 1 Then Continue Do Else Exit Do + End Try + Loop + Catch oex2 As OperationCanceledException When Token.IsCancellationRequested Or oex2.HelpLink = InstAborted + If oex2.HelpLink = InstAborted Then HasError = True + Catch DoEx As Exception + ProcessException(DoEx, Token, $"downloading saved posts error [{URL}]") End Try End Sub Private Sub ObtainMedia(ByVal node As EContainer, ByVal PostID As String, ByVal PostDate As String) @@ -124,6 +296,66 @@ Namespace API.Instagram CreateMedia(node) End If End Sub + Private Sub ObtainMedia2(ByVal n As EContainer, ByVal PostID As String) + Try + Dim img As Predicate(Of EContainer) = Function(_img) Not _img.Name.IsEmptyString AndAlso _img.Name.StartsWith("image_versions") AndAlso _img.Count > 0 + Dim vid As Predicate(Of EContainer) = Function(_vid) Not _vid.Name.IsEmptyString AndAlso _vid.Name.StartsWith("video_versions") AndAlso _vid.Count > 0 + Dim ss As Func(Of EContainer, Sizes) = Function(_ss) New Sizes(_ss.Value("width"), _ss.Value("url")) + If n.Count > 0 Then + Dim l As New List(Of Sizes) + Dim d As EContainer + Dim t% + '8 - gallery + '2 - one video + '1 - one picture + t = n.Value("media_type").FromXML(Of Integer)(-1) + If t >= 0 Then + Select Case t + Case 1 + If n.Contains(img) Then + t = n.Value("media_type").FromXML(Of Integer)(-1) + If t >= 0 Then + With n.ItemF({img, "candidates"}).XmlIfNothing + If .Count > 0 Then + l.Clear() + l.ListAddList(.Select(ss), LNC) + If l.Count > 0 Then + l.Sort() + _TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, l.First.Data, PostID, Nothing), LNC) + l.Clear() + End If + End If + End With + End If + End If + Case 2 + If n.Contains(vid) Then + With n.ItemF({vid}).XmlIfNothing + If .Count > 0 Then + l.Clear() + l.ListAddList(.Select(ss), LNC) + If l.Count > 0 Then + l.Sort() + _TempMediaList.ListAddValue(MediaFromData(UTypes.Video, l.First.Data, PostID, Nothing), LNC) + l.Clear() + End If + End If + End With + End If + Case 8 + With n("carousel_media").XmlIfNothing + If .Count > 0 Then + For Each d In .Self : ObtainMedia2(d, PostID) : Next + End If + End With + End Select + End If + l.Clear() + End If + Catch ex As Exception + ErrorsDescriber.Execute(EDP.SendInLog, ex, "API.Instagram.GetGallery") + End Try + End Sub Private Sub GetUserId() Try Dim r$ = Responser.GetResponse($"https://www.instagram.com/{Name}/?__a=1",, EDP.ThrowException) @@ -136,106 +368,71 @@ Namespace API.Instagram If Responser.StatusCode = HttpStatusCode.NotFound Or Responser.StatusCode = HttpStatusCode.BadRequest Then Throw ex Else - LogError(ex, "get instagram user id") + LogError(ex, "get Instagram user id") End If End Try End Sub Protected Overrides Sub ReparseVideo(ByVal Token As CancellationToken) End Sub Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken) - Try - Dim i% - Dim dCount% = 0, dTotal% = 0 - ThrowAny(Token) - If _ContentNew.Count > 0 Then - _ContentNew.RemoveAll(Function(c) c.URL.IsEmptyString) - If _ContentNew.Count > 0 Then - MyFile.Exists(SFO.Path) - Dim MyDir$ = MyFile.CutPath.PathNoSeparator - Dim vsf As Boolean = SeparateVideoFolderF - Dim f As SFile - Dim v As UserMedia - Using w As New WebClient - If vsf Then SFileShares.SFileExists($"{MyDir}\Video\", SFO.Path) - MainProgress.TotalCount += _ContentNew.Count - For i = 0 To _ContentNew.Count - 1 - ThrowAny(Token) - v = _ContentNew(i) - v.State = UStates.Tried - If v.File.IsEmptyString Then - f = v.URL - Else - f = v.File - End If - f.Separator = "\" - f.Path = MyDir - - If v.URL_BASE.IsEmptyString Then v.URL_BASE = v.URL - - If Not v.File.IsEmptyString AndAlso Not v.URL_BASE.IsEmptyString Then - Try - If v.Type = UTypes.Video And vsf Then f.Path = $"{f.PathWithSeparator}Video" - w.DownloadFile(v.URL_BASE, f.ToString) - Select Case v.Type - Case UTypes.Video : DownloadedVideos += 1 : _CountVideo += 1 - Case UTypes.Picture : DownloadedPictures += 1 : _CountPictures += 1 - End Select - v.File = ChangeFileNameByProvider(f, v) - v.State = UStates.Downloaded - Catch wex As Exception - ErrorDownloading(f, v.URL_BASE) - End Try - Else - v.State = UStates.Skipped - End If - _ContentNew(i) = v - If DownloadTopCount.HasValue AndAlso dCount >= DownloadTopCount.Value Then - MainProgress.Perform(_ContentNew.Count - dTotal) - Exit Sub - Else - dTotal += 1 - MainProgress.Perform() - End If - Next - End Using - End If - End If - Catch oex As OperationCanceledException When Token.IsCancellationRequested - Catch dex As ObjectDisposedException When Disposed - Catch ex As Exception - LogError(ex, "content downloading error") - HasError = True - End Try + DownloadContentDefault(Token) End Sub + ''' + '''
+ ''' 1 - continue + '''
+ Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False) As Integer + If Responser.StatusCode = HttpStatusCode.NotFound Then + UserExists = False + ElseIf Responser.StatusCode = HttpStatusCode.BadRequest Then + HasError = True + MyMainLOG = "Instagram credentials have expired" + Settings(Sites.Instagram).InstaHashUpdateRequired.Value = True + ElseIf Responser.StatusCode = 429 Then + With Settings(Sites.Instagram) + Dim WaiterExists As Boolean = .InstagramLastApplyingValue.HasValue + .InstagramTooManyRequests(True) + If Not WaiterExists Then .InstagramLastApplyingValue = 2 + End With + Caught429 = True + MyMainLOG = $"Number of requests before error 429: {RequestsCount}" + Return 1 + Else + Settings(Sites.Instagram).InstaHashUpdateRequired.Value = True + If Not FromPE Then LogError(ex, Message) : HasError = True + Return 0 + End If + Return 2 + End Function Private Shared Function MediaFromData(ByVal t As UTypes, ByVal _URL As String, ByVal PostID As String, ByVal PostDate As String) As UserMedia _URL = LinkFormatterSecure(RegexReplace(_URL.Replace("\", String.Empty), LinkPattern)) Dim m As New UserMedia(_URL, t) With {.Post = New UserPost With {.ID = PostID}} If Not m.URL.IsEmptyString Then m.File = CStr(RegexReplace(m.URL, FilesPattern)) - If Not PostDate.IsEmptyString Then m.Post.Date = AConvert(Of Date)(PostDate, Declarations.DateProvider, Nothing) Else m.Post.Date = Nothing + If Not PostDate.IsEmptyString Then m.Post.Date = AConvert(Of Date)(PostDate, DateProvider, Nothing) Else m.Post.Date = Nothing Return m End Function Friend Shared Function GetVideoInfo(ByVal URL As String) As IEnumerable(Of UserMedia) Try If Not URL.IsEmptyString AndAlso URL.Contains("instagram.com") Then - Do While Right(URL, 1) = "/" : URL = Left(URL, URL.Length - 1) : Loop - URL = $"{URL}/?__a=1" - Using t As New UserData - t.Responser = New PersonalUtilities.Tools.WEB.Response - t.Responser.Copy(Settings(Sites.Instagram).Responser) - Dim r$ = t.Responser.GetResponse(URL,, EDP.ThrowException) - If Not r.IsEmptyString Then - Using j As EContainer = JsonDocument.Parse(r).XmlIfNothing - Dim node As EContainer = j({"graphql", "shortcode_media"}).XmlIfNothing - If node.Count > 0 Then t.ObtainMedia(node, String.Empty, String.Empty) - End Using - End If - If t._TempMediaList.Count > 0 Then Return ListAddList(Nothing, t._TempMediaList) - End Using + Dim PID$ = RegexReplace(URL, New RegexStructure(".*?instagram.com/p/([_\w\d]+)", 1)) + If Not PID.IsEmptyString Then + Using t As New UserData + t.Responser = New PersonalUtilities.Tools.WEB.Response + t.Responser.Copy(Settings(Sites.Instagram).Responser) + t._SavedPostsIDs.Add(PID) + t.DownloadPosts(Nothing) + Return ListAddList(Nothing, t._TempMediaList) + End Using + End If End If Return Nothing Catch ex As Exception Return ErrorsDescriber.Execute(EDP.ShowMainMsg + EDP.SendInLog, ex, "Instagram standalone downloader: fetch media error") End Try End Function + Protected Overrides Sub Dispose(ByVal disposing As Boolean) + If Not disposedValue And disposing Then _SavedPostsIDs.Clear() + MyBase.Dispose(disposing) + End Sub End Class End Namespace \ No newline at end of file diff --git a/SCrawler/API/Reddit/Channel.vb b/SCrawler/API/Reddit/Channel.vb index 800a745..55f6d44 100644 --- a/SCrawler/API/Reddit/Channel.vb +++ b/SCrawler/API/Reddit/Channel.vb @@ -19,6 +19,8 @@ Namespace API.Reddit Private Const Name_ID As String = "ID" Private Const Name_Date As String = "Date" Private Const Name_PostsNode As String = "Posts" + Private Const Name_UsersAdded As String = "UsersAdded" + Private Const Name_PostsDownloaded As String = "PostsDownloaded" #End Region Friend Const DefaultDownloadLimitCount As Integer = 1000 #Region "IUserData Support" @@ -311,6 +313,31 @@ Namespace API.Reddit End Get End Property Private ReadOnly Property Range As RangeSwitcher(Of UserPost) + Friend ReadOnly Property CountOfAddedUsers As List(Of Integer) + Friend ReadOnly Property CountOfLoadedPostsPerSession As List(Of Integer) + Private _FirstUserAdded As Boolean = False + Friend Sub UserAdded(Optional ByVal IsAdded As Boolean = True) + If Not _FirstUserAdded Then CountOfAddedUsers.Add(0) : _FirstUserAdded = True + Dim v% = CountOfAddedUsers.Last + v += IIf(IsAdded, 1, -1) + If v < 0 Then v = 0 + CountOfAddedUsers(CountOfAddedUsers.Count - 1) = v + End Sub + Friend Function GetChannelStats(ByVal Extended As Boolean) As String + Dim s$ = String.Empty + Dim p As New ANumbers With {.FormatOptions = ANumbers.Options.GroupIntegral} + If Extended Then + s.StringAppendLine($"Users added from this channel: {CountOfAddedUsers.Sum.NumToString(p)}") + s.StringAppendLine($"Users added from this channel (avg): {CountOfAddedUsers.DefaultIfEmpty(0).Average.RoundDown.NumToString(p)}") + s.StringAppendLine($"Users added from this channel (session): {CountOfAddedUsers.LastOrDefault.NumToString(p)}") + s.StringAppendLine($"Posts downloaded (avg): {CountOfLoadedPostsPerSession.DefaultIfEmpty(0).Average.RoundUp.NumToString(p)}") + s.StringAppendLine($"Posts downloaded (session): {CountOfLoadedPostsPerSession.LastOrDefault.NumToString(p)}") + Else + s.StringAppend($"Users: {CountOfAddedUsers.Sum.NumToString(p)} (avg: {CountOfAddedUsers.DefaultIfEmpty(0).Average.RoundDown.NumToString(p)}; s: {CountOfAddedUsers.LastOrDefault.NumToString(p)})") + s.StringAppend($"Posts: {CountOfLoadedPostsPerSession.DefaultIfEmpty(0).Average.RoundUp.NumToString(p)} (s: {CountOfLoadedPostsPerSession.LastOrDefault.NumToString(p)})", "; ") + End If + Return s + End Function #Region "Limits Support" Private _DownloadLimitCount As Integer? = Nothing Friend Property DownloadLimitCount As Integer? Implements IChannelLimits.DownloadLimitCount @@ -379,6 +406,8 @@ Namespace API.Reddit Posts = New List(Of UserPost) PostsLatest = New List(Of UserPost) Range = New RangeSwitcher(Of UserPost)(Me) + CountOfAddedUsers = New List(Of Integer) + CountOfLoadedPostsPerSession = New List(Of Integer) End Sub Friend Sub New(ByVal f As SFile) Me.New @@ -422,7 +451,9 @@ Namespace API.Reddit } d.SetLimit(Me) d.DownloadData(Token) + Dim b% = Posts.Count Posts.ListAddList(d.GetNewChannelPosts(), LAP.NotContainsOnly) + If Posts.Count - b > 0 Then CountOfLoadedPostsPerSession.Add(Posts.Count - b) Posts.Sort() LatestParsedDate = If(Posts.FirstOrDefault(Function(pp) pp.Date.HasValue).Date, LatestParsedDate) End Using @@ -525,6 +556,8 @@ Namespace API.Reddit Name = x.Value(Name_Name) ID = x.Value(Name_ID) LatestParsedDate = AConvert(Of Date)(x.Value(Name_Date), XMLDateProvider, Nothing) + CountOfAddedUsers.ListAddList(x.Value(Name_UsersAdded).StringToList(Of Integer)("|"), LAP.ClearBeforeAdd) + CountOfLoadedPostsPerSession.ListAddList(x.Value(Name_PostsDownloaded).StringToList(Of Integer)("|"), LAP.ClearBeforeAdd) If Not PartialLoad Then With x(Name_PostsNode).XmlIfNothing If .Count > 0 Then .ForEach(Sub(ee) PostsLatest.Add(New UserPost With { @@ -549,6 +582,8 @@ Namespace API.Reddit LatestParsedDate = tmpPostList.FirstOrDefault(Function(pd) pd.Date.HasValue).Date x.Add(Name_Date, AConvert(Of String)(LatestParsedDate, XMLDateProvider, String.Empty)) x.Add(Name_PostsNode, String.Empty) + x.Add(Name_UsersAdded, CountOfAddedUsers.ListToString(, "|")) + x.Add(Name_PostsDownloaded, CountOfLoadedPostsPerSession.ListToString(, "|")) With x(Name_PostsNode) tmpPostList.Take(200).ToList.ForEach(Sub(p) .Add(New EContainer("Post", String.Empty, @@ -578,6 +613,8 @@ Namespace API.Reddit If disposing Then Posts.Clear() PostsLatest.Clear() + CountOfAddedUsers.Clear() + CountOfLoadedPostsPerSession.Clear() Range.Dispose() If Not Instance Is Nothing Then Instance.Dispose() If CachePath.Exists(SFO.Path, False) Then CachePath.Delete(SFO.Path, False, False, EDP.SendInLog) diff --git a/SCrawler/API/Reddit/ChannelsCollection.vb b/SCrawler/API/Reddit/ChannelsCollection.vb index c85feba..67d34d6 100644 --- a/SCrawler/API/Reddit/ChannelsCollection.vb +++ b/SCrawler/API/Reddit/ChannelsCollection.vb @@ -74,7 +74,6 @@ Namespace API.Reddit Next End If Throw New ArgumentException($"Channel ID [{ChannelID}] does not found in channels collection", "ChannelID") With {.HelpLink = 1} - 'Return Nothing End Get End Property Friend Sub DownloadData(ByVal Token As CancellationToken, Optional ByVal SkipExists As Boolean = True, @@ -111,7 +110,7 @@ Namespace API.Reddit Return Count > 0 AndAlso Channels.Contains(_Item) End Function Friend Function Remove(ByVal _Item As Channel) As Boolean Implements ICollection(Of Channel).Remove - If Count > 0 Then + If Count > 0 And Not _Item Is Nothing Then Dim i% = Channels.IndexOf(_Item) If i >= 0 Then With Channels(i) : .Delete() : .Dispose() : End With diff --git a/SCrawler/API/Reddit/Declarations.vb b/SCrawler/API/Reddit/Declarations.vb index 1c83eb5..821efa8 100644 --- a/SCrawler/API/Reddit/Declarations.vb +++ b/SCrawler/API/Reddit/Declarations.vb @@ -16,9 +16,8 @@ Namespace API.Reddit Friend ReadOnly VideoRegEx As New RegexStructure("http.{0,1}://[^" & Chr(34) & "]+?mp4", True, False) Friend ReadOnly DateProvider As New JsonDate Friend ReadOnly DateProviderChannel As New JsonDateChannel - Private ReadOnly EUR_PROVIDER As New ANumbers(ANumbers.Modes.EUR) + Private ReadOnly EUR_PROVIDER As New ANumbers(ANumbers.Cultures.EUR) Friend Class JsonDate : Implements ICustomProvider - ''' Friend Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider, Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert Return ADateTime.ParseUnicodeJS(Value, NothingArg, e) @@ -28,7 +27,6 @@ Namespace API.Reddit End Function End Class Friend Class JsonDateChannel : Implements ICustomProvider - ''' Friend Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider, Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert Return ADateTime.ParseUnicode(AConvert(Of Integer)(Value, EUR_PROVIDER, Value), NothingArg, e) diff --git a/SCrawler/API/Reddit/M3U8.vb b/SCrawler/API/Reddit/M3U8.vb index 62d386e..1c93797 100644 --- a/SCrawler/API/Reddit/M3U8.vb +++ b/SCrawler/API/Reddit/M3U8.vb @@ -74,7 +74,7 @@ Namespace API.Reddit ConcatFile.Extension = "mp4" CachePath = $"{f.PathWithSeparator}_Cache\{SFile.GetDirectories($"{f.PathWithSeparator}_Cache\",,, EDP.ReturnValue).ListIfNothing.Count + 1}\" If CachePath.Exists(SFO.Path) Then - Dim p As New SFileNumbers(ConcatFile.Name,,, New ANumbers(ANumbers.Modes.USA) With {.GroupSeparator = String.Empty, .FormatMode = ANumbers.Formats.General}) + Dim p As New SFileNumbers(ConcatFile.Name,,, New ANumbers With {.Format = ANumbers.Formats.General}) ConcatFile = SFile.Indexed_IndexFile(ConcatFile,, p, EDP.ReturnValue) Dim i% Dim eFiles As New List(Of SFile) diff --git a/SCrawler/API/Reddit/ProfileSaved.vb b/SCrawler/API/Reddit/ProfileSaved.vb index f851fc0..1622ecd 100644 --- a/SCrawler/API/Reddit/ProfileSaved.vb +++ b/SCrawler/API/Reddit/ProfileSaved.vb @@ -7,29 +7,23 @@ ' This program is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY Imports SCrawler.API.Base +Imports System.Threading +Imports PersonalUtilities.Forms.Toolbars Namespace API.Reddit Friend NotInheritable Class ProfileSaved + Friend Shared ReadOnly Property DataPath As SFile = $"{Settings(Sites.Reddit).Path.PathNoSeparator}\!Saved\" Private Sub New() End Sub - Friend Shared Sub Download(ByRef Toolbar As StatusStrip, ByRef PR As ToolStripProgressBar) + Friend Shared Sub Download(ByRef Bar As MyProgress, ByVal Token As CancellationToken) Try - Dim Bar = New PersonalUtilities.Forms.Toolbars.MyProgress(Toolbar, PR, Nothing) - Dim u As New UserInfo(Settings(Sites.Reddit).SavedPostsUserName.Value, Sites.Reddit) With { - .IsChannel = True, - .SpecialPath = $"{Settings(Sites.Reddit).Path.PathWithSeparator}\!Saved\" - } + Dim u As New UserInfo(Settings(Sites.Reddit).SavedPostsUserName.Value, Sites.Reddit) With {.IsChannel = True, .SpecialPath = DataPath} u.UpdateUserFile() - Using user As IUserData = UserDataBase.GetInstance(u) + Using user As New UserData(u,, False) DirectCast(user.Self, UserDataBase).IsSavedPosts = True - Bar.Enabled = True - DirectCast(user.Self, UserData).Progress = Bar + user.Progress = Bar If Not user.FileExists Then user.UpdateUserInformation() - user.DownloadData(Nothing) - Dim m As New MMessage("Reddit saved posts download complete", "Saved posts downloading", {"OK", "Open folder"}) - m.Text.StringAppendLine($"Downloaded images: {user.DownloadedPictures}") - m.Text.StringAppendLine($"Downloaded videos: {user.DownloadedVideos}") - If MsgBoxE(m) = 1 Then u.File.CutPath.Open(SFO.Path) - Bar.Enabled = False + user.DownloadData(Token) + Bar.InformationTemporary = $"Images: {user.DownloadedPictures}; Videos: {user.DownloadedVideos}" End Using Catch ex As Exception ErrorsDescriber.Execute(EDP.SendInLog, ex, "[API.Reddit.ProfileSaved.Download]") diff --git a/SCrawler/API/Reddit/UserData.vb b/SCrawler/API/Reddit/UserData.vb index b78e7b5..83747aa 100644 --- a/SCrawler/API/Reddit/UserData.vb +++ b/SCrawler/API/Reddit/UserData.vb @@ -7,7 +7,6 @@ ' This program is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY Imports PersonalUtilities.Functions.XML -Imports PersonalUtilities.Forms.Toolbars Imports PersonalUtilities.Tools.ImageRenderer Imports PersonalUtilities.Tools.WebDocuments.JSON Imports System.Net @@ -50,15 +49,6 @@ Namespace API.Reddit Select c.Post) Else Return Nothing End Function #End Region - Private _Progress As MyProgress - Friend Property Progress As MyProgress - Get - If _Progress Is Nothing Then Return MainProgress Else Return _Progress - End Get - Set(ByVal p As MyProgress) - _Progress = p - End Set - End Property #Region "Initializers" ''' Video downloader initializer Private Sub New() @@ -74,9 +64,13 @@ Namespace API.Reddit If _LoadUserInformation Then LoadUserInformation() End Sub #End Region +#Region "Load and Update user info" + Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean) + End Sub +#End Region #Region "Download Overrides" Friend Overrides Sub DownloadData(ByVal Token As CancellationToken) - If IsChannel AndAlso Not ChannelInfo.IsRegularChannel Then + If Not IsSavedPosts AndAlso (IsChannel AndAlso Not ChannelInfo.IsRegularChannel) Then If Not Responser Is Nothing Then Responser.Dispose() Responser = New PersonalUtilities.Tools.WEB.Response Responser.Copy(Settings(Sites.Reddit).Responser) @@ -92,7 +86,9 @@ Namespace API.Reddit End Sub Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) _TotalPostsDownloaded = 0 - If IsChannel Then + If IsSavedPosts Then + DownloadDataChannel(String.Empty, Token) + ElseIf IsChannel Then If ChannelInfo.IsRegularChannel Then ChannelPostsNames.ListAddList(_TempPostsList, LNC) If ChannelPostsNames.Count > 0 Then @@ -129,7 +125,7 @@ Namespace API.Reddit URL = $"https://gateway.reddit.com/desktopapi/v1/user/{Name}/posts?rtj=only&allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort=new&t=all&layout=classic" ThrowAny(Token) - Dim r$ = GetSiteResponse(URL) + Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException) If Not r.IsEmptyString Then Using w As EContainer = JsonDocument.Parse(r).XmlIfNothing If w.Count > 0 Then @@ -203,17 +199,8 @@ Namespace API.Reddit If POST.IsEmptyString And ExistsDetected Then Exit Sub If Not PostID.IsEmptyString And NewPostDetected Then DownloadDataUser(PostID, Token) End If - Catch oex As OperationCanceledException When Token.IsCancellationRequested - Catch dex As ObjectDisposedException When Disposed Catch ex As Exception - If ex.HelpLink = NonExistendUserHelp Then - UserExists = False - ElseIf ex.HelpLink = SuspendedUserHelp Then - UserSuspended = True - Else - LogError(ex, $"data downloading error [{URL}]") - HasError = True - End If + ProcessException(ex, Token, $"data downloading error [{URL}]") End Try End Sub Private Sub DownloadDataChannel(ByVal POST As String, ByVal Token As CancellationToken) @@ -234,7 +221,7 @@ Namespace API.Reddit End If ThrowAny(Token) - Dim r$ = GetSiteResponse(URL) + Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException) If Not r.IsEmptyString Then Using w As EContainer = JsonDocument.Parse(r).XmlIfNothing If w.Count > 0 Then @@ -296,17 +283,8 @@ Namespace API.Reddit If POST.IsEmptyString And ExistsDetected Then Exit Sub If Not PostID.IsEmptyString And NewPostDetected Then DownloadDataChannel(PostID, Token) End If - Catch oex As OperationCanceledException When Token.IsCancellationRequested - Catch dex As ObjectDisposedException When Disposed Catch ex As Exception - If ex.HelpLink = NonExistendUserHelp Then - UserExists = False - ElseIf ex.HelpLink = SuspendedUserHelp Then - UserSuspended = True - Else - LogError(ex, $"channel data downloading error [{URL}]") - HasError = True - End If + ProcessException(ex, Token, $"channel data downloading error [{URL}]") End Try End Sub #End Region @@ -366,8 +344,7 @@ Namespace API.Reddit End If Return added Catch ex As Exception - LogError(ex, "gallery parsing error") - HasError = True + ProcessException(ex, Nothing, "gallery parsing error", False) Return False End Try End Function @@ -382,7 +359,7 @@ Namespace API.Reddit ThrowAny(Token) If _TempMediaList(i).Type = UTypes.VideoPre Then m = _TempMediaList(i) - r = GetSiteResponse(m.URL, e) + r = Responser.GetResponse(m.URL,, e) _TempMediaList(i) = New UserMedia If Not r.IsEmptyString Then v = RegexReplace(r, VideoRegEx) @@ -395,10 +372,8 @@ Namespace API.Reddit End If Next End If - Catch oex As OperationCanceledException When Token.IsCancellationRequested - Catch dex As ObjectDisposedException When Disposed Catch ex As Exception - LogError(ex, "video reparsing error") + ProcessException(ex, Token, "video reparsing error", False) End Try End Sub Friend Shared Function GetVideoInfo(ByVal URL As String) As IEnumerable(Of UserMedia) @@ -433,7 +408,7 @@ Namespace API.Reddit Try If Not URL.IsEmptyString AndAlso URL.StringContains({".jpg", ".png", ".jpeg"}) Then Dim f As SFile = CStr(RegexReplace(URL, FilesPattern)) - Return Not f.IsEmptyString And Not f.File.IsEmptyString + Return Not f.File.IsEmptyString End If Return False Catch ex As Exception @@ -454,7 +429,7 @@ Namespace API.Reddit If _ContentNew.Count > 0 Then MyFile.Exists(SFO.Path) Dim MyDir$ - If IsChannel And SaveToCache Then + If Not IsSavedPosts AndAlso (IsChannel And SaveToCache) Then MyDir = ChannelInfo.CachePath.PathNoSeparator Else MyDir = MyFile.CutPath.PathNoSeparator @@ -605,29 +580,20 @@ Namespace API.Reddit HasError = True End Try End Sub - Protected Function GetSiteResponse(ByVal URL As String, Optional ByVal e As ErrorsDescriber = Nothing) As String - Try - Return Responser.GetResponse(URL,, EDP.ThrowException) - Catch ex As Exception - HasError = True - Dim OptText$ = String.Empty - If Not e.Exists Then - Dim ee As EDP = EDP.SendInLog - If Responser.StatusCode = HttpStatusCode.NotFound Then - ee = EDP.ThrowException - OptText = ": USER NOT FOUND" - ex.HelpLink = NonExistendUserHelp - ElseIf Responser.StatusCode = HttpStatusCode.Forbidden Then - ee = EDP.ThrowException - OptText = ": USER PROFILE SUSPENDED" - ex.HelpLink = SuspendedUserHelp - Else - ee += EDP.ReturnValue - End If - e = New ErrorsDescriber(ee) - End If - Return ErrorsDescriber.Execute(e, ex, $"[{Site} - {Name}: GetSiteResponse([{URL}])]{OptText}", String.Empty) - End Try + Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False) As Integer + If Responser.StatusCode = HttpStatusCode.NotFound Then + UserExists = False + ElseIf Responser.StatusCode = HttpStatusCode.Forbidden Then + UserSuspended = True + ElseIf Responser.StatusCode = HttpStatusCode.BadGateway Or + Responser.StatusCode = HttpStatusCode.ServiceUnavailable Or + Responser.StatusCode = HttpStatusCode.GatewayTimeout Then + MyMainLOG = "Reddit is currently unavailable" + Else + If Not FromPE Then LogError(ex, Message) : HasError = True + Return 0 + End If + Return 1 End Function Protected Overrides Sub Dispose(ByVal disposing As Boolean) If Not disposedValue And disposing Then ChannelPostsNames.Clear() : _ExistsUsersNames.Clear() diff --git a/SCrawler/API/Redgifs/Declarations.vb b/SCrawler/API/Redgifs/Declarations.vb new file mode 100644 index 0000000..4747d85 --- /dev/null +++ b/SCrawler/API/Redgifs/Declarations.vb @@ -0,0 +1,22 @@ +' Copyright (C) 2022 Andy +' 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.RedGifs + Friend Module Declarations + Friend ReadOnly DateProvider As New JsonDate + Friend Class JsonDate : Implements ICustomProvider + Friend Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider, + Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert + Return ADateTime.ParseUnicode(Value, NothingArg, e) + End Function + Private Function GetFormat(ByVal FormatType As Type) As Object Implements IFormatProvider.GetFormat + Throw New NotImplementedException("GetFormat is not available in this context") + End Function + End Class + End Module +End Namespace \ No newline at end of file diff --git a/SCrawler/API/Redgifs/UserData.vb b/SCrawler/API/Redgifs/UserData.vb new file mode 100644 index 0000000..37af32c --- /dev/null +++ b/SCrawler/API/Redgifs/UserData.vb @@ -0,0 +1,90 @@ +' Copyright (C) 2022 Andy +' This program is free software: you can redistribute it and/or modify +' it under the terms of the GNU General Public License as published by +' the Free Software Foundation, either version 3 of the License, or +' (at your option) any later version. +' +' This program is distributed in the hope that it will be useful, +' but WITHOUT ANY WARRANTY +Imports PersonalUtilities.Functions.XML +Imports PersonalUtilities.Tools.WebDocuments.JSON +Imports System.Threading +Imports System.Net +Imports SCrawler.API.Base +Imports UTypes = SCrawler.API.Base.UserMedia.Types +Namespace API.RedGifs + Friend Class UserData : Inherits UserDataBase + Friend Overrides Property Site As Sites = Sites.RedGifs + Friend Sub New(ByVal u As UserInfo, Optional ByVal _LoadUserInformation As Boolean = True) + User = u + If _LoadUserInformation Then LoadUserInformation() + End Sub + Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean) + End Sub + Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) + DownloadData(1, Token) + End Sub + Private Overloads Sub DownloadData(ByVal Page As Integer, ByVal Token As CancellationToken) + Dim URL$ = String.Empty + Try + URL = $"https://api.redgifs.com/v2/users/{Name}/search?order=recent&page={Page}" + Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException) + Dim postDate$, postID$ + Dim pTotal% = 0 + Dim u$ + Dim ut As UTypes + If Not r.IsEmptyString Then + Using j As EContainer = JsonDocument.Parse(r).XmlIfNothing + If j.Contains("gifs") Then + pTotal = j.Value("pages").FromXML(Of Integer)(0) + For Each g As EContainer In j("gifs") + postDate = g.Value("createDate") + postID = g.Value("id") + If Not _TempPostsList.Contains(postID) Then _TempPostsList.Add(postID) Else Exit For + With g("urls") + If .ListExists Then + u = If(.Item("hd"), .Item("sd")).XmlIfNothingValue + If Not u.IsEmptyString Then + ut = UTypes.Undefined + 'Type 1: video + 'Type 2: image + Select Case g.Value("type").FromXML(Of Integer)(0) + Case 1 : ut = UTypes.Video + Case 2 : ut = UTypes.Picture + End Select + If Not ut = UTypes.Undefined Then _TempMediaList.ListAddValue(MediaFromData(ut, u, postID, postDate)) + End If + End If + End With + Next + End If + End Using + End If + If pTotal > 0 And Page < pTotal Then DownloadData(Page + 1, Token) + Catch ex As Exception + ProcessException(ex, Token, $"data downloading error [{URL}]") + End Try + End Sub + Protected Overrides Sub ReparseVideo(ByVal Token As CancellationToken) + End Sub + Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken) + DownloadContentDefault(Token) + End Sub + Private Shared Function MediaFromData(ByVal t As UTypes, ByVal _URL As String, ByVal PostID As String, ByVal PostDate As String) As UserMedia + _URL = LinkFormatterSecure(RegexReplace(_URL.Replace("\", String.Empty), LinkPattern)) + Dim m As New UserMedia(_URL, t) With {.Post = New UserPost With {.ID = PostID}} + If Not m.URL.IsEmptyString Then m.File = CStr(RegexReplace(m.URL, FilesPattern)) : m.URL_BASE = m.URL + If Not PostDate.IsEmptyString Then m.Post.Date = AConvert(Of Date)(PostDate, DateProvider, Nothing) Else m.Post.Date = Nothing + Return m + End Function + Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False) As Integer + If Responser.StatusCode = HttpStatusCode.NotFound Then + UserExists = False + Else + If Not FromPE Then LogError(ex, Message) : HasError = True + Return 0 + End If + Return 1 + End Function + End Class +End Namespace \ No newline at end of file diff --git a/SCrawler/API/Twitter/UserData.vb b/SCrawler/API/Twitter/UserData.vb index d8ce2de..2c5ae46 100644 --- a/SCrawler/API/Twitter/UserData.vb +++ b/SCrawler/API/Twitter/UserData.vb @@ -12,35 +12,10 @@ Imports PersonalUtilities.Functions.XML Imports System.Net Imports System.Threading Imports SCrawler.API.Base -Imports UStates = SCrawler.API.Base.UserMedia.States Namespace API.Twitter Friend Class UserData : Inherits UserDataBase #Region "Declarations" Friend Overrides Property Site As Sites = Sites.Twitter - Private Structure Sizes : Implements IComparable(Of Sizes) - Friend Value As Integer - Friend Name As String - Friend ReadOnly HasError As Boolean - Friend Sub New(ByVal _Value As String, ByVal _Name As String) - Try - Value = _Value - Name = _Name - Catch ex As Exception - HasError = True - End Try - End Sub - Friend Function CompareTo(ByVal Other As Sizes) As Integer Implements IComparable(Of Sizes).CompareTo - Return Value.CompareTo(Other.Value) * -1 - End Function - Friend Shared Function Reparse(ByRef Current As Sizes, ByVal Other As Sizes, ByVal LargeContained As Boolean) As Sizes - If LargeContained And Current.Name.IsEmptyString And Current.Value > Other.Value Then Current.Name = "large" - Return Current - End Function - Friend Shared Function ApplyLarge(ByRef s As Sizes) As Sizes - s.Name = "large" - Return s - End Function - End Structure #End Region #Region "Initializer" Friend Sub New(ByVal u As UserInfo, Optional ByVal _LoadUserInformation As Boolean = True) @@ -48,6 +23,10 @@ Namespace API.Twitter If _LoadUserInformation Then LoadUserInformation() End Sub #End Region +#Region "Load and Update user info" + Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean) + End Sub +#End Region #Region "Download functions" Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) DownloadData(String.Empty, Token) @@ -115,19 +94,8 @@ Namespace API.Twitter If POST.IsEmptyString And ExistsDetected Then Exit Sub If Not PostID.IsEmptyString And NewPostDetected Then DownloadData(PostID, Token) End If - Catch oex As OperationCanceledException When Token.IsCancellationRequested - Catch dex As ObjectDisposedException When Disposed Catch ex As Exception - If Responser.StatusCode = HttpStatusCode.NotFound Then - UserExists = False - ElseIf Responser.StatusCode = HttpStatusCode.Unauthorized Then - UserSuspended = True - ElseIf Responser.StatusCode = HttpStatusCode.BadRequest Then - MyMainLOG = "Twitter has invalid credentials" - Else - LogError(ex, $"data downloading error [{URL}]") - HasError = True - End If + ProcessException(ex, Token, $"data downloading error [{URL}]") End Try End Sub Friend Shared Function GetVideoInfo(ByVal URL As String) As IEnumerable(Of UserMedia) @@ -164,12 +132,12 @@ Namespace API.Twitter Next If l.Count > 0 Then l.Sort() - If l(0).Name.IsEmptyString And LargeContained Then Return "large" Else Return l(0).Name + If l(0).Data.IsEmptyString And LargeContained Then Return "large" Else Return l(0).Data End If End If Return String.Empty Catch ex As Exception - LogError(ex, "[GetPictureOption]") + LogError(ex, "[API.Twitter.UserData.GetPictureOption]") Return String.Empty End Try End Function @@ -181,7 +149,7 @@ Namespace API.Twitter If Not URL.IsEmptyString Then _TempMediaList.ListAddValue(MediaFromData(URL, PostID, PostDate), LNC) : Return True Return False Catch ex As Exception - LogError(ex, "[CheckVideoNode]") + LogError(ex, "[API.Twitter.UserData.CheckVideoNode]") Return False End Try End Function @@ -202,7 +170,7 @@ Namespace API.Twitter End If Next If l.Count > 0 Then l.RemoveAll(Function(s) s.HasError) - If l.Count > 0 Then l.Sort() : Return l(0).Name + If l.Count > 0 Then l.Sort() : Return l(0).Data End If Return String.Empty End Function @@ -222,70 +190,20 @@ Namespace API.Twitter End Function #End Region Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken) - Try - Dim i% - Dim dCount% = 0, dTotal% = 0 - ThrowAny(Token) - If _ContentNew.Count > 0 Then - _ContentNew.RemoveAll(Function(c) c.URL.IsEmptyString) - If _ContentNew.Count > 0 Then - MyFile.Exists(SFO.Path) - Dim MyDir$ = MyFile.CutPath.PathNoSeparator - Dim vsf As Boolean = SeparateVideoFolderF - Dim f As SFile - Dim v As UserMedia - Using w As New WebClient - If vsf Then SFileShares.SFileExists($"{MyDir}\Video\", SFO.Path) - MainProgress.TotalCount += _ContentNew.Count - For i = 0 To _ContentNew.Count - 1 - ThrowAny(Token) - v = _ContentNew(i) - v.State = UStates.Tried - If v.File.IsEmptyString Then - f = v.URL - Else - f = v.File - End If - f.Separator = "\" - f.Path = MyDir - - If v.URL_BASE.IsEmptyString Then v.URL_BASE = v.URL - - If Not v.File.IsEmptyString AndAlso Not v.URL_BASE.IsEmptyString Then - Try - If f.Extension = "mp4" And vsf Then f.Path = $"{f.PathWithSeparator}Video" - w.DownloadFile(v.URL_BASE, f.ToString) - Select Case f.Extension - Case "mp4" : v.Type = UserMedia.Types.Video : DownloadedVideos += 1 : _CountVideo += 1 - Case Else : v.Type = UserMedia.Types.Picture : DownloadedPictures += 1 : _CountPictures += 1 - End Select - v.File = ChangeFileNameByProvider(f, v) - v.State = UStates.Downloaded - dCount += 1 - Catch wex As Exception - ErrorDownloading(f, v.URL_BASE) - End Try - Else - v.State = UStates.Skipped - End If - _ContentNew(i) = v - If DownloadTopCount.HasValue AndAlso dCount >= DownloadTopCount.Value Then - MainProgress.Perform(_ContentNew.Count - dTotal) - Exit Sub - Else - dTotal += 1 - MainProgress.Perform() - End If - Next - End Using - End If - End If - Catch oex As OperationCanceledException When Token.IsCancellationRequested - Catch dex As ObjectDisposedException When Disposed - Catch ex As Exception - LogError(ex, "content downloading error") - HasError = True - End Try + DownloadContentDefault(Token) End Sub + Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False) As Integer + If Responser.StatusCode = HttpStatusCode.NotFound Then + UserExists = False + ElseIf Responser.StatusCode = HttpStatusCode.Unauthorized Then + UserSuspended = True + ElseIf Responser.StatusCode = HttpStatusCode.BadRequest Then + MyMainLOG = "Twitter has invalid credentials" + Else + If Not FromPE Then LogError(ex, Message) : HasError = True + Return 0 + End If + Return 1 + End Function End Class End Namespace \ No newline at end of file diff --git a/SCrawler/API/UserDataBind.vb b/SCrawler/API/UserDataBind.vb index c41ff26..6f66892 100644 --- a/SCrawler/API/UserDataBind.vb +++ b/SCrawler/API/UserDataBind.vb @@ -7,6 +7,7 @@ ' This program is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY Imports PersonalUtilities.Tools +Imports PersonalUtilities.Functions.XML Imports System.Threading Imports SCrawler.API.Base Namespace API @@ -271,6 +272,8 @@ Namespace API Friend Overrides Sub LoadContentInformation() If Count > 0 Then Collections.ForEach(Sub(c) DirectCast(c.Self, UserDataBase).LoadContentInformation()) End Sub + Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean) + End Sub Friend Overrides Property DownloadTopCount As Integer? Get If Count > 0 Then @@ -292,6 +295,9 @@ Namespace API End Sub Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken) End Sub + Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False) As Integer + Return 0 + End Function Private Sub User_OnUserUpdated(ByVal User As IUserData) Raise_OnUserUpdated() End Sub @@ -338,16 +344,16 @@ Namespace API End Sub ''' FOR SETTINGS START LOADING ONLY Friend Overloads Sub Add(ByVal u As UserInfo, Optional ByVal _LoadData As Boolean = True) - Select Case u.Site - Case Sites.Reddit : Collections.Add(New Reddit.UserData(u, _LoadData)) - Case Sites.Twitter : Collections.Add(New Twitter.UserData(u, _LoadData)) - Case Else : Exit Sub - End Select - With DirectCast(Collections.Last.Self, UserDataBase) - .CreateButtons(Count - 1) - AddHandler .BTT_CONTEXT_DELETE.Click, AddressOf BTT_CONTEXT_DELETE_Click - End With - AddHandler Collections.Last.OnUserUpdated, AddressOf User_OnUserUpdated + Collections.Add(GetInstance(u, _LoadData)) + If Not Collections.Last Is Nothing Then + With DirectCast(Collections.Last.Self, UserDataBase) + .CreateButtons(Count - 1) + AddHandler .BTT_CONTEXT_DELETE.Click, AddressOf BTT_CONTEXT_DELETE_Click + End With + AddHandler Collections.Last.OnUserUpdated, AddressOf User_OnUserUpdated + Else + Collections.RemoveAt(Count - 1) + End If End Sub Friend Sub AddRange(ByVal _Items As IEnumerable(Of IUserData)) If Not _Items Is Nothing AndAlso _Items.Count > 0 Then diff --git a/SCrawler/Channels/ChannelViewForm.vb b/SCrawler/Channels/ChannelViewForm.vb index ed1efed..da9cb3a 100644 --- a/SCrawler/Channels/ChannelViewForm.vb +++ b/SCrawler/Channels/ChannelViewForm.vb @@ -19,20 +19,26 @@ Imports CmbDefaultButtons = PersonalUtilities.Forms.Controls.Base.ActionButton.D Imports RButton = PersonalUtilities.Tools.RangeSwitcherButton.Types Friend Class ChannelViewForm : Implements IChannelLimits Friend Event OnUsersAdded(ByVal StartIndex As Integer) + Friend Event OnDownloadDone(ByVal Message As String) #Region "Appended user structure" Private Structure PendingUser Friend ID As String Friend File As SFile - Friend Sub New(ByVal _ID As String, Optional ByVal _File As SFile = Nothing) + Friend Channel As Channel + Friend Sub New(ByVal _ID As String, ByRef _Channel As Channel, Optional ByVal _File As SFile = Nothing) ID = _ID + Channel = _Channel If Settings.FromChannelCopyImageToUser Then File = _File End Sub Public Shared Widening Operator CType(ByVal _ID As String) As PendingUser - Return New PendingUser(_ID, False) + Return New PendingUser(_ID, Nothing) End Operator Public Shared Widening Operator CType(ByVal u As PendingUser) As String Return u.ToString End Operator + Friend Sub ChannelUserAdded(Optional ByVal IsAdded As Boolean = True) + If Not Channel Is Nothing Then Channel.UserAdded(IsAdded) + End Sub Public Overrides Function ToString() As String Return ID End Function @@ -53,6 +59,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits Private WithEvents OPT_LIMITS_COUNT As RadioButton Private WithEvents OPT_LIMITS_POST As RadioButton Private WithEvents OPT_LIMITS_DATE As RadioButton + Private WithEvents BTT_SHOW_STATS As ToolStripButton #End Region Private ReadOnly CProvider As ANumbers Private ReadOnly CProgress As MyProgress @@ -134,7 +141,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits InitializeComponent() MyDefs = New DefaultFormProps CProgress = New MyProgress(ToolbarBOTTOM, PR_CN, LBL_STATUS, "Downloading data") With {.PerformMod = 10, .DropCurrentProgressOnTotalChange = False} - CProvider = New ANumbers(ANumbers.Modes.USA) With {.GroupSize = 3, .DecimalDigits = 0} + CProvider = New ANumbers With {.FormatOptions = ANumbers.Options.GroupIntegral} LimitProvider = New ADateTime("dd.MM.yyyy HH:mm") PendingUsers = New List(Of PendingUser) @@ -149,7 +156,8 @@ Friend Class ChannelViewForm : Implements IChannelLimits } CMB_CHANNELS.Buttons.AddRange({CmbDefaultButtons.Refresh, CmbDefaultButtons.Add, CmbDefaultButtons.Delete, New ActionButton(CmbDefaultButtons.Up) With {.ToolTipText = "Previous item (F1)"}, - New ActionButton(CmbDefaultButtons.Down) With {.ToolTipText = "Next item (F4)"}}) + New ActionButton(CmbDefaultButtons.Down) With {.ToolTipText = "Next item (F4)"}, + CmbDefaultButtons.Info}) TXT_LIMIT = New TextBoxExtended With { .CaptionText = "Limit", .Margin = New Padding(2), @@ -168,6 +176,9 @@ Friend Class ChannelViewForm : Implements IChannelLimits OPT_LIMITS_DATE = New RadioButton With {.Text = "Date", .BackColor = Color.Transparent, .Margin = New Padding(2)} CH_HIDE_EXISTS_USERS = New CheckBox With {.Text = "Hide exists users", .BackColor = Color.Transparent, .Margin = New Padding(2), .Checked = Settings.ChannelsHideExistsUser} + BTT_SHOW_STATS = New ToolStripButton With {.Text = "Info", .Image = PersonalUtilities.My.Resources.InfoPic_32, + .DisplayStyle = ToolStripItemDisplayStyle.ImageAndText, .Alignment = ToolStripItemAlignment.Right, + .AutoToolTip = True, .ToolTipText = "Show channels statistic"} TT_MAIN.SetToolTip(CH_HIDE_EXISTS_USERS, "Hide users which already exists in collection") TT_MAIN.SetToolTip(OPT_LIMITS_COUNT, "Total posts count limit") @@ -182,8 +193,9 @@ Friend Class ChannelViewForm : Implements IChannelLimits TXT_LIMIT.GetControlHost, LBL_LIMIT_TEXT, New ToolStripSeparator, - New ToolStripControlHost(CH_HIDE_EXISTS_USERS)}) - MyRange = New RangeSwitcher(Of UserPost) With {.Selector = Function(p) Not Settings.UserExists(Sites.Reddit, p.UserID)} + New ToolStripControlHost(CH_HIDE_EXISTS_USERS), + BTT_SHOW_STATS}) + MyRange = New RangeSwitcher(Of UserPost) With {.Selector = SelectorExpression} With MyRange .Limit = ImagesInRow * ImagesRows .InsertButtons(ToolbarTOP, {RButton.Previous, RButton.Next}, 5) @@ -192,7 +204,6 @@ Friend Class ChannelViewForm : Implements IChannelLimits .BindForm(Me) .LabelNumbersProvider = CProvider .UpdateControls() - .Selector = SelectorExpression End With AddHandler Settings.ChannelsImagesColumns.OnValueChanged, AddressOf ImagesCountChanged AddHandler Settings.ChannelsImagesRows.OnValueChanged, AddressOf ImagesCountChanged @@ -225,6 +236,8 @@ Friend Class ChannelViewForm : Implements IChannelLimits OPT_LIMITS_COUNT.Dispose() OPT_LIMITS_POST.Dispose() LBL_LIMIT_TEXT.Dispose() + BTT_SHOW_STATS.Dispose() + MyRange.Dispose() PendingUsers.Clear() MyDefs.Dispose() End Sub @@ -266,9 +279,11 @@ Friend Class ChannelViewForm : Implements IChannelLimits #Region "Images refill methods" Private Sub AppendPendingUsers() If LIST_POSTS.CheckedIndices.Count > 0 Then + Dim c As Channel = GetCurrentChannel(False) + Dim lp As New ListAddParams(LAP.NotContainsOnly) With {.OnAddAction = Sub(ByVal u As PendingUser) u.ChannelUserAdded()} PendingUsers.ListAddList((From p As ListViewItem In LIST_POSTS.Items Where p.Checked - Select New PendingUser(p.Text, GetPostBySelected(CStr(p.Tag)).CachedFile)), LNC) + Select New PendingUser(p.Text, c, GetPostBySelected(CStr(p.Tag)).CachedFile)), lp) Dim a As Action = Sub() BTT_ADD_USERS.Text = $"Add ({PendingUsers.Count.ToString(CProvider)})" If ToolbarTOP.InvokeRequired Then ToolbarTOP.Invoke(a) Else a.Invoke End If @@ -324,6 +339,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits TXT_LIMIT.Enabled = False CH_HIDE_EXISTS_USERS.Enabled = False CMB_CHANNELS.Enabled(True) = False + BTT_SHOW_STATS.Enabled = False MyRange.EnableButton(RButton.Previous, False) MyRange.EnableButton(RButton.Next, False) End If @@ -337,6 +353,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits _CollectionDownloading = True Settings.Channels.SetLimit(Me) Await Task.Run(Sub() Settings.Channels.DownloadData(Token, CH_HIDE_EXISTS_USERS.Checked, CProgress)) + RaiseEvent OnDownloadDone("All channels downloaded") Token.ThrowIfCancellationRequested() c = GetCurrentChannel() Else @@ -345,6 +362,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits InvokeToken.Invoke() c.SetLimit(Me) Await Task.Run(Sub() c.DownloadData(Token, CH_HIDE_EXISTS_USERS.Checked, CProgress)) + RaiseEvent OnDownloadDone($"Channel [{c.Name}] downloaded") Token.ThrowIfCancellationRequested() End If End If @@ -377,6 +395,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits TXT_LIMIT.Enabled = True CH_HIDE_EXISTS_USERS.Enabled = True CMB_CHANNELS.Enabled(True) = True + BTT_SHOW_STATS.Enabled = True CMB_CHANNELS_ActionOnCheckedChange(CMB_CHANNELS.Checked) With MyRange .EnableButton(RButton.Previous, .Count > 0 AndAlso .CurrentIndex > 0) @@ -524,12 +543,13 @@ Friend Class ChannelViewForm : Implements IChannelLimits If Not c Is Nothing Then MyRange.ChangeSource(c, EDP.SendInLog) End Sub Private Sub CMB_CHANNELS_ActionOnButtonClick(ByVal Sender As ActionButton) Handles CMB_CHANNELS.ActionOnButtonClick + Dim c As Channel Select Case Sender.DefaultButton Case CmbDefaultButtons.Refresh : RefillChannels() Case CmbDefaultButtons.Add : AddNewChannel() Case CmbDefaultButtons.Delete Try - Dim c As Channel = GetCurrentChannel() + c = GetCurrentChannel() If Not c Is Nothing AndAlso MsgBoxE($"Do you really want to delete channel [{c}]?", MsgBoxStyle.Exclamation + MsgBoxStyle.YesNo) = 0 Then Settings.Channels.Remove(c) RefillChannels() @@ -539,6 +559,13 @@ Friend Class ChannelViewForm : Implements IChannelLimits End Try Case CmbDefaultButtons.Up : ChangeComboIndex(-1) Case CmbDefaultButtons.Down : ChangeComboIndex(1) + Case CmbDefaultButtons.Info + Try + c = GetCurrentChannel() + If Not c Is Nothing Then MsgBoxE({c.GetChannelStats(True), "Channel statistics"}) + Catch info_ex As Exception + ErrorsDescriber.Execute(EDP.LogMessageValue, info_ex, "Error on trying to show channel info") + End Try End Select End Sub Private Sub CMB_CHANNELS_ActionOnCheckedChange(ByVal Mode As Boolean) Handles CMB_CHANNELS.ActionOnCheckedChange @@ -602,6 +629,12 @@ Friend Class ChannelViewForm : Implements IChannelLimits MyRange.Update() End If End Sub + Private Sub BTT_SHOW_STATS_Click(sender As Object, e As EventArgs) Handles BTT_SHOW_STATS.Click + Using f As New ChannelsStatsForm + f.ShowDialog() + If f.DeletedChannels > 0 Then RefillChannels() + End Using + End Sub #End Region #Region "CONTEXT" Private Sub BTT_C_OPEN_USER_Click(sender As Object, e As EventArgs) Handles BTT_C_OPEN_USER.Click @@ -634,10 +667,14 @@ Friend Class ChannelViewForm : Implements IChannelLimits Dim u$ = GetPostBySelected().UserID If Not u.IsEmptyString Then Dim uRemoved As Boolean = False - If PendingUsers.Contains(u) Then PendingUsers.Remove(u) : uRemoved = True + Dim i% = PendingUsers.IndexOf(u) + If i >= 0 Then + PendingUsers(i).ChannelUserAdded(False) + PendingUsers.RemoveAt(i) + uRemoved = True + End If With LIST_POSTS If .Items.Count > 0 Then - Dim i% Dim a As Action = Sub() .Items(i).Checked = False For i = 0 To .Items.Count - 1 If .Items(i).Text = u And .Items(i).Checked Then diff --git a/SCrawler/Channels/ChannelsStatsForm.Designer.vb b/SCrawler/Channels/ChannelsStatsForm.Designer.vb new file mode 100644 index 0000000..22fa9a2 --- /dev/null +++ b/SCrawler/Channels/ChannelsStatsForm.Designer.vb @@ -0,0 +1,112 @@ +' Copyright (C) 2022 Andy +' 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 + + +Partial Friend Class ChannelsStatsForm : Inherits System.Windows.Forms.Form + + Protected Overrides Sub Dispose(ByVal disposing As Boolean) + Try + If disposing AndAlso components IsNot Nothing Then + components.Dispose() + End If + Finally + MyBase.Dispose(disposing) + End Try + End Sub + Private components As System.ComponentModel.IContainer + + Private Sub InitializeComponent() + Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer + 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(ChannelsStatsForm)) + Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() + Dim ActionButton3 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() + Dim ListColumn1 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn() + Dim ListColumn2 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn() + Me.CMB_CHANNELS = New PersonalUtilities.Forms.Controls.ComboBoxExtended() + CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer() + CONTAINER_MAIN.ContentPanel.SuspendLayout() + CONTAINER_MAIN.SuspendLayout() + CType(Me.CMB_CHANNELS, System.ComponentModel.ISupportInitialize).BeginInit() + Me.SuspendLayout() + ' + 'CONTAINER_MAIN + ' + ' + 'CONTAINER_MAIN.ContentPanel + ' + CONTAINER_MAIN.ContentPanel.Controls.Add(Me.CMB_CHANNELS) + CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(384, 261) + CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill + CONTAINER_MAIN.LeftToolStripPanelVisible = False + CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0) + CONTAINER_MAIN.Name = "CONTAINER_MAIN" + CONTAINER_MAIN.RightToolStripPanelVisible = False + CONTAINER_MAIN.Size = New System.Drawing.Size(384, 261) + CONTAINER_MAIN.TabIndex = 0 + CONTAINER_MAIN.TopToolStripPanelVisible = False + ' + 'CMB_CHANNELS + ' + ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image) + ActionButton1.Index = 0 + ActionButton1.Name = "BTT_COMBOBOX_ARROW" + ActionButton1.Visible = False + ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image) + ActionButton2.Index = 1 + ActionButton2.Name = "BTT_CLEAR" + ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image) + ActionButton3.Index = 2 + ActionButton3.Name = "BTT_DELETE" + Me.CMB_CHANNELS.Buttons.Add(ActionButton1) + Me.CMB_CHANNELS.Buttons.Add(ActionButton2) + Me.CMB_CHANNELS.Buttons.Add(ActionButton3) + Me.CMB_CHANNELS.ClearTextByButtonClear = False + ListColumn1.DisplayMember = True + ListColumn1.Name = "COL_INFO" + ListColumn1.Text = "Information" + ListColumn1.Width = -2 + ListColumn2.Name = "COL_VALUE" + ListColumn2.Text = "Channel" + ListColumn2.ValueMember = True + ListColumn2.Visible = False + Me.CMB_CHANNELS.Columns.Add(ListColumn1) + Me.CMB_CHANNELS.Columns.Add(ListColumn2) + Me.CMB_CHANNELS.Dock = System.Windows.Forms.DockStyle.Fill + Me.CMB_CHANNELS.ListCheckBoxes = True + Me.CMB_CHANNELS.ListDropDownStyle = PersonalUtilities.Forms.Controls.ComboBoxExtended.ListMode.Simple + Me.CMB_CHANNELS.ListGridVisible = True + Me.CMB_CHANNELS.ListMultiSelect = True + Me.CMB_CHANNELS.Location = New System.Drawing.Point(0, 0) + Me.CMB_CHANNELS.Name = "CMB_CHANNELS" + Me.CMB_CHANNELS.Size = New System.Drawing.Size(386, 262) + Me.CMB_CHANNELS.TabIndex = 0 + ' + 'ChannelsStatsForm + ' + Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) + Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font + Me.ClientSize = New System.Drawing.Size(384, 261) + Me.Controls.Add(CONTAINER_MAIN) + Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon) + Me.KeyPreview = True + Me.MinimizeBox = False + Me.MinimumSize = New System.Drawing.Size(400, 300) + Me.Name = "ChannelsStatsForm" + Me.ShowInTaskbar = False + Me.Text = "Channels statistics" + CONTAINER_MAIN.ContentPanel.ResumeLayout(False) + CONTAINER_MAIN.ResumeLayout(False) + CONTAINER_MAIN.PerformLayout() + CType(Me.CMB_CHANNELS, System.ComponentModel.ISupportInitialize).EndInit() + Me.ResumeLayout(False) + + End Sub + Private WithEvents CMB_CHANNELS As PersonalUtilities.Forms.Controls.ComboBoxExtended +End Class \ No newline at end of file diff --git a/SCrawler/Channels/ChannelsStatsForm.resx b/SCrawler/Channels/ChannelsStatsForm.resx new file mode 100644 index 0000000..1e95d2e --- /dev/null +++ b/SCrawler/Channels/ChannelsStatsForm.resx @@ -0,0 +1,1383 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + 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 + AAAASUVORK5CYII= + + + + + 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 + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAEb/AABG/wMARv8PAEX/IgBF/0AARf9fAEX/fQBF/5wARf+6AEX/zQBF + /90ARf/rAEX/8wBF//gARf/8AEX//ABF//gARf/zAEX/6wBF/90ARf/NAEX/ugBF/5wARf99AEX/XwBF + /0AARf8iAEb/DwBG/wMARv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH/wAAR/8DAEb/FABG/zQARf9dAEX/iwBF + /7MARf/RAEX/5wBF//QARf/6AEX//gBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//gBF//oARf/0AEX/5wBF/9EARf+zAEX/iwBF/10ARv80AEb/FABH + /wMAR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASf8AAD//AABG + /wYARv8iAEX/UwBF/4sARf/AAEX/5QBF//cARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX/9wBF/+UARf/AAEX/iwBF/1MARv8iAEb/BgA//wAASf8AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAARv8AAEb/AwBF/x4ARv9WAEX/mQBF/9MARf/0AEX//gBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf/+AEX/9ABF/9MARf+ZAEb/VgBF/x4ARv8DAEb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH/wAAJv8AAEb/DABF/zsARf+FAEX/zABF + //QARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/0AEX/zABF + /4UARf87AEb/DAAm/wAAR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH + /wAASv8AAEb/EwBF/1AARf+nAEX/5gBF//0ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//QBF/+YARf+nAEX/UABG/xMASv8AAEf/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH/wAAT/8AAEb/FABF/1oARf+3AEX/8ABF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf/wAEX/twBF/1oARv8UAE//AABH/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABI/wAAQ/8AAEX/DgBF + /1QARf+2AEX/8gBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/8gBF + /7YARf9UAEX/DgBD/wAASP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAARv8AAEb/BgBG/z4ARf+mAEX/8ABF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//AARf+mAEb/PgBG/wYARv8AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR/8AAFP/AABG/yAARf+FAEX/4wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf/jAEX/hQBG/yAAU/8AAEf/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAEb/AABG/wkARf9SAEX/wwBF//sARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/7AEX/wwBF + /1IARv8JAEb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEf/AAA8/wAARv8eAEX/igBF/+sARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/6wBF/4oARv8eADz/AABH/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG + /wAARv8DAEX/QABF/7sARf/7AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX/+wBF/7sARf9AAEf/AwBG/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARv8AAEb/CgBF/2MARf/cAEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/9wARf9jAEb/CgBG + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARf8AAEX/AABF + /xUARf+HAEX/7wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF/+8ARf+HAEX/FQBF/wAARf8AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAEf/AABD/wAARf8hAEX/oQBF//gARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //gARf+hAEX/IQBD/wAAR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH/wAAQv8AAEb/LQBF + /7UARf/8AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//wARf+1AEX/LQBB/wAAR/8AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAR/8AAD3/AABG/zMARf/AAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf/AAEb/MwA9/wAAR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEf/AAA8/wAARf83AEX/xgBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/GAEX/NwA8 + /wAAR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAABG/wAAQ/8AAEb/MwBF/8YARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/GAEb/MwBD/wAARv8AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR/8AAET/AABF/ywARf/AAEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf/AAEX/LABE/wAAR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAEX/AABF/wAARf8hAEX/tQBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf+1AEX/IQBF/wAARf8AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARf8AAEX/FQBF/6EARf/9AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//0ARf+hAEX/FQBF/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAEX/AABG/woARf+HAEX/+QBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//kARf+HAEb/CgBF + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG/wAASP8CAEX/YwBF/+4ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF/+4ARf9jAEj/AgBG/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAARv8AAEP/AABF/0AARf/cAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AET//wBE//8AQ///AEP//wBC//8AQv//AEP//wBD//8AQ///AEP//wBC//8AQv//AEP//wBD + //8ARP//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + /9wARf9AAEP/AABG/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABF/wAARf8eAEX/uwBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AET//wBD//8AQ///AUT//wZJ//8QUP//HFn//yxk//87b///SHj//1F/ + //9Xhf//W4f//1uH//9Xhf//UX///0h4//87b///K2T//xxZ//8QUP//Bkn//wFE//8AQ///AEP//wBE + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/7sARf8eAEX/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAARv8AAEf/CABF/4oARf/7AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8AQ///AEP//wNG//8RUf//L2f//1WC + //97n///n7j//7vN///Q3f//4en//+rw///x9f//9ff///b5///3+f//9/n///b5///19///8fX//+rw + ///g6f//0N3//7rM//+euP//e57//1SB//8uZv//EVH//wNG//8AQ///AEP//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX/+wBF/4oAR/8IAEb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEb/AABC/wAARf9TAEX/6wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE + //8AQ///Bkn//yNe//9Wg///i6r//7vO///h6f//9fj///7+//////////////////////////////// + ///////////////////////////////////////////////////////////////////9/v//9fj//+Hp + //+6zf//iqn//1WC//8iXf//Bkn//wBD//8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/6wBF/1MAQv8AAEb/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAARf8AAEX/IABF/8MARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBD//8CRf//HVn//1eE//+atf//1N////X3//////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////9Pf//9Pf//+ZtP//VoP//xxZ + //8CRf//AEP//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX/wwBF/yAARf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEb/AABH/wUARf+FAEX//ABF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD//8GSP//MGf//3uf + ///J1///9Pf///////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////09///x9b//3qd//8uZv//Bkj//wBD//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/8AEX/hQBG + /wUARv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABI + /wAARP8AAEb/PgBF/+IARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBD//8FR///MWj//42s///d5v///P3///////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////+/z//9zl//+Lqv//L2f//wRH//8AQ///AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/iAEX/PgBE/wAASP8AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEX/AABG/w4ARf+lAEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8BRP//JmD//4Sl///b5f///f7///// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////39///a5P//gqT//yRf + //8BRP//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf+lAEb/DgBF/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH + /wAAQv8AAEX/VABF/+8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8AQ///DU3//1+K///M2v///P3///////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////7/P//ytn//1yI//8MTf//AEP//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/+8ARf9UAEL/AABH/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEb/AABG/xQARf+1AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AET//yZf//+ZtP//8fX///////////////////// + //////////////////////////////////////////////////////////////////////////////39 + ///09///6O7//9vl///O2///xNT//77Q//++0P//w9P//87b///b5f//6O7///T3///9/f////////// + //////////////////////////////////////////////////////////////////////////////// + ////////8PT//5ez//8kXv//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF/7UARv8UAEb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG + /wAARP8AAEX/WgBF//MARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AET//wJF + //9Cdf//xNP///39//////////////////////////////////////////////////////////////// + ///////////////////9/v//7fL//8nX//+dt///dZr//1KA//84bP//JV///xtY//8VVP//ElL//xFS + //8VVP//Glj//yVf//83bP//UoD//3SZ//+dt///yNf//+zx///9/v////////////////////////// + /////////////////////////////////////////////////////////f3//8HS//9Ac///AkX//wBE + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/8wBF/1oARP8AAEb/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEX/AABF/xMARf+3AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBE//8FR///WYb//9zl//////////////////////////////// + ///////////////////////////////////////////////////4+v//y9n//4Sl//9Ddf//GVf//wZJ + //8ARP//AEP//wBD//8AQ///AEP//wBD//8ARP//AET//wBD//8AQ///AEP//wBD//8AQv//AET//wZJ + //8ZVv//QnT//4Ok///K2P//9/n///////////////////////////////////////////////////// + /////////////////////////////9rk//9Wg///BEf//wBE//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX/twBF/xMARf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH + /wAARP8AAEX/UABF//AARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//Bkj//2SN + ///m7f////////////////////////////////////////////////////////////////////////// + ///8/f//zNn//2qS//8fW///A0b//wBD//8ARP//AET//wBD//8AQv//AEP//wFF//8ER///CEr//wlL + //8JS///CEn//wRH//8BRf//AEP//wBC//8AQ///AET//wBE//8AQ///A0b//x5a//9okf//ytj///v8 + /////////////////////////////////////////////////////////////////////////////+Tr + //9hi///BUf//wBE//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/wAEX/UABE + /wAAR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEX/AABG/wwARf+nAEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wNG//9gi///6O7///////////////////////////////////// + ////////////////////////////////////////8vX//5Sw//8lX///AUT//wBD//8ARP//AEP//wJF + //8PT///KGL//0l5//9nkP//gqT//5ay//+kvP//q8H//6vB//+kvP//lrL//4Ok//9nkf//Snr//yli + //8PT///AkX//wBD//8ARP//AEP//wFE//8kXv//ka7///H1//////////////////////////////// + /////////////////////////////////////////////+bt//9diP//A0b//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf+nAEb/DABF/wAAAAAAAAAAAAAAAAAAAAAAAAAAAABI + /wAARf8AAEX/OwBF/+YARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//Tn3//+Hp + //////////////////////////////////////////////////////////////////////////////H1 + //93m///DE3//wBD//8ARP//AEP//w1O//88cP//faD//7bJ///c5f//8fX///r7//////////////// + //////////////////////////////r8///x9f//3Ob//7bK//9+of//PXH//w5O//8AQ///AET//wBD + //8LTP//dJn///D0//////////////////////////////////////////////////////////////// + /////////////+Do//9Le///AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + /+YARf87AEX/AABG/wAAAAAAAAAAAAAAAAAAAAAAAEb/AABH/wMARf+FAEX//gBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEP//zBn///P3P////////////////////////////////////////// + ////////////////////////////////////////uMv//xFQ//8AQ///AET//wpL//9MfP//qsH//+fu + ///9/f////////////////////////////////////////////////////////////////////////// + //////////////3+///o7v//rML//059//8KS///AET//wBD//8QTv//tMj///////////////////// + /////////////////////////////////////////////////////////////8za//8tZf//AEP//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//gBF/4UASP8DAEb/AAAAAAAAAAAAAAAAAAAA + AAAARf8AAEX/HgBF/8wARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8SUf//pr7///// + //////////////////////////////////////////////////////////////////////////////// + //++z///F1T//wBB//8ZVv//i6r//+vw//////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////7PH//46s + //8aV///AEL//xVT//+7zf////////////////////////////////////////////////////////// + /////////////////////////////6O8//8QUP//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX/zABG/x4ARv8AAAAAAAAAAAAAAAAAAEb/AABF/wAARf9WAEX/9ABF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AUX//2eQ///19/////////////////////////////////////////// + //////////////////////////////////////////////X4//+euP//aZH//7DF///5+/////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////+vv//7LH//9pkf//m7b///X3//////////////// + ////////////////////////////////////////////////////////////////////////8/b//2ON + //8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/0AEX/VgBF/wAARv8AAAAAAAAA + AAAARv8AAEb/BgBF/5kARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD//8kXv//zdr///// + //////////////////////////////////////////////////////////////////////////////// + //////////////7+///7/P///v////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////v8///+/v////////////////////////////////////////////////////////// + ////////////////////////////////////////ytj//yFd//8ARP//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf+ZAEb/BgBG/wAAAAAAAAAAAABF/wAARv8iAEX/0wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AUX//3ab///7/P////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///6/P//cpj//wFF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/9MARv8iAEX/AAAA + AAAAR/8AAEX/AABF/1MARf/0AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8bWP//yNf///// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////E1P//GVf//wBE//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX/9ABF/1MARf8AAEf/AABG/wAASP8DAEX/iwBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEP//1SB///z9v////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////L1//9Qfv//AEP//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/iwBI + /wMARv8AAEb/AABG/xQARf/AAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ER///k6////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////46s//8DR///AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/AAEb/FABG/wAARf8AAEb/NABF/+UARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AET//xVU///D0/////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////v9D//xNS//8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + /+UARv80AEX/AABF/wAARf9cAEX/+ABF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8AQ///LmX//+Hp + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////f5///KmP//wBD + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/+ABF/1wARf8AAEj/AwBF/4sARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBC//9Gd///8PT///////////////////////////////////// + //////////////////////////////////////////////////////////////X3///Q3f//r8T//6a+ + //+4y///3uf///v8//////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////+/z//97n//+3y///pr3//67E + ///Q3f//9ff///////////////////////////////////////////////////////////////////// + /////////////////////////////+/z//9DdP//AEL//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX/iwBI/wMARv8PAEX/swBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEP//1WD + ///2+P////////////////////////////////////////////////////////////////////////// + //////////////3+///H1v//YIv//x9b//8LTP//CEr//w5P//8uZv//gaP//+Lq//////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////+Lq//+Bo///Lmb//w5P//8ISv//C0z//x9b//9giv//x9b///39//////////////// + ////////////////////////////////////////////////////////////////////////9ff//1GA + //8AQv//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf+zAEb/DwBF/yIARf/RAEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8AQ///XIj///j6//////////////////////////////// + ///////////////////////////////////////////////////9/v//rcP//ydh//8AQ///AEP//wBE + //8ARP//AET//wBD//8ER///S3z//9bh//////////////////////////////////////////////// + ///////////////////////////////////////////////////W4f//S3v//wRH//8AQ///AET//wBE + //8ARP//AEP//wBD//8mYP//rcL///3+//////////////////////////////////////////////// + ///////////////////////////////////3+f//WIX//wBD//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF/9EARf8iAEX/QABF/+cARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD + //9Yhf//9/n///////////////////////////////////////////////////////////////////// + /////////////8fW//8nYf//AEP//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8ARP//VoP//+vx + //////////////////////////////////////////////////////////////////////////////// + ////////6/H//1aD//8ARP//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD//8nYP//x9b///// + //////////////////////////////////////////////////////////////////////////////b4 + //9Ugv//AEL//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/5wBF/0AARf9fAEX/8wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEH//0p5///y9v////////////////////////// + ///////////////////////////////////////////////////1+P//YIv//wBD//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBE//8LTP//oLn///////////////////////////////////// + //////////////////////////////////////////////////+guf//C0z//wBE//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBD//9gi///9fj///////////////////////////////////// + ////////////////////////////////////////8fX//0d2//8AQf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf/zAEX/XwBF/30ARf/6AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD + //8PT///dZr///X4//////////////////////////////////////////////////////////////// + /////////////9Dd//8fW///AEP//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD + //9Ugf//9Pf///////////////////////////////////////////////////////////////////// + ////////9Pf//1SB//8AQ///AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEP//x9b + ///Q3f////////////////////////////////////////////////////////////////////////// + ///09///dZr//xFQ//8AQ///AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//oARf99AEX/nABF + //4ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//K2T//6W9///y9v////////////////////////// + ////////////////////////////////////////////////////////r8T//wtM//8ARP//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEP//y9m///j6/////////////////////////// + ///////////////////////////////////////////////////j6///L2b//wBD//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//C0z//6/E//////////////////////////////// + ///////////////////////////////////////////////////z9v//qL///y1l//8ARP//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//gBF/5wARf+6AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AET//zBn + ///C0v////////////////////////////////////////////////////////////////////////// + //////////////////+mvv//CEr//wBE//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8AQ///JmD//97n//////////////////////////////////////////////////////////////// + /////////////97n//8mYP//AEP//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE + //8ISv//pr7///////////////////////////////////////////////////////////////////// + ////////////////////////xNT//zNp//8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/ugBF + /84ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBE//8aV///s8f///////////////////////////////////// + /////////////////////////////////////////////////////////////7jL//8PT///AET//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD//84bf//6O7///////////////////// + ////////////////////////////////////////////////////////6O7//zht//8AQ///AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AET//w9P//+4y/////////////////////////// + ////////////////////////////////////////////////////////////////////////tsr//xxY + //8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/OAEX/3QBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//Akb//3Wa + ///6+/////////////////////////////////////////////////////////////////////////// + ////////////////////////3uf//y9m//8AQ///AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEP//2mR///5+/////////////////////////////////////////////////////////// + ///////////////////5+///aZH//wBD//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8AQ///L2b//97n//////////////////////////////////////////////////////////////// + ///////////////////////////////////6/P//eZ3//wJG//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + /90ARf/rAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBE//8fW///zdr///////////////////////////////////// + ///////////////////////////////////////////////////////////////////8/f//gqP//wRH + //8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD//8aVv//vc////////////////////// + //////////////////////////////////////////////////////////////////+9z///Glb//wBD + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AET//wRH//+Co////P3///////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///Q3P//Il3//wBD//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/6wBF//MARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEP//1KA + ///09/////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////i6v//THz//wBE//8ARP//AEX//wBF//8ARf//AEX//wBF + //8AQ///Ckv//4Kk///5+v////////////////////////////////////////////////////////// + //////////////////////////////n6//+CpP//Ckv//wBD//8ARf//AEX//wBF//8ARf//AEX//wBE + //8ARP//THz//+Lq//////////////////////////////////////////////////////////////// + //////////////////////////////////////////////X4//9Wg///AEP//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf/zAEX/+ABF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//faD///////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///X4f//VoP//wpM//8AQv//AEP//wBD//8AQ///AEP//xlW//+CpP//7/T///////////////////// + /////////////////////////////////////////////////////////////////////////////+/0 + //+CpP//GVb//wBD//8AQ///AEP//wBD//8AQ///Ckz//1aD///X4f////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////4Kj//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//gARf/8AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wRH + //+UsP////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////s8f//oLn//1SB//8vZv//JmD//zht + //9okf//vc////j6//////////////////////////////////////////////////////////////// + //////////////////////////////////////////////j6//+9z///aJH//zht//8mYP//L2b//1SB + //+guf//6/H///////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////mLP//wVH//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//ABF//wARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//BEf//5ay//////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////9Pf//+Pr///e5///6O7///n7//////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////5+///6O7//97n///j6///9Pf///////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////+atf//BUj//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/8AEX/+ABF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARP//f6L///////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////4Ol//8BRf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//gARf/zAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD//9Ugv//9Pf///////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////2+P//WIT//wBD//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/8wBF/+sARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEP//yBc///O2/////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////9Hd//8jXv//AEP//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf/rAEX/3QBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//Akb//3ic///6+/////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////7/P//e5///wNG//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/90ARf/OAEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARP//G1j//7XJ//////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////7jL//8dWf//AET//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX/zgBF/7oARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//Mmn//8TU + /////////////////////////////////////////////////////////////+vw///a5P///P3///// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////+/z//9jj///q7/////////////////////////////////////////// + ///////////////////H1v//NWv//wBE//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf+6AEX/nABF + //4ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//LmX//6i////z9/////////////////////////// + //////////////z9///Q3P//Wob//y1l//+Usf//7fL///////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////+zx//+Sr///K2T//1eE + ///O2////P3////////////////////////////////////////09///q8H//zBn//8ARP//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//gBF/5wARf99AEX/+gBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8AQ///ElH//12I//+wxf//4On///P2///3+f//9fj//+rw///H1v//gKL//yli//8BRf//AEP//wtM + //9Ugv//vc7///f5//////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////b4//+7zf//UoH//wpL//8AQ///AUX//yhh//9+of//x9b//+rw///1+P//9/n///P2 + ///h6f//ssb//1+K//8TUv//AEP//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/6AEX/fQBF + /18ARf/0AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//AET//w5P//8uZv//THz//1mG + //9Tgf//O2///xlX//8DRv//AEP//wBF//8ARf//AET//wBE//8YVv//aZH//8jX///3+f////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////f5///H1v//Z5D//xdV//8ARP//AET//wBF + //8ARf//AEP//wNG//8YVv//O2///1OB//9Zhv//TXz//y9m//8PT///AET//wBE//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//MARf9fAEX/QABF/+cARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AET//wBD//8AQv//AEP//wBC//8AQ///AET//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBE//8BRP//Hlr//2WO//+6zP//8PT///////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////+/0 + //+5zP//ZI3//x1Z//8BRP//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8AQ///AEL//wBD + //8AQv//AEP//wBE//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/5wBF + /0AARf8iAEX/0QBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//AET//xRT + //9Nff//lbH//9Pf///2+P////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////9vj//9Le//+TsP//THz//xRT//8ARP//AET//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/RAEX/IgBG/w8ARf+zAEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AET//wBD//8FSP//I17//1qG//+Usf//x9b//+rw + ///6/P////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////r7///r8P//x9b//5Sw//9Zhf//I13//wVI + //8AQ///AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + /7MARv8PAEb/AwBF/4sARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8AQ///AEP//wVH//8YVv//PnH//2iR//+Sr///uMv//9fi///p7///9Pf///r7 + ///+/v/////////////////////////////////////////////+/v//+vv///P2///n7v//1uH//7nM + //+Sr///Z5D//z5x//8YVv//BUf//wBD//8AQ///AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/iwBI/wMARf8AAEX/XABF//gARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE + //8AQ///AEP//wRH//8PUP//Il3//zlu//9Qf///ZY///3id//+IqP//kq///8fW///+/v///////+7y + //+guf//iKj//3qd//9mj///Tn3//zZr//8hXP//EFD//wRH//8AQ///AEP//wBE//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //gARf9cAEX/AABF/wAARv80AEX/5QBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8AQ///AEP//wBC + //8AQ///AET//wFF//8BRf//YIr///j6////////4+v//zNp//8AQ///AET//wBD//8AQv//AEP//wBD + //8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/5QBG/zQARf8AAEb/AABG/xQARf/AAEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBC//84bf//6O7///// + ///1+P//VYL//wBC//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf/AAEb/FABG/wAARv8AAEj/AwBF/4sARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AET//xpY///M2f////////////9/of//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/4sASP8DAEb/AABH/wAARf8AAEX/UwBF + //QARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//CUv//6e+ + /////////////6rA//8KS///AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf/0AEX/UwBF/wAAR/8AAAAAAABF/wAARv8iAEX/0wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//fJ////7+////////ztv//xxZ//8ARP//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/9MARv8iAEX/AAAAAAAAAAAAAEb/AABH + /wYARf+ZAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD + //9SgP//9Pf////////p7///Om///wBD//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX/mQBH/wYARv8AAAAAAAAAAAAAR/8AAEX/AABG/1YARf/0AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEP//y5m///h6f////////j6//9hi///AEP//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//QARv9WAEX/AABH/wAAAAAAAAAAAAAA + AAAARf8AAEX/HgBF/8wARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARP//FFP//8LS/////////////4yr//8CRv//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX/zABG/x4ARv8AAAAAAAAAAAAAAAAAAAAAAABG/wAAR/8DAEX/hQBF//4ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8GSP//m7b/////////////tcn//w5P + //8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//4ARf+FAEj/AwBG/wAAAAAAAAAAAAAA + AAAAAAAAAEj/AABF/wAARf87AEX/5gBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBD//9vlv///P3////////X4v//JF7//wBD//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8AQ///Akb//wZI + //8ER///AEP//wBD//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX/5gBF/zsARf8AAEb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEX/AABG/wwARf+nAEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEL//0d4///w9P///////+/z + //9Fdv//AEL//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARP//F1X//1KA//+IqP//nrj//5Sw//9qkv//KmP//wNG//8ARP//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf+nAEb/DABF/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAR/8AAET/AABF/1EARf/wAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8AQ///JV///9nj////////+/z//22U//8AQ///AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//A0b//0V3//+6zP//8/b///// + //////////////r8///V4P//b5X//w5O//8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX/8ABF/1EARP8AAEf/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARf8AAEb/EwBF + /7cARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8PT///t8r///// + ////////mbT//wVI//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//9Nff//3eb////////////////////////////////////////09///haX//wtM + //8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf+3AEb/EwBF/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH/wAAQv8AAEX/WgBF//MARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wNG//+Prf/////////////A0f//E1L//wBE//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8AQ///JWD//8rZ//////////////// + ///////////////////////////////////v8///Wob//wBE//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX/8wBF/1oAQv8AAEf/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG + /wAARv8UAEX/tQBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEP//2ON + ///5+////////+Do//8sZf//AEP//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//92m////P3///////////////////////////////////////////////////// + //+7zf//FFP//wBE//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf+1AEb/FABG/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEf/AABC/wAARf9UAEX/7wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8AQ///PHD//+vw////////9Pf//1B///8AQ///AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8AQv//Dk3//7XJ//////////////// + /////////////////////////////////////////////+rw//88cP//AEP//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX/7wBF/1QAQv8AAEf/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAEX/AABG/w4ARf+lAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE + //8dWv//0N3////////+/v//ep3//wBE//8ARf//AEX//wBF//8ARf//AEX//wBE//8ARP//AEP//wBD + //8DRv//Dk///yNe//9Xg///3+f///////////////////////////////////////////////////// + ////////9vj//1aD//8AQ///AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf+lAEb/DgBF/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASP8AAET/AABF/z4ARf/iAEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AET//wpM//+swv////////////+lvf//CEr//wBE + //8ARP//AEP//wBC//8BRf//Ckz//xxZ//87b///Yoz//42s//+2yv//2OP///D0///+/v////////// + ///////////////////////////////////////////////////2+P//VoP//wBD//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX/4gBF/z4ARP8AAEj/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAARv8AAEb/BQBF/4UARf/8AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AUX//4Kj/////////////8rY//8ZVv//BUj//xZV//8xaP//VoP//4Ci//+rwf//z9z//+rv + ///5+v////////////////////////////////////////////////////////////////////////// + /////////////+rw//88cP//AEP//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//wARf+FAEb/BQBG/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARf8AAEb/IABF + /8MARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8AQv//V4T///b4////////7fL//5Cu + //+dt///xdX//+Tr///1+P///v7///////////////////////////////////v8///u8///5+3///z9 + ////////////////////////////////////////////////////////u83//xRT//8ARP//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX/wwBG/yAARf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH/wAAP/8AAEX/UwBF/+sARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBD//8yaf//5Ov//////////////v7///////////////////////////////////3+ + ///09///4On//8HR//+atf//bpX//0R2//9Bc///y9n///////////////////////////////////// + /////////////+/z//9ahv//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/+sARf9TAD//AABH/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG + /wAAR/8IAEX/igBF//sARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AET//xZV///F1f////////// + ///////////////////3+f//5+7//8vZ//+mvv//e57//1F///8tZf//FFP//wVI//8AQ///AEL//wBD + //9Nff//3eb////////////////////////////////////////09///haX//wtM//8ARP//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf/7AEX/igBH/wgARv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABF/wAARf8eAEX/uwBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//BEf//3ic///t8v//7fL//9Xg//+xxv//iKj//12I//83bP//Glf//wlK + //8BRP//AEP//wBD//8ARP//AEX//wBF//8ARf//AEX//wNG//9Gd///us3///P3//////////////// + ///6/P//1eD//2+V//8OTv//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/7sARf8eAEX/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAEb/AABD/wAARf9AAEX/3ABF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//Dk7//0J0 + //9Bc///IVz//wxN//8CRv//AEP//wBD//8ARP//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBE//8YVf//VIL//4io//+dt///lLD//2qS//8qY///A0b//wBE//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf/cAEX/QABD/wAARv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEb/AABI/wIARf9jAEX/7gBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//AEP//wBD//8AQ///AET//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8AQ///AkX//wZI + //8ER///AEP//wBD//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/7gBF/2MASP8CAEb/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAEX/AABG/woARf+HAEX/+QBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //kARf+HAEb/CgBF/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEX/AABF + /xUARf+hAEX//QBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/9AEX/oQBF/xUARf8AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARf8AAEX/AABF/yEARf+1AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + /7UARf8hAEX/AABF/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAR/8AAET/AABG/ywARf/AAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/AAEX/LABE/wAAR/8AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARv8AAEP/AABG/zMARf/GAEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/xgBG + /zMAQ/8AAEb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAR/8AADz/AABF/zcARf/GAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF/8YARf83ADz/AABH/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR/8AAD3/AABG + /zMARf/AAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/AAEb/MwA9 + /wAAR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR/8AAEH/AABF/y0ARf+1AEX//ABF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf/8AEX/tQBF/y0AQf8AAEf/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAR/8AAEP/AABF/yEARf+hAEX/+ABF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/+ABF/6EARf8hAEP/AABH + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARf8AAEX/AABF/xUARf+HAEX/7wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF/+8ARf+HAEX/FQBF/wAARf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAEb/AABG/woARf9jAEX/3ABF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/cAEX/YwBG/woARv8AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEb/AABH + /wMARf9AAEX/uwBF//sARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf/7AEX/uwBF/0AAR/8DAEb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEf/AAA8/wAARv8eAEX/igBF/+sARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/6wBF/4oARv8eAD//AABH/wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAABG/wAARv8JAEX/UgBF/8MARf/7AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/+wBF + /8MARf9SAEb/CQBG/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG/wAASP8AAEX/IABF + /4UARf/jAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF/+MARf+FAEX/IABI/wAARv8AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARv8AAEb/BgBG/z4ARf+mAEX/8ABF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//AARf+mAEb/PgBG + /wYARv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAASP8AAEP/AABF/w4ARf9UAEX/tQBF//IARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//IARf+1AEX/VABF/w4AQ/8AAEj/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEf/AABP/wAARv8UAEX/WgBF + /7cARf/wAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//AARf+3AEX/WgBG/xQAT/8AAEf/AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABF/wAARP8AAEX/EwBF/1AARf+nAEX/5gBF//0ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//QBF + /+YARf+nAEX/UABF/xMARP8AAEX/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAR/8AACf/AABG/wwARf87AEX/hQBF/8wARf/0AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX/9ABF/8wARf+FAEX/OwBG/wwAJ/8AAEf/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG/wAAR/8DAEb/HgBF + /1YARf+YAEX/0wBF//QARf/+AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//4ARf/0AEX/0wBF/5gARf9WAEb/HgBH + /wMARv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASf8AAD//AABG/wYARv8iAEX/UwBF/4sARf/AAEX/5QBF + //cARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/9wBF + /+UARf/AAEX/iwBF/1MARv8iAEb/BgA//wAASf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAR/8AAEf/AwBG/xQARv80AEX/XQBF/4sARf+zAEX/0QBF/+cARf/0AEX/+gBF + //4ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF + //4ARf/6AEX/9ABF/+cARf/RAEX/swBF/4sARf9dAEb/NABG/xQAR/8DAEf/AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAR/8AAEf/AwBG/w8ARf8iAEX/QABF/18ARf99AEX/nABF/7oARf/NAEX/3QBF/+sARf/zAEX/+ABF + //wARf/8AEX/+ABF//MARf/rAEX/3QBF/80ARf+6AEX/nABF/30ARf9fAEX/QABF/yIARv8PAEf/AwBH + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA////////wAAAA////////////////AAAAAA//////////////+AAAAAA + B/////////////8AAAAAAAD////////////8AAAAAAAAP///////////8AAAAAAAAA///////////8AA + AAAAAAAD//////////8AAAAAAAAAAP/////////8AAAAAAAAAAA/////////+AAAAAAAAAAAH/////// + /+AAAAAAAAAAAAf////////AAAAAAAAAAAAD////////AAAAAAAAAAAAAP///////gAAAAAAAAAAAAB/ + //////wAAAAAAAAAAAAAP//////4AAAAAAAAAAAAAB//////8AAAAAAAAAAAAAAP/////+AAAAAAAAAA + AAAAB//////AAAAAAAAAAAAAAAP/////gAAAAAAAAAAAAAAB/////wAAAAAAAAAAAAAAAP////4AAAAA + AAAAAAAAAAB////8AAAAAAAAAAAAAAAAP///+AAAAAAAAAAAAAAAAB////AAAAAAAAAAAAAAAAAP///w + AAAAAAAAAAAAAAAAD///4AAAAAAAAAAAAAAAAAf//8AAAAAAAAAAAAAAAAAD///AAAAAAAAAAAAAAAAA + A///gAAAAAAAAAAAAAAAAAH//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP/+AAAAAAAAAAAA + AAAAAAB//gAAAAAAAAAAAAAAAAAAf/wAAAAAAAAAAAAAAAAAAD/8AAAAAAAAAAAAAAAAAAA/+AAAAAAA + AAAAAAAAAAAAH/gAAAAAAAAAAAAAAAAAAB/wAAAAAAAAAAAAAAAAAAAP8AAAAAAAAAAAAAAAAAAAD+AA + AAAAAAAAAAAAAAAAAAfgAAAAAAAAAAAAAAAAAAAH4AAAAAAAAAAAAAAAAAAAB8AAAAAAAAAAAAAAAAAA + AAPAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAA + AAAAAAABgAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAgAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAABgAAAAAAA + AAAAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAA+AA + AAAAAAAAAAAAAAAAAAfgAAAAAAAAAAAAAAAAAAAH4AAAAAAAAAAAAAAAAAAAB/AAAAAAAAAAAAAAAAAA + AA/wAAAAAAAAAAAAAAAAAAAP+AAAAAAAAAAAAAAAAAAAH/gAAAAAAAAAAAAAAAAAAB/8AAAAAAAAAAAA + AAAAAAA//AAAAAAAAAAAAAAAAAAAP/4AAAAAAAAAAAAAAAAAAH/+AAAAAAAAAAAAAAAAAAB//wAAAAAA + AAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//gAAAAAAAAAAAAAAAAAH//8AAAAAAAAAAAAAAAAAD///A + AAAAAAAAAAAAAAAAA///4AAAAAAAAAAAAAAAAAf///AAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAA + D///+AAAAAAAAAAAAAAAAB////wAAAAAAAAAAAAAAAA////+AAAAAAAAAAAAAAAAf////wAAAAAAAAAA + AAAAAP////+AAAAAAAAAAAAAAAH/////wAAAAAAAAAAAAAAD/////+AAAAAAAAAAAAAAB//////wAAAA + AAAAAAAAAA//////+AAAAAAAAAAAAAAf//////wAAAAAAAAAAAAAP//////+AAAAAAAAAAAAAH////// + /wAAAAAAAAAAAAD////////AAAAAAAAAAAAD////////4AAAAAAAAAAAB/////////gAAAAAAAAAAB// + ///////8AAAAAAAAAAA//////////wAAAAAAAAAA///////////AAAAAAAAAA///////////8AAAAAAA + AA////////////wAAAAAAAA/////////////AAAAAAAA/////////////+AAAAAAB//////////////8 + AAAAAD///////////////8AAAAP///////8= + + + \ No newline at end of file diff --git a/SCrawler/Channels/ChannelsStatsForm.vb b/SCrawler/Channels/ChannelsStatsForm.vb new file mode 100644 index 0000000..7447d08 --- /dev/null +++ b/SCrawler/Channels/ChannelsStatsForm.vb @@ -0,0 +1,84 @@ +' Copyright (C) 2022 Andy +' 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.Forms.Controls.Base +Imports PersonalUtilities.Forms.Toolbars +Friend Class ChannelsStatsForm : Implements IOkCancelDeleteToolbar + Private ReadOnly MyDefs As DefaultFormProps + Friend Property DeletedChannels As Integer = 0 + Friend Sub New() + InitializeComponent() + MyDefs = New DefaultFormProps + End Sub + Private Sub ChannelsStatsForm_Load(sender As Object, e As EventArgs) Handles Me.Load + Try + With MyDefs + .MyViewInitialize(Me, Settings.Design) + .AddOkCancelToolbar() + .DelegateClosingChecker() + .MyOkCancel.EnableDelete = False + If Settings.Channels.Count > 0 Then + RefillList() + Else + MsgBoxE("Channels not found", vbExclamation) + End If + .AppendDetectors() + .EndLoaderOperations() + End With + Catch ex As Exception + MyDefs.InvokeLoaderError(ex) + End Try + End Sub + Private Sub ChannelsStatsForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing + MyDefs.Dispose() + End Sub + Private Sub RefillList() + CMB_CHANNELS.Items.Clear() + If Settings.Channels.Count > 0 Then + CMB_CHANNELS.BeginUpdate() + CMB_CHANNELS.Items.AddRange(Settings.Channels.Select(Function(c) New ListItem({$"[{c.ID}]: {c.GetChannelStats(False)}", c.ID}))) + CMB_CHANNELS.EndUpdate() + End If + End Sub + Private Sub ToolbarBttOK() Implements IOkCancelToolbar.ToolbarBttOK + MyDefs.CloseForm() + End Sub + Private Sub ToolbarBttCancel() Implements IOkCancelToolbar.ToolbarBttCancel + MyDefs.CloseForm(DialogResult.Cancel) + End Sub + Private Sub ToolbarBttDelete() Implements IOkCancelDeleteToolbar.ToolbarBttDelete + Try + Dim c As List(Of String) = CMB_CHANNELS.Items.CheckedItems.Select(Function(cc) CStr(cc.Value(1))).ListIfNothing + If c.ListExists Then + If MsgBoxE({$"The following channels will be deleted:{vbCr}{c.ListToString(, vbCr)}", "Deleting channels"}, vbExclamation,,, {"Confirm", "Cancel"}) = 0 Then + For Each CID$ In c : Settings.Channels.Remove(Settings.Channels.Find(CID)) : Next + MyMainLOG = $"Deleted channels:{vbNewLine}{c.ListToString(, vbNewLine)}" + MsgBoxE("Channels deleted") + DeletedChannels += c.Count + c.Clear() + MyDefs.ChangesDetected = False + RefillList() + Else + MsgBoxE("Operation canceled") + End If + Else + MsgBoxE("No one channel checked", vbExclamation) + End If + Catch ex As Exception + ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Deleting channels") + End Try + End Sub + Private Sub CMB_CHANNELS_ActionOnChangeDetected(ByVal c As Boolean) Handles CMB_CHANNELS.ActionOnChangeDetected + If Not MyDefs.Initializing Then MyDefs.MyOkCancel.EnableDelete = CMB_CHANNELS.ListCheckedIndexes.Count > 0 + End Sub + Private Sub CMB_CHANNELS_ActionOnButtonClearClick() Handles CMB_CHANNELS.ActionOnButtonClearClick + CMB_CHANNELS.ListCheckedIndexes = Nothing + End Sub +End Class \ No newline at end of file diff --git a/SCrawler/Content/Icons/BookmarkIcon_32.ico b/SCrawler/Content/Icons/BookmarkIcon_32.ico new file mode 100644 index 0000000000000000000000000000000000000000..07b48e68db9f1c3737cd725f258acabb44bbe168 GIT binary patch literal 18686 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 P00000NkvXXu0mjfz}()o literal 0 HcmV?d00001 diff --git a/SCrawler/DownloadSavedPostsForm.Designer.vb b/SCrawler/DownloadSavedPostsForm.Designer.vb new file mode 100644 index 0000000..3b77939 --- /dev/null +++ b/SCrawler/DownloadSavedPostsForm.Designer.vb @@ -0,0 +1,336 @@ +' Copyright (C) 2022 Andy +' 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 + +Partial Friend Class DownloadSavedPostsForm : Inherits System.Windows.Forms.Form + + Protected Overrides Sub Dispose(ByVal disposing As Boolean) + Try + If disposing AndAlso components IsNot Nothing Then + components.Dispose() + End If + Finally + MyBase.Dispose(disposing) + End Try + End Sub + Private components As System.ComponentModel.IContainer + + Private Sub InitializeComponent() + Me.components = New System.ComponentModel.Container() + Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel + Dim TP_BUTTONS As System.Windows.Forms.TableLayoutPanel + Dim TP_REDDIT As System.Windows.Forms.TableLayoutPanel + Dim TP_REDDIT_PR As System.Windows.Forms.TableLayoutPanel + Dim TP_INST As System.Windows.Forms.TableLayoutPanel + Dim TP_INST_PR As System.Windows.Forms.TableLayoutPanel + Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(DownloadSavedPostsForm)) + Dim TT_MAIN As System.Windows.Forms.ToolTip + Me.BTT_DOWN_ALL = New System.Windows.Forms.Button() + Me.BTT_STOP_ALL = New System.Windows.Forms.Button() + Me.BTT_REDDIT_START = New System.Windows.Forms.Button() + Me.BTT_REDDIT_STOP = New System.Windows.Forms.Button() + Me.PR_REDDIT = New System.Windows.Forms.ProgressBar() + Me.BTT_REDDIT_OPEN = New System.Windows.Forms.Button() + Me.LBL_REDDIT = New System.Windows.Forms.Label() + Me.BTT_INST_START = New System.Windows.Forms.Button() + Me.BTT_INST_STOP = New System.Windows.Forms.Button() + Me.PR_INST = New System.Windows.Forms.ProgressBar() + Me.BTT_INST_OPEN = New System.Windows.Forms.Button() + Me.LBL_INST = New System.Windows.Forms.Label() + TP_MAIN = New System.Windows.Forms.TableLayoutPanel() + TP_BUTTONS = New System.Windows.Forms.TableLayoutPanel() + TP_REDDIT = New System.Windows.Forms.TableLayoutPanel() + TP_REDDIT_PR = New System.Windows.Forms.TableLayoutPanel() + TP_INST = New System.Windows.Forms.TableLayoutPanel() + TP_INST_PR = New System.Windows.Forms.TableLayoutPanel() + TT_MAIN = New System.Windows.Forms.ToolTip(Me.components) + TP_MAIN.SuspendLayout() + TP_BUTTONS.SuspendLayout() + TP_REDDIT.SuspendLayout() + TP_REDDIT_PR.SuspendLayout() + TP_INST.SuspendLayout() + TP_INST_PR.SuspendLayout() + Me.SuspendLayout() + ' + 'TP_MAIN + ' + TP_MAIN.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.Inset + TP_MAIN.ColumnCount = 1 + TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + TP_MAIN.Controls.Add(TP_BUTTONS, 0, 0) + TP_MAIN.Controls.Add(TP_REDDIT, 0, 1) + TP_MAIN.Controls.Add(TP_INST, 0, 2) + 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 = 3 + TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30.0!)) + TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) + TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) + TP_MAIN.Size = New System.Drawing.Size(484, 156) + TP_MAIN.TabIndex = 0 + ' + 'TP_BUTTONS + ' + TP_BUTTONS.ColumnCount = 2 + TP_BUTTONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) + TP_BUTTONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) + TP_BUTTONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!)) + TP_BUTTONS.Controls.Add(Me.BTT_DOWN_ALL, 0, 0) + TP_BUTTONS.Controls.Add(Me.BTT_STOP_ALL, 1, 0) + TP_BUTTONS.Dock = System.Windows.Forms.DockStyle.Fill + TP_BUTTONS.Location = New System.Drawing.Point(2, 2) + TP_BUTTONS.Margin = New System.Windows.Forms.Padding(0) + TP_BUTTONS.Name = "TP_BUTTONS" + TP_BUTTONS.RowCount = 1 + TP_BUTTONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + TP_BUTTONS.Size = New System.Drawing.Size(480, 30) + TP_BUTTONS.TabIndex = 0 + ' + 'BTT_DOWN_ALL + ' + Me.BTT_DOWN_ALL.Dock = System.Windows.Forms.DockStyle.Fill + Me.BTT_DOWN_ALL.Location = New System.Drawing.Point(3, 3) + Me.BTT_DOWN_ALL.Name = "BTT_DOWN_ALL" + Me.BTT_DOWN_ALL.Size = New System.Drawing.Size(234, 24) + Me.BTT_DOWN_ALL.TabIndex = 0 + Me.BTT_DOWN_ALL.Text = "Download ALL" + Me.BTT_DOWN_ALL.UseVisualStyleBackColor = True + ' + 'BTT_STOP_ALL + ' + Me.BTT_STOP_ALL.Dock = System.Windows.Forms.DockStyle.Fill + Me.BTT_STOP_ALL.Location = New System.Drawing.Point(243, 3) + Me.BTT_STOP_ALL.Name = "BTT_STOP_ALL" + Me.BTT_STOP_ALL.Size = New System.Drawing.Size(234, 24) + Me.BTT_STOP_ALL.TabIndex = 1 + Me.BTT_STOP_ALL.Text = "Stop ALL" + Me.BTT_STOP_ALL.UseVisualStyleBackColor = True + ' + 'TP_REDDIT + ' + TP_REDDIT.ColumnCount = 1 + TP_REDDIT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + TP_REDDIT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!)) + TP_REDDIT.Controls.Add(TP_REDDIT_PR, 0, 0) + TP_REDDIT.Controls.Add(Me.LBL_REDDIT, 0, 1) + TP_REDDIT.Dock = System.Windows.Forms.DockStyle.Fill + TP_REDDIT.Location = New System.Drawing.Point(2, 34) + TP_REDDIT.Margin = New System.Windows.Forms.Padding(0) + TP_REDDIT.Name = "TP_REDDIT" + TP_REDDIT.RowCount = 2 + TP_REDDIT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) + TP_REDDIT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) + TP_REDDIT.Size = New System.Drawing.Size(480, 59) + TP_REDDIT.TabIndex = 1 + ' + 'TP_REDDIT_PR + ' + TP_REDDIT_PR.ColumnCount = 4 + TP_REDDIT_PR.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 30.0!)) + TP_REDDIT_PR.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 30.0!)) + TP_REDDIT_PR.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 30.0!)) + TP_REDDIT_PR.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + TP_REDDIT_PR.Controls.Add(Me.BTT_REDDIT_START, 0, 0) + TP_REDDIT_PR.Controls.Add(Me.BTT_REDDIT_STOP, 1, 0) + TP_REDDIT_PR.Controls.Add(Me.PR_REDDIT, 3, 0) + TP_REDDIT_PR.Controls.Add(Me.BTT_REDDIT_OPEN, 2, 0) + TP_REDDIT_PR.Dock = System.Windows.Forms.DockStyle.Fill + TP_REDDIT_PR.Location = New System.Drawing.Point(0, 0) + TP_REDDIT_PR.Margin = New System.Windows.Forms.Padding(0) + TP_REDDIT_PR.Name = "TP_REDDIT_PR" + TP_REDDIT_PR.RowCount = 1 + TP_REDDIT_PR.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + TP_REDDIT_PR.Size = New System.Drawing.Size(480, 29) + TP_REDDIT_PR.TabIndex = 0 + ' + 'BTT_REDDIT_START + ' + Me.BTT_REDDIT_START.BackgroundImage = Global.SCrawler.My.Resources.Resources.StartPic_01_Green_16 + Me.BTT_REDDIT_START.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom + Me.BTT_REDDIT_START.Dock = System.Windows.Forms.DockStyle.Fill + Me.BTT_REDDIT_START.Location = New System.Drawing.Point(3, 3) + Me.BTT_REDDIT_START.Name = "BTT_REDDIT_START" + Me.BTT_REDDIT_START.Size = New System.Drawing.Size(24, 23) + Me.BTT_REDDIT_START.TabIndex = 0 + TT_MAIN.SetToolTip(Me.BTT_REDDIT_START, "Start downloading saved Reddit posts") + Me.BTT_REDDIT_START.UseVisualStyleBackColor = True + ' + 'BTT_REDDIT_STOP + ' + Me.BTT_REDDIT_STOP.BackgroundImage = Global.SCrawler.My.Resources.Resources.Delete + Me.BTT_REDDIT_STOP.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom + Me.BTT_REDDIT_STOP.Dock = System.Windows.Forms.DockStyle.Fill + Me.BTT_REDDIT_STOP.Enabled = False + Me.BTT_REDDIT_STOP.Location = New System.Drawing.Point(33, 3) + Me.BTT_REDDIT_STOP.Name = "BTT_REDDIT_STOP" + Me.BTT_REDDIT_STOP.Size = New System.Drawing.Size(24, 23) + Me.BTT_REDDIT_STOP.TabIndex = 1 + TT_MAIN.SetToolTip(Me.BTT_REDDIT_STOP, "Stop downloading saved Reddit posts") + Me.BTT_REDDIT_STOP.UseVisualStyleBackColor = True + ' + 'PR_REDDIT + ' + Me.PR_REDDIT.Dock = System.Windows.Forms.DockStyle.Fill + Me.PR_REDDIT.Location = New System.Drawing.Point(93, 3) + Me.PR_REDDIT.Name = "PR_REDDIT" + Me.PR_REDDIT.Size = New System.Drawing.Size(384, 23) + Me.PR_REDDIT.TabIndex = 2 + ' + 'BTT_REDDIT_OPEN + ' + Me.BTT_REDDIT_OPEN.BackgroundImage = CType(resources.GetObject("BTT_REDDIT_OPEN.BackgroundImage"), System.Drawing.Image) + Me.BTT_REDDIT_OPEN.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom + Me.BTT_REDDIT_OPEN.Dock = System.Windows.Forms.DockStyle.Fill + Me.BTT_REDDIT_OPEN.Location = New System.Drawing.Point(63, 3) + Me.BTT_REDDIT_OPEN.Name = "BTT_REDDIT_OPEN" + Me.BTT_REDDIT_OPEN.Size = New System.Drawing.Size(24, 23) + Me.BTT_REDDIT_OPEN.TabIndex = 3 + Me.BTT_REDDIT_OPEN.UseVisualStyleBackColor = True + ' + 'LBL_REDDIT + ' + Me.LBL_REDDIT.AutoSize = True + Me.LBL_REDDIT.Dock = System.Windows.Forms.DockStyle.Fill + Me.LBL_REDDIT.Location = New System.Drawing.Point(3, 29) + Me.LBL_REDDIT.Name = "LBL_REDDIT" + Me.LBL_REDDIT.Size = New System.Drawing.Size(474, 30) + Me.LBL_REDDIT.TabIndex = 1 + Me.LBL_REDDIT.Text = "Reddit" + Me.LBL_REDDIT.TextAlign = System.Drawing.ContentAlignment.TopCenter + ' + 'TP_INST + ' + TP_INST.ColumnCount = 1 + TP_INST.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + TP_INST.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!)) + TP_INST.Controls.Add(TP_INST_PR, 0, 0) + TP_INST.Controls.Add(Me.LBL_INST, 0, 1) + TP_INST.Dock = System.Windows.Forms.DockStyle.Fill + TP_INST.Location = New System.Drawing.Point(2, 95) + TP_INST.Margin = New System.Windows.Forms.Padding(0) + TP_INST.Name = "TP_INST" + TP_INST.RowCount = 2 + TP_INST.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) + TP_INST.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) + TP_INST.Size = New System.Drawing.Size(480, 59) + TP_INST.TabIndex = 2 + ' + 'TP_INST_PR + ' + TP_INST_PR.ColumnCount = 4 + TP_INST_PR.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 30.0!)) + TP_INST_PR.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 30.0!)) + TP_INST_PR.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 30.0!)) + TP_INST_PR.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + TP_INST_PR.Controls.Add(Me.BTT_INST_START, 0, 0) + TP_INST_PR.Controls.Add(Me.BTT_INST_STOP, 1, 0) + TP_INST_PR.Controls.Add(Me.PR_INST, 3, 0) + TP_INST_PR.Controls.Add(Me.BTT_INST_OPEN, 2, 0) + TP_INST_PR.Dock = System.Windows.Forms.DockStyle.Fill + TP_INST_PR.Location = New System.Drawing.Point(0, 0) + TP_INST_PR.Margin = New System.Windows.Forms.Padding(0) + TP_INST_PR.Name = "TP_INST_PR" + TP_INST_PR.RowCount = 1 + TP_INST_PR.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + TP_INST_PR.Size = New System.Drawing.Size(480, 29) + TP_INST_PR.TabIndex = 0 + ' + 'BTT_INST_START + ' + Me.BTT_INST_START.BackgroundImage = Global.SCrawler.My.Resources.Resources.StartPic_01_Green_16 + Me.BTT_INST_START.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom + Me.BTT_INST_START.Dock = System.Windows.Forms.DockStyle.Fill + Me.BTT_INST_START.Location = New System.Drawing.Point(3, 3) + Me.BTT_INST_START.Name = "BTT_INST_START" + Me.BTT_INST_START.Size = New System.Drawing.Size(24, 23) + Me.BTT_INST_START.TabIndex = 0 + TT_MAIN.SetToolTip(Me.BTT_INST_START, "Start downloading saved Instagram posts") + Me.BTT_INST_START.UseVisualStyleBackColor = True + ' + 'BTT_INST_STOP + ' + Me.BTT_INST_STOP.BackgroundImage = Global.SCrawler.My.Resources.Resources.Delete + Me.BTT_INST_STOP.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom + Me.BTT_INST_STOP.Dock = System.Windows.Forms.DockStyle.Fill + Me.BTT_INST_STOP.Enabled = False + Me.BTT_INST_STOP.Location = New System.Drawing.Point(33, 3) + Me.BTT_INST_STOP.Name = "BTT_INST_STOP" + Me.BTT_INST_STOP.Size = New System.Drawing.Size(24, 23) + Me.BTT_INST_STOP.TabIndex = 1 + TT_MAIN.SetToolTip(Me.BTT_INST_STOP, "Stop downloading saved Instagram posts") + Me.BTT_INST_STOP.UseVisualStyleBackColor = True + ' + 'PR_INST + ' + Me.PR_INST.Dock = System.Windows.Forms.DockStyle.Fill + Me.PR_INST.Location = New System.Drawing.Point(93, 3) + Me.PR_INST.Name = "PR_INST" + Me.PR_INST.Size = New System.Drawing.Size(384, 23) + Me.PR_INST.TabIndex = 2 + ' + 'BTT_INST_OPEN + ' + Me.BTT_INST_OPEN.BackgroundImage = CType(resources.GetObject("BTT_INST_OPEN.BackgroundImage"), System.Drawing.Image) + Me.BTT_INST_OPEN.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom + Me.BTT_INST_OPEN.Dock = System.Windows.Forms.DockStyle.Fill + Me.BTT_INST_OPEN.Location = New System.Drawing.Point(63, 3) + Me.BTT_INST_OPEN.Name = "BTT_INST_OPEN" + Me.BTT_INST_OPEN.Size = New System.Drawing.Size(24, 23) + Me.BTT_INST_OPEN.TabIndex = 3 + Me.BTT_INST_OPEN.UseVisualStyleBackColor = True + ' + 'LBL_INST + ' + Me.LBL_INST.AutoSize = True + Me.LBL_INST.Dock = System.Windows.Forms.DockStyle.Fill + Me.LBL_INST.Location = New System.Drawing.Point(3, 29) + Me.LBL_INST.Name = "LBL_INST" + Me.LBL_INST.Size = New System.Drawing.Size(474, 30) + Me.LBL_INST.TabIndex = 1 + Me.LBL_INST.Text = "Instagram" + Me.LBL_INST.TextAlign = System.Drawing.ContentAlignment.TopCenter + ' + 'DownloadSavedPostsForm + ' + Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) + Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font + Me.ClientSize = New System.Drawing.Size(484, 156) + Me.Controls.Add(TP_MAIN) + Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle + Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon) + Me.MaximizeBox = False + Me.MaximumSize = New System.Drawing.Size(500, 195) + Me.MinimumSize = New System.Drawing.Size(500, 195) + Me.Name = "DownloadSavedPostsForm" + Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide + Me.Text = "Saved posts" + TP_MAIN.ResumeLayout(False) + TP_BUTTONS.ResumeLayout(False) + TP_REDDIT.ResumeLayout(False) + TP_REDDIT.PerformLayout() + TP_REDDIT_PR.ResumeLayout(False) + TP_INST.ResumeLayout(False) + TP_INST.PerformLayout() + TP_INST_PR.ResumeLayout(False) + Me.ResumeLayout(False) + + End Sub + Private WithEvents BTT_DOWN_ALL As Button + Private WithEvents BTT_STOP_ALL As Button + Private WithEvents BTT_REDDIT_START As Button + Private WithEvents BTT_REDDIT_STOP As Button + Private WithEvents PR_REDDIT As ProgressBar + Private WithEvents LBL_REDDIT As Label + Private WithEvents BTT_INST_START As Button + Private WithEvents BTT_INST_STOP As Button + Private WithEvents PR_INST As ProgressBar + Private WithEvents LBL_INST As Label + Private WithEvents BTT_REDDIT_OPEN As Button + Private WithEvents BTT_INST_OPEN As Button +End Class \ No newline at end of file diff --git a/SCrawler/DownloadSavedPostsForm.resx b/SCrawler/DownloadSavedPostsForm.resx new file mode 100644 index 0000000..27f32ce --- /dev/null +++ b/SCrawler/DownloadSavedPostsForm.resx @@ -0,0 +1,492 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + False + + + False + + + False + + + False + + + False + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP + WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP + aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+ + 5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8 + vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB + cMaRN0UdBBkAAAAASUVORK5CYII= + + + + False + + + False + + + 17, 17 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP + WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP + aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+ + 5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8 + vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB + cMaRN0UdBBkAAAAASUVORK5CYII= + + + + False + + + 17, 17 + + + + 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 + 2/+ioqL/mpqa/8nJyf/o6Oj/9PT0//n5+f/5+fn/9PT0/+jo6P/Jycn/mpqa/6Kiov/b29v/+fn5wf39 + /T729vYA9vb2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vYA9vb2AP// + /z77+/vB0NDQ/35+fv9paWn/l5eX/76+vv/X19f/5OTk/+Tk5P/X19f/vr6+/5eXl/9paWn/fn5+/9DQ + 0P/7+/vB////Pvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb2 + 9gD29vYA////Pvv7+8HNzc3/c3Nz/0pKSv9ZWVn/eHh4/6Ghof+3t7f/t7e3/6Ghof94eHj/WVlZ/0pK + Sv9zc3P/zc3N//v7+8H///8+9vb2APb29gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA9vb2APb29gD///8+/Pz8wcvLy/9vb2//Ozs7/zs7O/9PT0//c3Nz/4eHh/+Hh4f/c3Nz/09P + T/87Ozv/Ozs7/29vb//Ly8v//Pz8wf///z729vYA9vb2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAD29vYA9vb2AP///z78/PzBy8vL/29vb/89PT3/PT09/0VFRf9RUVH/V1dX/1dX + V/9RUVH/RUVF/z09Pf89PT3/b29v/8vLy//8/PzB////Pvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA////Pvz8/MHMzMz/b29v/z4+Pv8/Pz//QUFB/0BA + QP9AQED/QEBA/0BAQP9BQUH/Pz8//z4+Pv9vb2//zMzM//z8/MH///8+9vb2APb29gAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2APb29gD///8+/Pz8wczMzP9vb2//Pj4+/z8/ + P/9CQkL/QUFB/0FBQf9BQUH/QUFB/0JCQv8/Pz//Pj4+/29vb//MzMz//Pz8wf///z729vYA9vb2AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vYA9vb2AP///z78/PzBzMzM/29v + b/8+Pj7/Pz8//0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/z8/P/8+Pj7/b29v/8zMzP/8/PzB////Pvb2 + 9gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA////Pvz8 + /MHMzMz/b29v/z4+Pv8/Pz//QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/Pz8//z4+Pv9vb2//zMzM//z8 + /MH///8+9vb2APb29gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2APb2 + 9gD///8+/Pz8wczMzP9vb2//Pj4+/z8/P/9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv8/Pz//Pj4+/29v + b//MzMz//Pz8wf///z729vYA9vb2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAD29vYA9vb2AP///z78/PzBzMzM/29vb/8+Pj7/Pz8//0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/z8/ + P/8+Pj7/b29v/8zMzP/8/PzB////Pvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAPb29gD29vYA////Pvz8/MHMzMz/b29v/z4+Pv8/Pz//QkJC/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/Pz8//z4+Pv9vb2//zMzM//z8/MH///8+9vb2APb29gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA9vb2APb29gD///8+/Pz8wczMzP9vb2//Pj4+/z8/P/9CQkL/QkJC/0JC + Qv9CQkL/QkJC/0JCQv8/Pz//Pj4+/29vb//MzMz//Pz8wf///z729vYA9vb2AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vYA9vb2AP///z78/PzBzMzM/29vb/8+Pj7/Pz8//0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/z8/P/8+Pj7/b29v/8zMzP/8/PzB////Pvb29gD29vYAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA////Pvz8/MHMzMz/b29v/z4+ + Pv8/Pz//QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/Pz8//z4+Pv9vb2//zMzM//z8/MH///8+9vb2APb2 + 9gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2APb29gD///8+/Pz8wczM + zP9vb2//Pj4+/z8/P/9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv8/Pz//Pj4+/29vb//MzMz//Pz8wf// + /z729vYA9vb2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vYA9vb2AP// + /z78/PzBzMzM/29vb/8+Pj7/Pz8//0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/z8/P/8+Pj7/b29v/8zM + zP/8/PzB////Pvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb2 + 9gD29vYA////Pvz8/MHMzMz/b29v/z4+Pv8/Pz//QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/Pz8//z4+ + Pv9vb2//zMzM//z8/MH///8+9vb2APb29gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA9vb2APb29gD///8+/Pz8wczMzP9vb2//Pj4+/z8/P/9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC + Qv8/Pz//Pj4+/29vb//MzMz//Pz8wf///z729vYA9vb2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAD29vYA9vb2AP///z78/PzBy8vL/21tbf87Ozv/PT09/z8/P/8/Pz//Pz8//z8/ + P/8/Pz//Pz8//z09Pf87Ozv/bW1t/8vLy//8/PzB////Pvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA////Pvz8/MHLy8v/bGxs/zk5Of87Ozv/Pj4+/z4+ + Pv8+Pj7/Pj4+/z4+Pv8+Pj7/Ozs7/zk5Of9sbGz/y8vL//z8/MH///8+9vb2APb29gAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2APb29gD+/v4++vr6wdbW1v+RkZH/bGxs/21t + bf9vb2//b29v/29vb/9vb2//b29v/29vb/9tbW3/bGxs/5GRkf/W1tb/+vr6wf7+/j729vYA9vb2AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vYA9vb2APn5+T739/fB7Ozs/9bW + 1v/Ly8v/y8vL/8zMzP/MzMz/zMzM/8zMzP/MzMz/zMzM/8vLy//Ly8v/1tbW/+zs7P/39/fB+fn5Pvb2 + 9gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Lvb2 + 9pH39/fD+vr6wfz8/L/8/Py//Pz8v/z8/L/8/Py//Pz8v/z8/L/8/Py//Pz8v/z8/L/6+vrB9/f3w/b2 + 9pH29vYu9vb2APb29gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2APb2 + 9gD19fUP9vb2Lvj4+D79/f09////PP///zz///88////PP///zz///88////PP///zz///88////PP39 + /T34+Pg+9vb2LvX19Q/29vYA9vb2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////gfgf/4H + 4H/+AAB//gAAf/4AAH/+AAB//gAAf/4AAH/+AAB//gAAf/4AAH/+AAB//gAAf/4AAH/+AAB//gAAf/4A + AH/+AAB//gAAf/4AAH/+AAB//gAAf/4AAH/+AAB//gAAf/4AAH/+AAB//gAAf/4AAH/+AAB//////ygA + AAAwAAAAYAAAAAEAIAAAAAAAACQAAMMOAADDDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Afb29gX29vYK9vb2Dvb29hD29vYQ9vb2Dvb2 + 9gr29vYF9vb2Afb29gD29vYAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Afb29gX29vYK9vb2Dvb2 + 9hD29vYQ9vb2Dvb29gr29vYF9vb2Afb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2BPb29hr29vY29vb2S/b2 + 9lT29vZU9vb2S/b29jb29vYa9vb2BPb29gD29vYAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2BPb2 + 9hr29vY29vb2S/b29lT29vZU9vb2S/b29jb29vYa9vb2BPb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Cfb2 + 9jf29vZy9vb2n/b29rL29vay9vb2n/b29nL29vY39vb2Cfb29gD29vYAAAAAAAAAAAAAAAAAAAAAAPb2 + 9gD29vYA9vb2Cfb29jf29vZy9vb2n/b29rL29vay9vb2n/b29nL29vY39vb2Cfb29gD29vYAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb2 + 9gD29vYA9vb2Dfb29k729vaj9vb24/b29v729vb+9vb25Pb29qj29vZX9vb2G/b29gf29vYJ9vb2Dvb2 + 9g729vYO9vb2Dvb29gn29vYH9vb2G/b29lf29vao9vb25Pb29v729vb+9vb24/b29qP29vZO9vb2Dfb2 + 9gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAPb29gD29vYA9vb2Dvb29lL29vat9vb28ff39//4+Pj/+fn59fn5+cf5+fmK+Pj4XPf3 + 90339/dO9vb2Uvb29lL29vZS9vb2Uvf390739/dN+Pj4XPn5+Yr5+fnH+fn59fj4+P/39/f/9vb28fb2 + 9q329vZS9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dvb29lL29vat9vb28fj4+P/5+fn/+vr6+vr6 + +uT5+fnH+Pj4sff396r29var9vb2rfb29q329vat9vb2rfb29qv39/eq+Pj4sfn5+cf6+vrk+vr6+vn5 + +f/4+Pj/9vb28fb29q329vZS9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dvf391L29vat9vb28fPz + 8//w8PD/7+/v/u/v7/ry8vL19PT08vX19fD29vbx9vb28fb29vH29vbx9vb28fb29vH19fXw9PT08vLy + 8vXv7+/67+/v/vDw8P/z8/P/9vb28fb29q339/dS9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dvn5 + +VL4+Pit8/Pz8efn5//W1tb/zMzM/9LS0v/h4eH/7e3t//Pz8//29vb/9/f3//j4+P/4+Pj/9/f3//b2 + 9v/z8/P/7e3t/+Hh4f/S0tL/zMzM/9bW1v/n5+f/8/Pz8fj4+K35+flS9vb2Dvb29gD29vYAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb2 + 9gD29vYA9vb2Dv39/VL7+/ut8PDw8dbW1v+zs7P/np6e/6qqqv/Hx8f/4eHh/+7u7v/09PT/+Pj4//r6 + +v/6+vr/+Pj4//T09P/u7u7/4eHh/8fHx/+qqqr/np6e/7Ozs//W1tb/8PDw8fv7+639/f1S9vb2Dvb2 + 9gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L9/f2t7u7u8cjIyP+Wlpb/eHh4/4WFhf+pqan/ysrK/9zc + 3P/o6Oj/7+/v//Pz8//z8/P/7+/v/+jo6P/c3Nz/ysrK/6mpqf+FhYX/eHh4/5aWlv/IyMj/7u7u8f39 + /a3///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L+/v6t7Ozs8cLCwv+IiIj/YmJi/2dn + Z/+FhYX/oqKi/7i4uP/Ly8v/2NjY/97e3v/e3t7/2NjY/8vLy/+4uLj/oqKi/4WFhf9nZ2f/YmJi/4iI + iP/CwsL/7Ozs8f7+/q3///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L+/v6t7Ozs8b+/ + v/+Dg4P/VVVV/09PT/9dXV3/cnJy/4qKiv+kpKT/uLi4/8DAwP/AwMD/uLi4/6SkpP+Kior/cnJy/11d + Xf9PT0//VVVV/4ODg/+/v7//7Ozs8f7+/q3///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv// + /1L///+t7Ozs8b6+vv+AgID/Tk5O/z4+Pv9BQUH/Tk5O/2VlZf+CgoL/l5eX/6Ghof+hoaH/l5eX/4KC + gv9lZWX/Tk5O/0FBQf8+Pj7/Tk5O/4CAgP++vr7/7Ozs8f///63///9S9vb2Dvb29gD29vYAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb2 + 9gD29vYA9vb2Dv///1L///+t6+vr8b29vf9+fn7/S0tL/zg4OP84ODj/QUFB/1FRUf9oaGj/eHh4/39/ + f/9/f3//eHh4/2hoaP9RUVH/QUFB/zg4OP84ODj/S0tL/35+fv+9vb3/6+vr8f///63///9S9vb2Dvb2 + 9gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L///+t6+vr8b6+vv9+fn7/S0tL/zo6Ov86Ojr/QUFB/0hI + SP9TU1P/W1tb/19fX/9fX1//W1tb/1NTU/9ISEj/QUFB/zo6Ov86Ojr/S0tL/35+fv++vr7/6+vr8f// + /63///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L///+t6+vr8b6+vv9/f3//TExM/zw8 + PP8+Pj7/QkJC/0RERP9FRUX/R0dH/0dHR/9HR0f/R0dH/0VFRf9ERET/QkJC/z4+Pv88PDz/TExM/39/ + f/++vr7/6+vr8f///63///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L///+t6+vr8b6+ + vv9/f3//TExM/zw8PP8+Pj7/QkJC/0FBQf9AQED/Pz8//z8/P/8/Pz//Pz8//0BAQP9BQUH/QkJC/z4+ + Pv88PDz/TExM/39/f/++vr7/6+vr8f///63///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv// + /1L///+t6+vr8b6+vv9/f3//TExM/zw8PP8+Pj7/QkJC/0FBQf9BQUH/QEBA/0BAQP9AQED/QEBA/0FB + Qf9BQUH/QkJC/z4+Pv88PDz/TExM/39/f/++vr7/6+vr8f///63///9S9vb2Dvb29gD29vYAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb2 + 9gD29vYA9vb2Dv///1L///+t6+vr8b6+vv9/f3//TExM/zw8PP8+Pj7/QkJC/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/z4+Pv88PDz/TExM/39/f/++vr7/6+vr8f///63///9S9vb2Dvb2 + 9gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L///+t6+vr8b6+vv9/f3//TExM/zw8PP8+Pj7/QkJC/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/z4+Pv88PDz/TExM/39/f/++vr7/6+vr8f// + /63///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L///+t6+vr8b6+vv9/f3//TExM/zw8 + PP8+Pj7/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/z4+Pv88PDz/TExM/39/ + f/++vr7/6+vr8f///63///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L///+t6+vr8b6+ + vv9/f3//TExM/zw8PP8+Pj7/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/z4+ + Pv88PDz/TExM/39/f/++vr7/6+vr8f///63///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv// + /1L///+t6+vr8b6+vv9/f3//TExM/zw8PP8+Pj7/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC/z4+Pv88PDz/TExM/39/f/++vr7/6+vr8f///63///9S9vb2Dvb29gD29vYAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb2 + 9gD29vYA9vb2Dv///1L///+t6+vr8b6+vv9/f3//TExM/zw8PP8+Pj7/QkJC/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/z4+Pv88PDz/TExM/39/f/++vr7/6+vr8f///63///9S9vb2Dvb2 + 9gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L///+t6+vr8b6+vv9/f3//TExM/zw8PP8+Pj7/QkJC/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/z4+Pv88PDz/TExM/39/f/++vr7/6+vr8f// + /63///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L///+t6+vr8b6+vv9/f3//TExM/zw8 + PP8+Pj7/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/z4+Pv88PDz/TExM/39/ + f/++vr7/6+vr8f///63///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L///+t6+vr8b6+ + vv9/f3//TExM/zw8PP8+Pj7/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/z4+ + Pv88PDz/TExM/39/f/++vr7/6+vr8f///63///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv// + /1L///+t6+vr8b6+vv9/f3//TExM/zw8PP8+Pj7/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC/z4+Pv88PDz/TExM/39/f/++vr7/6+vr8f///63///9S9vb2Dvb29gD29vYAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb2 + 9gD29vYA9vb2Dv///1L///+t6+vr8b6+vv9/f3//TExM/zw8PP8+Pj7/QkJC/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/z4+Pv88PDz/TExM/39/f/++vr7/6+vr8f///63///9S9vb2Dvb2 + 9gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L///+t6+vr8b6+vv9/f3//TExM/zw8PP8+Pj7/QkJC/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/z4+Pv88PDz/TExM/39/f/++vr7/6+vr8f// + /63///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L///+t6+vr8b6+vv9/f3//TExM/zw8 + PP8+Pj7/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/z4+Pv88PDz/TExM/39/ + f/++vr7/6+vr8f///63///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L///+t6+vr8b6+ + vv9/f3//TExM/zw8PP8+Pj7/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/z4+ + Pv88PDz/TExM/39/f/++vr7/6+vr8f///63///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv// + /1L///+t6+vr8b6+vv9/f3//TExM/zw8PP8+Pj7/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC/z4+Pv88PDz/TExM/39/f/++vr7/6+vr8f///63///9S9vb2Dvb29gD29vYAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb2 + 9gD29vYA9vb2Dv///1L///+t6+vr8b6+vv9/f3//TExM/zw8PP8+Pj7/QkJC/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/z4+Pv88PDz/TExM/39/f/++vr7/6+vr8f///63///9S9vb2Dvb2 + 9gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L///+t6+vr8b6+vv9/f3//TExM/zw8PP8+Pj7/QkJC/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/z4+Pv88PDz/TExM/39/f/++vr7/6+vr8f// + /63///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L///+t6+vr8b6+vv9/f3//TExM/zw8 + PP8+Pj7/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/z4+Pv88PDz/TExM/39/ + f/++vr7/6+vr8f///63///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L///+t6+vr8b6+ + vv9/f3//TExM/zw8PP8+Pj7/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/z4+ + Pv88PDz/TExM/39/f/++vr7/6+vr8f///63///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv// + /1L///+t6+vr8by8vP98fHz/SEhI/zg4OP86Ojr/Pj4+/z4+Pv8+Pj7/Pj4+/z4+Pv8+Pj7/Pj4+/z4+ + Pv8+Pj7/Pj4+/zo6Ov84ODj/SEhI/3x8fP+8vLz/6+vr8f///63///9S9vb2Dvb29gD29vYAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb2 + 9gD29vYA9vb2Dv///1L///+t6+vr8by8vP97e3v/RkZG/zY2Nv84ODj/PDw8/zw8PP88PDz/PDw8/zw8 + PP88PDz/PDw8/zw8PP88PDz/PDw8/zg4OP82Njb/RkZG/3t7e/+8vLz/6+vr8f///63///9S9vb2Dvb2 + 9gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAPb29gD29vYA9vb2Dv///1L+/v6t7Ozs8cHBwf+FhYX/VVVV/0ZGRv9ISEj/TExM/0xM + TP9MTEz/TExM/0xMTP9MTEz/TExM/0xMTP9MTEz/TExM/0hISP9GRkb/VVVV/4WFhf/BwcH/7Ozs8f7+ + /q3///9S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dv7+/lL8/Pyt7+/v8dHR0f+np6f/hYWF/3t7 + e/98fHz/f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3x8fP97e3v/hYWF/6en + p//R0dH/7+/v8fz8/K3+/v5S9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dvr6+lL5+fmt8/Pz8eTk + 5P/R0dH/wcHB/7y8vP+8vLz/vr6+/76+vv++vr7/vr6+/76+vv++vr7/vr6+/76+vv++vr7/vr6+/7y8 + vP+8vLz/wcHB/9HR0f/k5OT/8/Pz8fn5+a36+vpS9vb2Dvb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Dff3 + 90739/ej9fX14/Pz8/nv7+/27Ozs8evr6/Hr6+vx6+vr8evr6/Hr6+vx6+vr8evr6/Hr6+vx6+vr8evr + 6/Hr6+vx6+vr8evr6/Hr6+vx7Ozs8e/v7/bz8/P59fX14/f396P39/dO9vb2Dfb29gD29vYAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb2 + 9gD29vYA9vb2CfX19Tf29vZy9/f3n/n5+a78/Pyt/v7+qf///6n///+p////qf///6n///+p////qf// + /6n///+p////qf///6n///+p////qf///6n///+p/v7+qfz8/K35+fmu9/f3n/b29nL19fU39vb2Cfb2 + 9gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAPb29gD29vYA9vb2BPX19Rr29vY29/f3S/n5+VL8/PxS////UP///1D///9Q////UP// + /1D///9Q////UP///1D///9Q////UP///1D///9Q////UP///1D///9Q////UPz8/FL5+flS9/f3S/b2 + 9jb19fUa9vb2BPb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29gD29vYA9vb2Afb29gX29vYK9vb2Dvb29g/29vYP9vb2D/b2 + 9g/29vYP9vb2D/b29g/29vYP9vb2D/b29g/29vYP9vb2D/b29g/29vYP9vb2D/b29g/29vYP9vb2D/b2 + 9g/29vYP9vb2Dvb29gr29vYF9vb2Afb29gD29vYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAD///////8AAP/AD/AD/wAA/8AP8AP/AAD/wA/wA/8AAP/AAAAD/wAA/8AAAAP/ + AAD/wAAAA/8AAP/AAAAD/wAA/8AAAAP/AAD/wAAAA/8AAP/AAAAD/wAA/8AAAAP/AAD/wAAAA/8AAP/A + AAAD/wAA/8AAAAP/AAD/wAAAA/8AAP/AAAAD/wAA/8AAAAP/AAD/wAAAA/8AAP/AAAAD/wAA/8AAAAP/ + AAD/wAAAA/8AAP/AAAAD/wAA/8AAAAP/AAD/wAAAA/8AAP/AAAAD/wAA/8AAAAP/AAD/wAAAA/8AAP/A + AAAD/wAA/8AAAAP/AAD/wAAAA/8AAP/AAAAD/wAA/8AAAAP/AAD/wAAAA/8AAP/AAAAD/wAA/8AAAAP/ + AAD/wAAAA/8AAP/AAAAD/wAA/8AAAAP/AAD/wAAAA/8AAP/AAAAD/wAA/8AAAAP/AAD/wAAAA/8AAP/A + AAAD/wAA/8AAAAP/AAD/wAAAA/8AAP/AAAAD/wAA////////AAAoAAAAEAAAACAAAAABACAAAAAAAAAE + AADDDgAAww4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2/wAAAAAAAAAAAAAAAAAA + AAD29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v9kZGT/1NTU//b2 + 9v/29vb/1NTU/2RkZP/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/QkJC/0JC + Qv+cnJz/nJyc/0JCQv9CQkL/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb2 + 9v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAD29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA9vb2/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAPb29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/AAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAD29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2/wAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA9vb2/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC//b29v8AAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2/wAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 + 9v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AADzzwAA8A8AAPAPAADwDwAA8A8AAPAPAADwDwAA8A8AAPAP + AADwDwAA8A8AAPAPAADwDwAA8A8AAP//AAA= + + + \ No newline at end of file diff --git a/SCrawler/DownloadSavedPostsForm.vb b/SCrawler/DownloadSavedPostsForm.vb new file mode 100644 index 0000000..57393b2 --- /dev/null +++ b/SCrawler/DownloadSavedPostsForm.vb @@ -0,0 +1,157 @@ +' Copyright (C) 2022 Andy +' 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 System.Threading +Imports PersonalUtilities.Forms +Imports PersonalUtilities.Forms.Toolbars +Imports SCrawler.API +Imports Job = SCrawler.TDownloader.Job +Friend Class DownloadSavedPostsForm + Friend Event OnDownloadDone(ByVal Message As String) + Private MyView As FormsView + Private ReadOnly ProgressReddit As MyProgress + Private ReadOnly ProgressInstgram As MyProgress + Private JobReddit As Job + Private JobInstagram As Job + Friend ReadOnly Property Working As Boolean + Get + Return JobReddit Or JobInstagram + End Get + End Property +#Region "Start and Stop functions" + Friend Overloads Sub [Stop]() + [Stop](Sites.Reddit) + [Stop](Sites.Instagram) + End Sub + Private Overloads Sub [Stop](ByVal Site As Sites) + Select Case Site + Case Sites.Reddit : If JobReddit Then JobReddit.Stop() + Case Sites.Instagram : If JobInstagram Then JobInstagram.Stop() + End Select + End Sub + Private Overloads Sub [Start]() + Start(Sites.Reddit) + Start(Sites.Instagram) + End Sub + Private Overloads Sub [Start](ByVal Site As Sites) + Select Case Site + Case Sites.Reddit : If Not JobReddit Then JobReddit.Start(New ThreadStart(Sub() DownloadData(Sites.Reddit))) + Case Sites.Instagram + If Not JobInstagram Then + If Not Downloader.Working(Sites.Instagram) Then + Downloader.InstagramSavedPostsDownloading = True + JobInstagram.Start(New ThreadStart(Sub() DownloadData(Sites.Instagram))) + Else + MsgBoxE({$"Downloading Instagram profiles still works.{vbCr}Wait for this to be done before starting.{vbCr}Operation canceled", + "Instagram saved posts"}, MsgBoxStyle.Critical) + End If + End If + End Select + End Sub +#End Region +#Region "Form functions" + Friend Sub New() + InitializeComponent() + ProgressReddit = New MyProgress(PR_REDDIT, LBL_REDDIT) + ProgressInstgram = New MyProgress(PR_INST, LBL_INST) + JobReddit = New Job(ProgressReddit) With {.Site = Sites.Reddit} + JobInstagram = New Job(ProgressInstgram) With {.Site = Sites.Instagram} + End Sub + Private Sub DownloadSavedPostsForm_Load(sender As Object, e As EventArgs) Handles Me.Load + MyView = New FormsView(Me) With {.LocationOnly = True} + MyView.ImportFromXML(Settings.Design) + MyView.SetMeSize() + End Sub + Private Sub DownloadSavedPostsForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing + e.Cancel = True + Hide() + End Sub + Private Sub DownloadSavedPostsForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed + [Stop]() + MyView.Dispose(Settings.Design) + End Sub +#End Region +#Region "Controls" + Private Sub BTT_DOWN_ALL_Click(sender As Object, e As EventArgs) Handles BTT_DOWN_ALL.Click + Start() + End Sub + Private Sub BTT_STOP_ALL_Click(sender As Object, e As EventArgs) Handles BTT_STOP_ALL.Click + [Stop]() + End Sub +#Region "Reddit" + Private Sub BTT_REDDIT_START_Click(sender As Object, e As EventArgs) Handles BTT_REDDIT_START.Click + Start(Sites.Reddit) + End Sub + Private Sub BTT_REDDIT_STOP_Click(sender As Object, e As EventArgs) Handles BTT_REDDIT_STOP.Click + [Stop](Sites.Reddit) + End Sub + Private Sub BTT_REDDIT_OPEN_Click(sender As Object, e As EventArgs) Handles BTT_REDDIT_OPEN.Click + OpenPath(Reddit.ProfileSaved.DataPath) + End Sub + Private Sub LBL_REDDIT_DoubleClick(sender As Object, e As EventArgs) Handles LBL_REDDIT.DoubleClick + OpenPath(Reddit.ProfileSaved.DataPath) + End Sub +#End Region +#Region "Instagram" + Private Sub BTT_INST_START_Click(sender As Object, e As EventArgs) Handles BTT_INST_START.Click + Start(Sites.Instagram) + End Sub + Private Sub BTT_INST_STOP_Click(sender As Object, e As EventArgs) Handles BTT_INST_STOP.Click + [Stop](Sites.Instagram) + End Sub + Private Sub BTT_INST_OPEN_Click(sender As Object, e As EventArgs) Handles BTT_INST_OPEN.Click + OpenPath(Instagram.ProfileSaved.DataPath) + End Sub + Private Sub LBL_INST_DoubleClick(sender As Object, e As EventArgs) Handles LBL_INST.DoubleClick + OpenPath(Instagram.ProfileSaved.DataPath) + End Sub +#End Region +#End Region + Private Sub DownloadData(ByVal Site As Sites) + Dim btte As Action(Of Button, Boolean) = Sub(b, e) If b.InvokeRequired Then b.Invoke(Sub() b.Enabled = e) Else b.Enabled = e + Try + Select Case Site + Case Sites.Reddit + btte(BTT_REDDIT_START, False) + btte(BTT_REDDIT_STOP, True) + JobReddit.Progress.InformationTemporary = "Reddit downloading started" + JobReddit.Start() + Reddit.ProfileSaved.Download(JobReddit.Progress, JobReddit) + Case Sites.Instagram + btte(BTT_INST_START, False) + btte(BTT_INST_STOP, True) + JobInstagram.Progress.InformationTemporary = "Instagram downloading started" + JobInstagram.Start() + Instagram.ProfileSaved.Download(JobInstagram.Progress, JobInstagram) + End Select + RaiseEvent OnDownloadDone($"Downloading saved {Site} posts is completed") + Catch ex As Exception + Select Case Site + Case Sites.Reddit : JobReddit.Progress.InformationTemporary = "Reddit downloading error" + Case Sites.Instagram : JobInstagram.Progress.InformationTemporary = "Instagram downloading error" + End Select + ErrorsDescriber.Execute(EDP.LogMessageValue, ex, {$"{Site} saved posts downloading error", "Saved posts"}) + Finally + Select Case Site + Case Sites.Reddit + JobReddit.Stopped() + btte(BTT_REDDIT_START, True) + btte(BTT_REDDIT_STOP, False) + Case Sites.Instagram + JobInstagram.Stopped() + btte(BTT_INST_START, True) + btte(BTT_INST_STOP, False) + Downloader.InstagramSavedPostsDownloading = False + End Select + End Try + End Sub + Private Sub OpenPath(ByVal f As SFile) + If f.Exists(SFO.Path, False) Then f.Open(SFO.Path) + End Sub +End Class \ No newline at end of file diff --git a/SCrawler/DownloadedInfoForm.Designer.vb b/SCrawler/DownloadedInfoForm.Designer.vb index 1abaa41..f960b36 100644 --- a/SCrawler/DownloadedInfoForm.Designer.vb +++ b/SCrawler/DownloadedInfoForm.Designer.vb @@ -14,6 +14,7 @@ Partial Friend Class DownloadedInfoForm : Inherits System.Windows.Forms.Form Private Sub InitializeComponent() Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(DownloadedInfoForm)) + Dim SEP_1 As System.Windows.Forms.ToolStripSeparator Me.ToolbarTOP = New System.Windows.Forms.ToolStrip() Me.MENU_VIEW = New System.Windows.Forms.ToolStripDropDownButton() Me.MENU_VIEW_SESSION = New System.Windows.Forms.ToolStripMenuItem() @@ -21,13 +22,15 @@ Partial Friend Class DownloadedInfoForm : Inherits System.Windows.Forms.Form Me.BTT_REFRESH = New System.Windows.Forms.ToolStripButton() Me.ToolbarBOTTOM = New System.Windows.Forms.StatusStrip() Me.LIST_DOWN = New System.Windows.Forms.ListBox() + Me.BTT_CLEAR = New System.Windows.Forms.ToolStripButton() + SEP_1 = New System.Windows.Forms.ToolStripSeparator() Me.ToolbarTOP.SuspendLayout() Me.SuspendLayout() ' 'ToolbarTOP ' Me.ToolbarTOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden - Me.ToolbarTOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.MENU_VIEW, Me.BTT_REFRESH}) + Me.ToolbarTOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.MENU_VIEW, Me.BTT_REFRESH, SEP_1, Me.BTT_CLEAR}) Me.ToolbarTOP.Location = New System.Drawing.Point(0, 0) Me.ToolbarTOP.Name = "ToolbarTOP" Me.ToolbarTOP.Size = New System.Drawing.Size(554, 25) @@ -48,7 +51,7 @@ Partial Friend Class DownloadedInfoForm : Inherits System.Windows.Forms.Form ' Me.MENU_VIEW_SESSION.AutoToolTip = True Me.MENU_VIEW_SESSION.Name = "MENU_VIEW_SESSION" - Me.MENU_VIEW_SESSION.Size = New System.Drawing.Size(180, 22) + Me.MENU_VIEW_SESSION.Size = New System.Drawing.Size(113, 22) Me.MENU_VIEW_SESSION.Text = "Session" Me.MENU_VIEW_SESSION.ToolTipText = "Show downloaded users by this session" ' @@ -56,7 +59,7 @@ Partial Friend Class DownloadedInfoForm : Inherits System.Windows.Forms.Form ' Me.MENU_VIEW_ALL.AutoToolTip = True Me.MENU_VIEW_ALL.Name = "MENU_VIEW_ALL" - Me.MENU_VIEW_ALL.Size = New System.Drawing.Size(180, 22) + Me.MENU_VIEW_ALL.Size = New System.Drawing.Size(113, 22) Me.MENU_VIEW_ALL.Text = "All" Me.MENU_VIEW_ALL.ToolTipText = "Show all users (sorted by latest download)" ' @@ -85,6 +88,21 @@ Partial Friend Class DownloadedInfoForm : Inherits System.Windows.Forms.Form Me.LIST_DOWN.Size = New System.Drawing.Size(554, 364) Me.LIST_DOWN.TabIndex = 2 ' + 'SEP_1 + ' + SEP_1.Name = "SEP_1" + SEP_1.Size = New System.Drawing.Size(6, 25) + ' + 'BTT_CLEAR + ' + Me.BTT_CLEAR.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text + Me.BTT_CLEAR.Image = CType(resources.GetObject("BTT_CLEAR.Image"), System.Drawing.Image) + Me.BTT_CLEAR.ImageTransparentColor = System.Drawing.Color.Magenta + Me.BTT_CLEAR.Name = "BTT_CLEAR" + Me.BTT_CLEAR.Size = New System.Drawing.Size(38, 22) + Me.BTT_CLEAR.Text = "Clear" + Me.BTT_CLEAR.ToolTipText = "Clear info list" + ' 'DownloadedInfoForm ' Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) @@ -112,4 +130,5 @@ Partial Friend Class DownloadedInfoForm : Inherits System.Windows.Forms.Form Private WithEvents BTT_REFRESH As ToolStripButton Private WithEvents ToolbarBOTTOM As StatusStrip Private WithEvents LIST_DOWN As ListBox + Private WithEvents BTT_CLEAR As ToolStripButton End Class \ No newline at end of file diff --git a/SCrawler/DownloadedInfoForm.resx b/SCrawler/DownloadedInfoForm.resx index fb52630..09e5614 100644 --- a/SCrawler/DownloadedInfoForm.resx +++ b/SCrawler/DownloadedInfoForm.resx @@ -134,6 +134,24 @@ mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D TgDQASA1MVpwzwAAAABJRU5ErkJggg== + + + + False + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 + 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw + bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc + VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 + c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 + Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo + mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ + kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D + TgDQASA1MVpwzwAAAABJRU5ErkJggg== diff --git a/SCrawler/DownloadedInfoForm.vb b/SCrawler/DownloadedInfoForm.vb index d96581f..269037f 100644 --- a/SCrawler/DownloadedInfoForm.vb +++ b/SCrawler/DownloadedInfoForm.vb @@ -45,6 +45,7 @@ Friend Class DownloadedInfoForm MyView.ImportFromXML(Settings.Design) MyView.SetMeSize() End If + BTT_CLEAR.Visible = ViewMode = ViewModes.Session RefillList() Catch ex As Exception End Try @@ -104,17 +105,25 @@ Friend Class DownloadedInfoForm MENU_VIEW_SESSION.Checked = True MENU_VIEW_ALL.Checked = False ViewMode = ViewModes.Session + BTT_CLEAR.Visible = True RefillList() End Sub Private Sub MENU_VIEW_ALL_Click(sender As Object, e As EventArgs) Handles MENU_VIEW_ALL.Click MENU_VIEW_SESSION.Checked = False MENU_VIEW_ALL.Checked = True ViewMode = ViewModes.All + BTT_CLEAR.Visible = False RefillList() End Sub Private Sub BTT_REFRESH_Click(sender As Object, e As EventArgs) Handles BTT_REFRESH.Click RefillList() End Sub + Private Sub BTT_CLEAR_Click(sender As Object, e As EventArgs) Handles BTT_CLEAR.Click + If LIST_DOWN.Items.Count > 0 Then + Downloader.Downloaded.Clear() + RefillList() + End If + End Sub Private _LatestSelected As Integer = -1 Private Sub LIST_DOWN_SelectedIndexChanged(sender As Object, e As EventArgs) Handles LIST_DOWN.SelectedIndexChanged _LatestSelected = LIST_DOWN.SelectedIndex diff --git a/SCrawler/Editors/CollectionEditorForm.vb b/SCrawler/Editors/CollectionEditorForm.vb index 6ee5a4c..18d98a3 100644 --- a/SCrawler/Editors/CollectionEditorForm.vb +++ b/SCrawler/Editors/CollectionEditorForm.vb @@ -6,7 +6,6 @@ ' ' This program is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY -Imports System.ComponentModel Imports PersonalUtilities.Forms Imports PersonalUtilities.Forms.Controls.Base Imports PersonalUtilities.Forms.Toolbars @@ -28,50 +27,40 @@ Namespace Editors Try With MyDefs .MyViewInitialize(Me, Settings.Design) - .MyOkCancel = New OkCancelToolbar(Me, Me, CONTAINER_MAIN.BottomToolStripPanel) - .MyOkCancel.AddThisToolbar() + .AddOkCancelToolbar() + .DelegateClosingChecker() Collections.ListAddList((From c In Settings.Users Where c.IsCollection Select c.CollectionName), LAP.NotContainsOnly, EDP.ThrowException) - If Collections.ListExists Then CMB_COLLECTIONS.Items.AddRange(From c In Collections Select New Controls.Base.ListItem(c)) + If Collections.ListExists Then Collections.Sort() : CMB_COLLECTIONS.Items.AddRange(From c In Collections Select New ListItem(c)) If Not Collection.IsEmptyString And Collections.Contains(Collection) Then CMB_COLLECTIONS.SelectedIndex = Collections.IndexOf(Collection) End With Catch ex As Exception MyDefs.InvokeLoaderError(ex) End Try End Sub - Private Sub CollectionEditorForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing - If Not BeforeCloseChecker(MyDefs.ChangesDetected) Then - e.Cancel = True - Else - Collections.Clear() - MyDefs.Dispose() - End If + Private Sub CollectionEditorForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed + Collections.Clear() End Sub Private Sub CollectionEditorForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown - If e.KeyCode = Keys.Insert Then - AddNewCollection() - e.Handled = True - Else - e.Handled = False - End If + If e.KeyCode = Keys.Insert Then AddNewCollection() : e.Handled = True Else e.Handled = False End Sub Private Sub ToolbarBttOK() Implements IOkCancelToolbar.ToolbarBttOK If CMB_COLLECTIONS.SelectedIndex >= 0 Then Collection = CMB_COLLECTIONS.Value.ToString - MyDefs.ChangesDetected = False - DialogResult = DialogResult.OK - Close() + MyDefs.CloseForm() Else - MsgBoxE("Collection does not selected", MsgBoxStyle.Exclamation) + MsgBoxE("Collection not selected", MsgBoxStyle.Exclamation) End If End Sub Private Sub ToolbarBttCancel() Implements IOkCancelToolbar.ToolbarBttCancel - MyDefs.ChangesDetected = False - DialogResult = DialogResult.Cancel - Close() + MyDefs.CloseForm(DialogResult.Cancel) End Sub Private Sub CMB_COLLECTIONS_ActionOnButtonClick(ByVal Sender As ActionButton) Handles CMB_COLLECTIONS.ActionOnButtonClick If Sender.DefaultButton = ActionButton.DefaultButtons.Add Then AddNewCollection() End Sub + Private Sub CMB_COLLECTIONS_ActionOnListDoubleClick(ByVal _Item As ListViewItem) Handles CMB_COLLECTIONS.ActionOnListDoubleClick + _Item.Selected = True + ToolbarBttOK() + End Sub Private Sub AddNewCollection() Dim c$ = InputBoxE("Enter new collection name:", "Collection name") If Not c.IsEmptyString Then diff --git a/SCrawler/Editors/GlobalSettingsForm.Designer.vb b/SCrawler/Editors/GlobalSettingsForm.Designer.vb index 0cbf873..e84d4d3 100644 --- a/SCrawler/Editors/GlobalSettingsForm.Designer.vb +++ b/SCrawler/Editors/GlobalSettingsForm.Designer.vb @@ -24,22 +24,18 @@ 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 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 Dim TT_MAIN As System.Windows.Forms.ToolTip Dim TP_CHANNELS_IMGS As System.Windows.Forms.TableLayoutPanel - Dim TAB_MAIN As System.Windows.Forms.TabControl Dim TAB_BASIS As System.Windows.Forms.TabPage Dim TAB_DEFAULTS As System.Windows.Forms.TabPage Dim TP_DEFS As System.Windows.Forms.TableLayoutPanel Dim TAB_DEFS_CHANNELS As System.Windows.Forms.TabPage Dim TP_CHANNELS As System.Windows.Forms.TableLayoutPanel Dim TAB_DEFS_REDDIT As System.Windows.Forms.TabPage - Dim TP_REDDIT As System.Windows.Forms.TableLayoutPanel Dim TAB_DEFS_TWITTER As System.Windows.Forms.TabPage - Dim TP_TWITTER As System.Windows.Forms.TableLayoutPanel - Dim TP_INSTAGRAM As System.Windows.Forms.TableLayoutPanel - 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 Me.TXT_GLOBAL_PATH = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_IMAGE_LARGE = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_IMAGE_SMALL = New PersonalUtilities.Forms.Controls.TextBoxExtended() @@ -48,6 +44,15 @@ Me.TXT_MAX_JOBS_CHANNELS = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.CH_CHECK_VER_START = New System.Windows.Forms.CheckBox() Me.TXT_IMGUR_CLIENT_ID = New PersonalUtilities.Forms.Controls.TextBoxExtended() + 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() + Me.CH_FILE_DATE = New System.Windows.Forms.CheckBox() + Me.CH_FILE_TIME = New System.Windows.Forms.CheckBox() + Me.OPT_FILE_DATE_START = New System.Windows.Forms.RadioButton() + Me.OPT_FILE_DATE_END = New System.Windows.Forms.RadioButton() + Me.CH_EXIT_CONFIRM = New System.Windows.Forms.CheckBox() + Me.CH_CLOSE_TO_TRAY = New System.Windows.Forms.CheckBox() Me.CH_COPY_CHANNEL_USER_IMAGE = New System.Windows.Forms.CheckBox() Me.CH_DEF_TEMP = New System.Windows.Forms.CheckBox() Me.CH_DOWN_IMAGES = New System.Windows.Forms.CheckBox() @@ -57,44 +62,35 @@ Me.TXT_CHANNELS_ROWS = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_CHANNELS_COLUMNS = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_CHANNEL_USER_POST_LIMIT = New PersonalUtilities.Forms.Controls.TextBoxExtended() - Me.CH_REDDIT_TEMP = New System.Windows.Forms.CheckBox() - Me.CH_REDDIT_DOWN_IMG = New System.Windows.Forms.CheckBox() - Me.CH_REDDIT_DOWN_VID = New System.Windows.Forms.CheckBox() + Me.DEFS_REDDIT = New SCrawler.Editors.SiteDefaults() Me.TXT_REDDIT_SAVED_POSTS_USER = New PersonalUtilities.Forms.Controls.TextBoxExtended() - Me.CH_TWITTER_TEMP = New System.Windows.Forms.CheckBox() - Me.CH_TWITTER_DOWN_IMG = New System.Windows.Forms.CheckBox() - Me.CH_TWITTER_DOWN_VID = New System.Windows.Forms.CheckBox() + Me.DEFS_TWITTER = New SCrawler.Editors.SiteDefaults() Me.CH_TWITTER_USER_MEDIA = New System.Windows.Forms.CheckBox() + Me.TXT_REQ_WAIT_TIMER = New PersonalUtilities.Forms.Controls.TextBoxExtended() + Me.TXT_REQ_COUNT = New PersonalUtilities.Forms.Controls.TextBoxExtended() + Me.TXT_LIMIT_TIMER = New PersonalUtilities.Forms.Controls.TextBoxExtended() + Me.TAB_MAIN = New System.Windows.Forms.TabControl() Me.TAB_DEFS_INSTAGRAM = New System.Windows.Forms.TabPage() - Me.CH_INSTA_TEMP = New System.Windows.Forms.CheckBox() - Me.CH_INSTA_DOWN_IMG = New System.Windows.Forms.CheckBox() - Me.CH_INSTA_DOWN_VID = New System.Windows.Forms.CheckBox() + Me.DEFS_INST = New SCrawler.Editors.SiteDefaults() + Me.TXT_INST_SAVED_POSTS_USER = New PersonalUtilities.Forms.Controls.TextBoxExtended() + Me.TAB_DEFS_REDGIFS = New System.Windows.Forms.TabPage() + Me.DEFS_REDGIFS = New SCrawler.Editors.SiteDefaults() Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer() - 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() - Me.CH_FILE_DATE = New System.Windows.Forms.CheckBox() - Me.CH_FILE_TIME = New System.Windows.Forms.CheckBox() - Me.OPT_FILE_DATE_START = New System.Windows.Forms.RadioButton() - Me.OPT_FILE_DATE_END = New System.Windows.Forms.RadioButton() + Me.CH_SHOW_NOTIFY = New System.Windows.Forms.CheckBox() TP_BASIS = New System.Windows.Forms.TableLayoutPanel() TP_IMAGES = New System.Windows.Forms.TableLayoutPanel() + TP_FILE_NAME = New System.Windows.Forms.TableLayoutPanel() + TP_FILE_PATTERNS = New System.Windows.Forms.TableLayoutPanel() + LBL_DATE_POS = New System.Windows.Forms.Label() TT_MAIN = New System.Windows.Forms.ToolTip(Me.components) TP_CHANNELS_IMGS = New System.Windows.Forms.TableLayoutPanel() - TAB_MAIN = New System.Windows.Forms.TabControl() TAB_BASIS = New System.Windows.Forms.TabPage() TAB_DEFAULTS = New System.Windows.Forms.TabPage() TP_DEFS = New System.Windows.Forms.TableLayoutPanel() TAB_DEFS_CHANNELS = New System.Windows.Forms.TabPage() TP_CHANNELS = New System.Windows.Forms.TableLayoutPanel() TAB_DEFS_REDDIT = New System.Windows.Forms.TabPage() - TP_REDDIT = New System.Windows.Forms.TableLayoutPanel() TAB_DEFS_TWITTER = New System.Windows.Forms.TabPage() - TP_TWITTER = New System.Windows.Forms.TableLayoutPanel() - TP_INSTAGRAM = New System.Windows.Forms.TableLayoutPanel() - TP_FILE_NAME = New System.Windows.Forms.TableLayoutPanel() - TP_FILE_PATTERNS = New System.Windows.Forms.TableLayoutPanel() - LBL_DATE_POS = New System.Windows.Forms.Label() TP_BASIS.SuspendLayout() CType(Me.TXT_GLOBAL_PATH, System.ComponentModel.ISupportInitialize).BeginInit() TP_IMAGES.SuspendLayout() @@ -104,10 +100,11 @@ CType(Me.TXT_MAX_JOBS_USERS, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_MAX_JOBS_CHANNELS, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_IMGUR_CLIENT_ID, System.ComponentModel.ISupportInitialize).BeginInit() + TP_FILE_NAME.SuspendLayout() + TP_FILE_PATTERNS.SuspendLayout() TP_CHANNELS_IMGS.SuspendLayout() CType(Me.TXT_CHANNELS_ROWS, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_CHANNELS_COLUMNS, System.ComponentModel.ISupportInitialize).BeginInit() - TAB_MAIN.SuspendLayout() TAB_BASIS.SuspendLayout() TAB_DEFAULTS.SuspendLayout() TP_DEFS.SuspendLayout() @@ -115,16 +112,20 @@ TP_CHANNELS.SuspendLayout() CType(Me.TXT_CHANNEL_USER_POST_LIMIT, System.ComponentModel.ISupportInitialize).BeginInit() TAB_DEFS_REDDIT.SuspendLayout() - TP_REDDIT.SuspendLayout() + Me.DEFS_REDDIT.SuspendLayout() CType(Me.TXT_REDDIT_SAVED_POSTS_USER, System.ComponentModel.ISupportInitialize).BeginInit() TAB_DEFS_TWITTER.SuspendLayout() - TP_TWITTER.SuspendLayout() + Me.DEFS_TWITTER.SuspendLayout() + CType(Me.TXT_REQ_WAIT_TIMER, System.ComponentModel.ISupportInitialize).BeginInit() + CType(Me.TXT_REQ_COUNT, System.ComponentModel.ISupportInitialize).BeginInit() + CType(Me.TXT_LIMIT_TIMER, System.ComponentModel.ISupportInitialize).BeginInit() + Me.TAB_MAIN.SuspendLayout() Me.TAB_DEFS_INSTAGRAM.SuspendLayout() - TP_INSTAGRAM.SuspendLayout() + Me.DEFS_INST.SuspendLayout() + CType(Me.TXT_INST_SAVED_POSTS_USER, System.ComponentModel.ISupportInitialize).BeginInit() + Me.TAB_DEFS_REDGIFS.SuspendLayout() Me.CONTAINER_MAIN.ContentPanel.SuspendLayout() Me.CONTAINER_MAIN.SuspendLayout() - TP_FILE_NAME.SuspendLayout() - TP_FILE_PATTERNS.SuspendLayout() Me.SuspendLayout() ' 'TP_BASIS @@ -141,10 +142,13 @@ TP_BASIS.Controls.Add(Me.TXT_IMGUR_CLIENT_ID, 0, 6) TP_BASIS.Controls.Add(TP_FILE_NAME, 0, 7) TP_BASIS.Controls.Add(TP_FILE_PATTERNS, 0, 8) + TP_BASIS.Controls.Add(Me.CH_EXIT_CONFIRM, 0, 9) + TP_BASIS.Controls.Add(Me.CH_CLOSE_TO_TRAY, 0, 10) + TP_BASIS.Controls.Add(Me.CH_SHOW_NOTIFY, 0, 11) 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 = 10 + 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!)) @@ -154,8 +158,11 @@ 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, 30.0!)) TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30.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, 352) + TP_BASIS.Size = New System.Drawing.Size(570, 341) TP_BASIS.TabIndex = 0 ' 'TXT_GLOBAL_PATH @@ -305,470 +312,6 @@ Me.TXT_IMGUR_CLIENT_ID.Size = New System.Drawing.Size(562, 22) Me.TXT_IMGUR_CLIENT_ID.TabIndex = 6 ' - 'CH_COPY_CHANNEL_USER_IMAGE - ' - Me.CH_COPY_CHANNEL_USER_IMAGE.AutoSize = True - Me.CH_COPY_CHANNEL_USER_IMAGE.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_COPY_CHANNEL_USER_IMAGE.Location = New System.Drawing.Point(4, 62) - Me.CH_COPY_CHANNEL_USER_IMAGE.Name = "CH_COPY_CHANNEL_USER_IMAGE" - Me.CH_COPY_CHANNEL_USER_IMAGE.Size = New System.Drawing.Size(562, 19) - Me.CH_COPY_CHANNEL_USER_IMAGE.TabIndex = 2 - Me.CH_COPY_CHANNEL_USER_IMAGE.Text = "Copy channel user image" - TT_MAIN.SetToolTip(Me.CH_COPY_CHANNEL_USER_IMAGE, "Copy image posted by user (in the channel you added from) to the user's destinati" & - "on folder.") - Me.CH_COPY_CHANNEL_USER_IMAGE.UseVisualStyleBackColor = True - ' - 'CH_DEF_TEMP - ' - Me.CH_DEF_TEMP.AutoSize = True - Me.CH_DEF_TEMP.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_DEF_TEMP.Location = New System.Drawing.Point(4, 30) - Me.CH_DEF_TEMP.Name = "CH_DEF_TEMP" - Me.CH_DEF_TEMP.Size = New System.Drawing.Size(562, 19) - Me.CH_DEF_TEMP.TabIndex = 1 - Me.CH_DEF_TEMP.Text = "Temporary" - TT_MAIN.SetToolTip(Me.CH_DEF_TEMP, "Default value when creating a new user (can be changed in the new user form)") - Me.CH_DEF_TEMP.UseVisualStyleBackColor = True - ' - 'CH_DOWN_IMAGES - ' - Me.CH_DOWN_IMAGES.AutoSize = True - Me.CH_DOWN_IMAGES.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_DOWN_IMAGES.Location = New System.Drawing.Point(4, 56) - Me.CH_DOWN_IMAGES.Name = "CH_DOWN_IMAGES" - Me.CH_DOWN_IMAGES.Size = New System.Drawing.Size(562, 19) - Me.CH_DOWN_IMAGES.TabIndex = 2 - Me.CH_DOWN_IMAGES.Text = "Download images" - TT_MAIN.SetToolTip(Me.CH_DOWN_IMAGES, "Default value when creating a new user (can be changed in the new user form)") - Me.CH_DOWN_IMAGES.UseVisualStyleBackColor = True - ' - 'CH_DOWN_VIDEOS - ' - Me.CH_DOWN_VIDEOS.AutoSize = True - Me.CH_DOWN_VIDEOS.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_DOWN_VIDEOS.Location = New System.Drawing.Point(4, 82) - Me.CH_DOWN_VIDEOS.Name = "CH_DOWN_VIDEOS" - Me.CH_DOWN_VIDEOS.Size = New System.Drawing.Size(562, 19) - Me.CH_DOWN_VIDEOS.TabIndex = 3 - Me.CH_DOWN_VIDEOS.Text = "Download videos" - TT_MAIN.SetToolTip(Me.CH_DOWN_VIDEOS, "Default value when creating a new user (can be changed in the new user form)") - Me.CH_DOWN_VIDEOS.UseVisualStyleBackColor = True - ' - 'CH_SEPARATE_VIDEO_FOLDER - ' - Me.CH_SEPARATE_VIDEO_FOLDER.AutoSize = True - Me.CH_SEPARATE_VIDEO_FOLDER.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_SEPARATE_VIDEO_FOLDER.Location = New System.Drawing.Point(4, 4) - Me.CH_SEPARATE_VIDEO_FOLDER.Name = "CH_SEPARATE_VIDEO_FOLDER" - Me.CH_SEPARATE_VIDEO_FOLDER.Size = New System.Drawing.Size(562, 19) - Me.CH_SEPARATE_VIDEO_FOLDER.TabIndex = 0 - Me.CH_SEPARATE_VIDEO_FOLDER.Text = "Separate video folders" - TT_MAIN.SetToolTip(Me.CH_SEPARATE_VIDEO_FOLDER, resources.GetString("CH_SEPARATE_VIDEO_FOLDER.ToolTip")) - Me.CH_SEPARATE_VIDEO_FOLDER.UseVisualStyleBackColor = True - ' - 'CH_CHANNELS_USERS_TEMP - ' - Me.CH_CHANNELS_USERS_TEMP.AutoSize = True - Me.CH_CHANNELS_USERS_TEMP.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_CHANNELS_USERS_TEMP.Location = New System.Drawing.Point(4, 88) - Me.CH_CHANNELS_USERS_TEMP.Name = "CH_CHANNELS_USERS_TEMP" - Me.CH_CHANNELS_USERS_TEMP.Size = New System.Drawing.Size(562, 19) - Me.CH_CHANNELS_USERS_TEMP.TabIndex = 3 - Me.CH_CHANNELS_USERS_TEMP.Text = "Create temporary users" - TT_MAIN.SetToolTip(Me.CH_CHANNELS_USERS_TEMP, "Users added from channels will be created with this parameter") - Me.CH_CHANNELS_USERS_TEMP.UseVisualStyleBackColor = True - ' - 'TP_CHANNELS_IMGS - ' - TP_CHANNELS_IMGS.ColumnCount = 2 - TP_CHANNELS_IMGS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) - TP_CHANNELS_IMGS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) - TP_CHANNELS_IMGS.Controls.Add(Me.TXT_CHANNELS_ROWS, 0, 0) - TP_CHANNELS_IMGS.Controls.Add(Me.TXT_CHANNELS_COLUMNS, 1, 0) - TP_CHANNELS_IMGS.Dock = System.Windows.Forms.DockStyle.Fill - TP_CHANNELS_IMGS.Location = New System.Drawing.Point(1, 1) - TP_CHANNELS_IMGS.Margin = New System.Windows.Forms.Padding(0) - TP_CHANNELS_IMGS.Name = "TP_CHANNELS_IMGS" - TP_CHANNELS_IMGS.RowCount = 1 - TP_CHANNELS_IMGS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_CHANNELS_IMGS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) - TP_CHANNELS_IMGS.Size = New System.Drawing.Size(568, 28) - TP_CHANNELS_IMGS.TabIndex = 0 - ' - 'TXT_CHANNELS_ROWS - ' - Me.TXT_CHANNELS_ROWS.CaptionText = "Channels rows" - Me.TXT_CHANNELS_ROWS.CaptionToolTipEnabled = True - Me.TXT_CHANNELS_ROWS.CaptionToolTipText = "How many lines of images should be shown in the channels form" - Me.TXT_CHANNELS_ROWS.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown - Me.TXT_CHANNELS_ROWS.Dock = System.Windows.Forms.DockStyle.Fill - Me.TXT_CHANNELS_ROWS.Location = New System.Drawing.Point(3, 3) - Me.TXT_CHANNELS_ROWS.Name = "TXT_CHANNELS_ROWS" - Me.TXT_CHANNELS_ROWS.Size = New System.Drawing.Size(278, 22) - Me.TXT_CHANNELS_ROWS.TabIndex = 0 - Me.TXT_CHANNELS_ROWS.Text = "0" - Me.TXT_CHANNELS_ROWS.TextBoxTextAlign = System.Windows.Forms.HorizontalAlignment.Center - ' - 'TXT_CHANNELS_COLUMNS - ' - Me.TXT_CHANNELS_COLUMNS.CaptionText = "Channels columns" - Me.TXT_CHANNELS_COLUMNS.CaptionToolTipEnabled = True - Me.TXT_CHANNELS_COLUMNS.CaptionToolTipText = "How many columns of images should be shown in the channels form" - Me.TXT_CHANNELS_COLUMNS.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown - Me.TXT_CHANNELS_COLUMNS.Dock = System.Windows.Forms.DockStyle.Fill - Me.TXT_CHANNELS_COLUMNS.Location = New System.Drawing.Point(287, 3) - Me.TXT_CHANNELS_COLUMNS.Name = "TXT_CHANNELS_COLUMNS" - Me.TXT_CHANNELS_COLUMNS.Size = New System.Drawing.Size(278, 22) - Me.TXT_CHANNELS_COLUMNS.TabIndex = 1 - Me.TXT_CHANNELS_COLUMNS.Text = "0" - Me.TXT_CHANNELS_COLUMNS.TextBoxTextAlign = System.Windows.Forms.HorizontalAlignment.Center - ' - 'TAB_MAIN - ' - TAB_MAIN.Controls.Add(TAB_BASIS) - TAB_MAIN.Controls.Add(TAB_DEFAULTS) - TAB_MAIN.Controls.Add(TAB_DEFS_CHANNELS) - TAB_MAIN.Controls.Add(TAB_DEFS_REDDIT) - TAB_MAIN.Controls.Add(TAB_DEFS_TWITTER) - TAB_MAIN.Controls.Add(Me.TAB_DEFS_INSTAGRAM) - TAB_MAIN.Dock = System.Windows.Forms.DockStyle.Fill - TAB_MAIN.Location = New System.Drawing.Point(0, 0) - TAB_MAIN.Name = "TAB_MAIN" - TAB_MAIN.SelectedIndex = 0 - TAB_MAIN.Size = New System.Drawing.Size(584, 384) - TAB_MAIN.TabIndex = 1 - ' - 'TAB_BASIS - ' - TAB_BASIS.Controls.Add(TP_BASIS) - 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, 358) - TAB_BASIS.TabIndex = 0 - TAB_BASIS.Text = "Basis" - ' - 'TAB_DEFAULTS - ' - TAB_DEFAULTS.Controls.Add(TP_DEFS) - 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, 358) - TAB_DEFAULTS.TabIndex = 1 - TAB_DEFAULTS.Text = "Defaults" - ' - 'TP_DEFS - ' - TP_DEFS.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] - TP_DEFS.ColumnCount = 1 - TP_DEFS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_DEFS.Controls.Add(Me.CH_SEPARATE_VIDEO_FOLDER, 0, 0) - TP_DEFS.Controls.Add(Me.CH_DOWN_VIDEOS, 0, 3) - TP_DEFS.Controls.Add(Me.CH_DOWN_IMAGES, 0, 2) - TP_DEFS.Controls.Add(Me.CH_DEF_TEMP, 0, 1) - 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 = 5 - 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, 352) - TP_DEFS.TabIndex = 0 - ' - 'TAB_DEFS_CHANNELS - ' - TAB_DEFS_CHANNELS.Controls.Add(TP_CHANNELS) - 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, 358) - TAB_DEFS_CHANNELS.TabIndex = 4 - TAB_DEFS_CHANNELS.Text = "Channels" - ' - 'TP_CHANNELS - ' - TP_CHANNELS.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] - TP_CHANNELS.ColumnCount = 1 - TP_CHANNELS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_CHANNELS.Controls.Add(Me.TXT_CHANNEL_USER_POST_LIMIT, 0, 1) - TP_CHANNELS.Controls.Add(TP_CHANNELS_IMGS, 0, 0) - TP_CHANNELS.Controls.Add(Me.CH_COPY_CHANNEL_USER_IMAGE, 0, 2) - TP_CHANNELS.Controls.Add(Me.CH_CHANNELS_USERS_TEMP, 0, 3) - TP_CHANNELS.Dock = System.Windows.Forms.DockStyle.Fill - TP_CHANNELS.Location = New System.Drawing.Point(3, 3) - TP_CHANNELS.Name = "TP_CHANNELS" - TP_CHANNELS.RowCount = 5 - TP_CHANNELS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) - TP_CHANNELS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.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.Absolute, 25.0!)) - TP_CHANNELS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_CHANNELS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20.0!)) - TP_CHANNELS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20.0!)) - TP_CHANNELS.Size = New System.Drawing.Size(570, 352) - TP_CHANNELS.TabIndex = 0 - ' - 'TXT_CHANNEL_USER_POST_LIMIT - ' - Me.TXT_CHANNEL_USER_POST_LIMIT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox - Me.TXT_CHANNEL_USER_POST_LIMIT.CaptionSizeType = System.Windows.Forms.SizeType.Percent - Me.TXT_CHANNEL_USER_POST_LIMIT.CaptionText = "Download limit for channel user" - Me.TXT_CHANNEL_USER_POST_LIMIT.CaptionToolTipEnabled = True - Me.TXT_CHANNEL_USER_POST_LIMIT.CaptionToolTipText = "Set a limit on the number of downloads of posts limit if the user is added from t" & - "he channel" - Me.TXT_CHANNEL_USER_POST_LIMIT.CaptionWidth = 50.0R - Me.TXT_CHANNEL_USER_POST_LIMIT.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown - Me.TXT_CHANNEL_USER_POST_LIMIT.Dock = System.Windows.Forms.DockStyle.Fill - Me.TXT_CHANNEL_USER_POST_LIMIT.Location = New System.Drawing.Point(4, 33) - Me.TXT_CHANNEL_USER_POST_LIMIT.Name = "TXT_CHANNEL_USER_POST_LIMIT" - Me.TXT_CHANNEL_USER_POST_LIMIT.NumberMaximum = New Decimal(New Integer() {1000, 0, 0, 0}) - Me.TXT_CHANNEL_USER_POST_LIMIT.NumberMinimum = New Decimal(New Integer() {1, 0, 0, 0}) - Me.TXT_CHANNEL_USER_POST_LIMIT.Size = New System.Drawing.Size(562, 22) - Me.TXT_CHANNEL_USER_POST_LIMIT.TabIndex = 1 - Me.TXT_CHANNEL_USER_POST_LIMIT.Text = "1" - Me.TXT_CHANNEL_USER_POST_LIMIT.TextBoxTextAlign = System.Windows.Forms.HorizontalAlignment.Center - ' - 'TAB_DEFS_REDDIT - ' - TAB_DEFS_REDDIT.Controls.Add(TP_REDDIT) - TAB_DEFS_REDDIT.Location = New System.Drawing.Point(4, 22) - TAB_DEFS_REDDIT.Name = "TAB_DEFS_REDDIT" - TAB_DEFS_REDDIT.Padding = New System.Windows.Forms.Padding(3) - TAB_DEFS_REDDIT.Size = New System.Drawing.Size(576, 358) - TAB_DEFS_REDDIT.TabIndex = 2 - TAB_DEFS_REDDIT.Text = "Reddit" - ' - 'TP_REDDIT - ' - TP_REDDIT.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] - TP_REDDIT.ColumnCount = 1 - TP_REDDIT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_REDDIT.Controls.Add(Me.CH_REDDIT_TEMP, 0, 0) - TP_REDDIT.Controls.Add(Me.CH_REDDIT_DOWN_IMG, 0, 1) - TP_REDDIT.Controls.Add(Me.CH_REDDIT_DOWN_VID, 0, 2) - TP_REDDIT.Controls.Add(Me.TXT_REDDIT_SAVED_POSTS_USER, 0, 3) - TP_REDDIT.Dock = System.Windows.Forms.DockStyle.Fill - TP_REDDIT.Location = New System.Drawing.Point(3, 3) - TP_REDDIT.Name = "TP_REDDIT" - TP_REDDIT.RowCount = 5 - TP_REDDIT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) - TP_REDDIT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) - TP_REDDIT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) - TP_REDDIT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) - TP_REDDIT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_REDDIT.Size = New System.Drawing.Size(570, 352) - TP_REDDIT.TabIndex = 0 - ' - 'CH_REDDIT_TEMP - ' - Me.CH_REDDIT_TEMP.AutoSize = True - Me.CH_REDDIT_TEMP.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_REDDIT_TEMP.Location = New System.Drawing.Point(4, 4) - Me.CH_REDDIT_TEMP.Name = "CH_REDDIT_TEMP" - Me.CH_REDDIT_TEMP.Size = New System.Drawing.Size(562, 19) - Me.CH_REDDIT_TEMP.TabIndex = 0 - Me.CH_REDDIT_TEMP.Text = "Temporary" - Me.CH_REDDIT_TEMP.ThreeState = True - Me.CH_REDDIT_TEMP.UseVisualStyleBackColor = True - ' - 'CH_REDDIT_DOWN_IMG - ' - Me.CH_REDDIT_DOWN_IMG.AutoSize = True - Me.CH_REDDIT_DOWN_IMG.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_REDDIT_DOWN_IMG.Location = New System.Drawing.Point(4, 30) - Me.CH_REDDIT_DOWN_IMG.Name = "CH_REDDIT_DOWN_IMG" - Me.CH_REDDIT_DOWN_IMG.Size = New System.Drawing.Size(562, 19) - Me.CH_REDDIT_DOWN_IMG.TabIndex = 1 - Me.CH_REDDIT_DOWN_IMG.Text = "Download images" - Me.CH_REDDIT_DOWN_IMG.ThreeState = True - Me.CH_REDDIT_DOWN_IMG.UseVisualStyleBackColor = True - ' - 'CH_REDDIT_DOWN_VID - ' - Me.CH_REDDIT_DOWN_VID.AutoSize = True - Me.CH_REDDIT_DOWN_VID.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_REDDIT_DOWN_VID.Location = New System.Drawing.Point(4, 56) - Me.CH_REDDIT_DOWN_VID.Name = "CH_REDDIT_DOWN_VID" - Me.CH_REDDIT_DOWN_VID.Size = New System.Drawing.Size(562, 19) - Me.CH_REDDIT_DOWN_VID.TabIndex = 2 - Me.CH_REDDIT_DOWN_VID.Text = "Download videos" - Me.CH_REDDIT_DOWN_VID.ThreeState = True - Me.CH_REDDIT_DOWN_VID.UseVisualStyleBackColor = True - ' - 'TXT_REDDIT_SAVED_POSTS_USER - ' - Me.TXT_REDDIT_SAVED_POSTS_USER.CaptionText = "Saved posts user" - Me.TXT_REDDIT_SAVED_POSTS_USER.Dock = System.Windows.Forms.DockStyle.Fill - Me.TXT_REDDIT_SAVED_POSTS_USER.Location = New System.Drawing.Point(4, 82) - Me.TXT_REDDIT_SAVED_POSTS_USER.Name = "TXT_REDDIT_SAVED_POSTS_USER" - Me.TXT_REDDIT_SAVED_POSTS_USER.Size = New System.Drawing.Size(562, 22) - Me.TXT_REDDIT_SAVED_POSTS_USER.TabIndex = 3 - ' - 'TAB_DEFS_TWITTER - ' - TAB_DEFS_TWITTER.Controls.Add(TP_TWITTER) - TAB_DEFS_TWITTER.Location = New System.Drawing.Point(4, 22) - TAB_DEFS_TWITTER.Name = "TAB_DEFS_TWITTER" - TAB_DEFS_TWITTER.Padding = New System.Windows.Forms.Padding(3) - TAB_DEFS_TWITTER.Size = New System.Drawing.Size(576, 358) - TAB_DEFS_TWITTER.TabIndex = 3 - TAB_DEFS_TWITTER.Text = "Twitter" - ' - 'TP_TWITTER - ' - TP_TWITTER.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] - TP_TWITTER.ColumnCount = 1 - TP_TWITTER.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_TWITTER.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!)) - TP_TWITTER.Controls.Add(Me.CH_TWITTER_TEMP, 0, 0) - TP_TWITTER.Controls.Add(Me.CH_TWITTER_DOWN_IMG, 0, 1) - TP_TWITTER.Controls.Add(Me.CH_TWITTER_DOWN_VID, 0, 2) - TP_TWITTER.Controls.Add(Me.CH_TWITTER_USER_MEDIA, 0, 3) - TP_TWITTER.Dock = System.Windows.Forms.DockStyle.Fill - TP_TWITTER.Location = New System.Drawing.Point(3, 3) - TP_TWITTER.Name = "TP_TWITTER" - TP_TWITTER.RowCount = 5 - TP_TWITTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) - TP_TWITTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) - TP_TWITTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) - TP_TWITTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) - TP_TWITTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_TWITTER.Size = New System.Drawing.Size(570, 352) - TP_TWITTER.TabIndex = 0 - ' - 'CH_TWITTER_TEMP - ' - Me.CH_TWITTER_TEMP.AutoSize = True - Me.CH_TWITTER_TEMP.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_TWITTER_TEMP.Location = New System.Drawing.Point(4, 4) - Me.CH_TWITTER_TEMP.Name = "CH_TWITTER_TEMP" - Me.CH_TWITTER_TEMP.Size = New System.Drawing.Size(562, 19) - Me.CH_TWITTER_TEMP.TabIndex = 0 - Me.CH_TWITTER_TEMP.Text = "Temporary" - Me.CH_TWITTER_TEMP.ThreeState = True - Me.CH_TWITTER_TEMP.UseVisualStyleBackColor = True - ' - 'CH_TWITTER_DOWN_IMG - ' - Me.CH_TWITTER_DOWN_IMG.AutoSize = True - Me.CH_TWITTER_DOWN_IMG.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_TWITTER_DOWN_IMG.Location = New System.Drawing.Point(4, 30) - Me.CH_TWITTER_DOWN_IMG.Name = "CH_TWITTER_DOWN_IMG" - Me.CH_TWITTER_DOWN_IMG.Size = New System.Drawing.Size(562, 19) - Me.CH_TWITTER_DOWN_IMG.TabIndex = 1 - Me.CH_TWITTER_DOWN_IMG.Text = "Download images" - Me.CH_TWITTER_DOWN_IMG.ThreeState = True - Me.CH_TWITTER_DOWN_IMG.UseVisualStyleBackColor = True - ' - 'CH_TWITTER_DOWN_VID - ' - Me.CH_TWITTER_DOWN_VID.AutoSize = True - Me.CH_TWITTER_DOWN_VID.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_TWITTER_DOWN_VID.Location = New System.Drawing.Point(4, 56) - Me.CH_TWITTER_DOWN_VID.Name = "CH_TWITTER_DOWN_VID" - Me.CH_TWITTER_DOWN_VID.Size = New System.Drawing.Size(562, 19) - Me.CH_TWITTER_DOWN_VID.TabIndex = 2 - Me.CH_TWITTER_DOWN_VID.Text = "Download videos" - Me.CH_TWITTER_DOWN_VID.ThreeState = True - Me.CH_TWITTER_DOWN_VID.UseVisualStyleBackColor = True - ' - 'CH_TWITTER_USER_MEDIA - ' - Me.CH_TWITTER_USER_MEDIA.AutoSize = True - Me.CH_TWITTER_USER_MEDIA.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_TWITTER_USER_MEDIA.Location = New System.Drawing.Point(4, 82) - Me.CH_TWITTER_USER_MEDIA.Name = "CH_TWITTER_USER_MEDIA" - Me.CH_TWITTER_USER_MEDIA.Size = New System.Drawing.Size(562, 19) - Me.CH_TWITTER_USER_MEDIA.TabIndex = 3 - Me.CH_TWITTER_USER_MEDIA.Text = "Get user media only" - Me.CH_TWITTER_USER_MEDIA.UseVisualStyleBackColor = True - ' - 'TAB_DEFS_INSTAGRAM - ' - Me.TAB_DEFS_INSTAGRAM.BackColor = System.Drawing.SystemColors.Control - Me.TAB_DEFS_INSTAGRAM.Controls.Add(TP_INSTAGRAM) - Me.TAB_DEFS_INSTAGRAM.Location = New System.Drawing.Point(4, 22) - Me.TAB_DEFS_INSTAGRAM.Name = "TAB_DEFS_INSTAGRAM" - Me.TAB_DEFS_INSTAGRAM.Size = New System.Drawing.Size(576, 358) - Me.TAB_DEFS_INSTAGRAM.TabIndex = 5 - Me.TAB_DEFS_INSTAGRAM.Text = "Instagram" - ' - 'TP_INSTAGRAM - ' - TP_INSTAGRAM.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] - TP_INSTAGRAM.ColumnCount = 1 - TP_INSTAGRAM.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_INSTAGRAM.Controls.Add(Me.CH_INSTA_TEMP, 0, 0) - TP_INSTAGRAM.Controls.Add(Me.CH_INSTA_DOWN_IMG, 0, 1) - TP_INSTAGRAM.Controls.Add(Me.CH_INSTA_DOWN_VID, 0, 2) - TP_INSTAGRAM.Dock = System.Windows.Forms.DockStyle.Fill - TP_INSTAGRAM.Location = New System.Drawing.Point(0, 0) - TP_INSTAGRAM.Name = "TP_INSTAGRAM" - TP_INSTAGRAM.RowCount = 4 - TP_INSTAGRAM.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) - TP_INSTAGRAM.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) - TP_INSTAGRAM.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) - TP_INSTAGRAM.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_INSTAGRAM.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20.0!)) - TP_INSTAGRAM.Size = New System.Drawing.Size(576, 358) - TP_INSTAGRAM.TabIndex = 0 - ' - 'CH_INSTA_TEMP - ' - Me.CH_INSTA_TEMP.AutoSize = True - Me.CH_INSTA_TEMP.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_INSTA_TEMP.Location = New System.Drawing.Point(4, 4) - Me.CH_INSTA_TEMP.Name = "CH_INSTA_TEMP" - Me.CH_INSTA_TEMP.Size = New System.Drawing.Size(568, 19) - Me.CH_INSTA_TEMP.TabIndex = 0 - Me.CH_INSTA_TEMP.Text = "Temporary" - Me.CH_INSTA_TEMP.ThreeState = True - Me.CH_INSTA_TEMP.UseVisualStyleBackColor = True - ' - 'CH_INSTA_DOWN_IMG - ' - Me.CH_INSTA_DOWN_IMG.AutoSize = True - Me.CH_INSTA_DOWN_IMG.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_INSTA_DOWN_IMG.Location = New System.Drawing.Point(4, 30) - Me.CH_INSTA_DOWN_IMG.Name = "CH_INSTA_DOWN_IMG" - Me.CH_INSTA_DOWN_IMG.Size = New System.Drawing.Size(568, 19) - Me.CH_INSTA_DOWN_IMG.TabIndex = 1 - Me.CH_INSTA_DOWN_IMG.Text = "Download images" - Me.CH_INSTA_DOWN_IMG.ThreeState = True - Me.CH_INSTA_DOWN_IMG.UseVisualStyleBackColor = True - ' - 'CH_INSTA_DOWN_VID - ' - Me.CH_INSTA_DOWN_VID.AutoSize = True - Me.CH_INSTA_DOWN_VID.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_INSTA_DOWN_VID.Location = New System.Drawing.Point(4, 56) - Me.CH_INSTA_DOWN_VID.Name = "CH_INSTA_DOWN_VID" - Me.CH_INSTA_DOWN_VID.Size = New System.Drawing.Size(568, 19) - Me.CH_INSTA_DOWN_VID.TabIndex = 2 - Me.CH_INSTA_DOWN_VID.Text = "Download videos" - Me.CH_INSTA_DOWN_VID.ThreeState = True - Me.CH_INSTA_DOWN_VID.UseVisualStyleBackColor = True - ' - 'CONTAINER_MAIN - ' - ' - 'CONTAINER_MAIN.ContentPanel - ' - Me.CONTAINER_MAIN.ContentPanel.Controls.Add(TAB_MAIN) - Me.CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(584, 384) - 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, 384) - Me.CONTAINER_MAIN.TabIndex = 0 - Me.CONTAINER_MAIN.TopToolStripPanelVisible = False - ' 'TP_FILE_NAME ' TP_FILE_NAME.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] @@ -904,19 +447,473 @@ Me.OPT_FILE_DATE_END.Text = "End" Me.OPT_FILE_DATE_END.UseVisualStyleBackColor = True ' + 'CH_EXIT_CONFIRM + ' + Me.CH_EXIT_CONFIRM.AutoSize = True + Me.CH_EXIT_CONFIRM.Dock = System.Windows.Forms.DockStyle.Fill + Me.CH_EXIT_CONFIRM.Location = New System.Drawing.Point(4, 266) + Me.CH_EXIT_CONFIRM.Name = "CH_EXIT_CONFIRM" + Me.CH_EXIT_CONFIRM.Size = New System.Drawing.Size(562, 19) + Me.CH_EXIT_CONFIRM.TabIndex = 9 + Me.CH_EXIT_CONFIRM.Text = "Exit confirm" + Me.CH_EXIT_CONFIRM.UseVisualStyleBackColor = True + ' + 'CH_CLOSE_TO_TRAY + ' + Me.CH_CLOSE_TO_TRAY.AutoSize = True + Me.CH_CLOSE_TO_TRAY.Dock = System.Windows.Forms.DockStyle.Fill + Me.CH_CLOSE_TO_TRAY.Location = New System.Drawing.Point(4, 292) + Me.CH_CLOSE_TO_TRAY.Name = "CH_CLOSE_TO_TRAY" + Me.CH_CLOSE_TO_TRAY.Size = New System.Drawing.Size(562, 19) + Me.CH_CLOSE_TO_TRAY.TabIndex = 10 + Me.CH_CLOSE_TO_TRAY.Text = "Close to tray" + Me.CH_CLOSE_TO_TRAY.UseVisualStyleBackColor = True + ' + 'CH_COPY_CHANNEL_USER_IMAGE + ' + Me.CH_COPY_CHANNEL_USER_IMAGE.AutoSize = True + Me.CH_COPY_CHANNEL_USER_IMAGE.Dock = System.Windows.Forms.DockStyle.Fill + Me.CH_COPY_CHANNEL_USER_IMAGE.Location = New System.Drawing.Point(4, 62) + Me.CH_COPY_CHANNEL_USER_IMAGE.Name = "CH_COPY_CHANNEL_USER_IMAGE" + Me.CH_COPY_CHANNEL_USER_IMAGE.Size = New System.Drawing.Size(562, 19) + Me.CH_COPY_CHANNEL_USER_IMAGE.TabIndex = 2 + Me.CH_COPY_CHANNEL_USER_IMAGE.Text = "Copy channel user image" + TT_MAIN.SetToolTip(Me.CH_COPY_CHANNEL_USER_IMAGE, "Copy image posted by user (in the channel you added from) to the user's destinati" & + "on folder.") + Me.CH_COPY_CHANNEL_USER_IMAGE.UseVisualStyleBackColor = True + ' + 'CH_DEF_TEMP + ' + Me.CH_DEF_TEMP.AutoSize = True + Me.CH_DEF_TEMP.Dock = System.Windows.Forms.DockStyle.Fill + Me.CH_DEF_TEMP.Location = New System.Drawing.Point(4, 30) + Me.CH_DEF_TEMP.Name = "CH_DEF_TEMP" + Me.CH_DEF_TEMP.Size = New System.Drawing.Size(562, 19) + Me.CH_DEF_TEMP.TabIndex = 1 + Me.CH_DEF_TEMP.Text = "Temporary" + TT_MAIN.SetToolTip(Me.CH_DEF_TEMP, "Default value when creating a new user (can be changed in the new user form)") + Me.CH_DEF_TEMP.UseVisualStyleBackColor = True + ' + 'CH_DOWN_IMAGES + ' + Me.CH_DOWN_IMAGES.AutoSize = True + Me.CH_DOWN_IMAGES.Dock = System.Windows.Forms.DockStyle.Fill + Me.CH_DOWN_IMAGES.Location = New System.Drawing.Point(4, 56) + Me.CH_DOWN_IMAGES.Name = "CH_DOWN_IMAGES" + Me.CH_DOWN_IMAGES.Size = New System.Drawing.Size(562, 19) + Me.CH_DOWN_IMAGES.TabIndex = 2 + Me.CH_DOWN_IMAGES.Text = "Download images" + TT_MAIN.SetToolTip(Me.CH_DOWN_IMAGES, "Default value when creating a new user (can be changed in the new user form)") + Me.CH_DOWN_IMAGES.UseVisualStyleBackColor = True + ' + 'CH_DOWN_VIDEOS + ' + Me.CH_DOWN_VIDEOS.AutoSize = True + Me.CH_DOWN_VIDEOS.Dock = System.Windows.Forms.DockStyle.Fill + Me.CH_DOWN_VIDEOS.Location = New System.Drawing.Point(4, 82) + Me.CH_DOWN_VIDEOS.Name = "CH_DOWN_VIDEOS" + Me.CH_DOWN_VIDEOS.Size = New System.Drawing.Size(562, 19) + Me.CH_DOWN_VIDEOS.TabIndex = 3 + Me.CH_DOWN_VIDEOS.Text = "Download videos" + TT_MAIN.SetToolTip(Me.CH_DOWN_VIDEOS, "Default value when creating a new user (can be changed in the new user form)") + Me.CH_DOWN_VIDEOS.UseVisualStyleBackColor = True + ' + 'CH_SEPARATE_VIDEO_FOLDER + ' + Me.CH_SEPARATE_VIDEO_FOLDER.AutoSize = True + Me.CH_SEPARATE_VIDEO_FOLDER.Dock = System.Windows.Forms.DockStyle.Fill + Me.CH_SEPARATE_VIDEO_FOLDER.Location = New System.Drawing.Point(4, 4) + Me.CH_SEPARATE_VIDEO_FOLDER.Name = "CH_SEPARATE_VIDEO_FOLDER" + Me.CH_SEPARATE_VIDEO_FOLDER.Size = New System.Drawing.Size(562, 19) + Me.CH_SEPARATE_VIDEO_FOLDER.TabIndex = 0 + Me.CH_SEPARATE_VIDEO_FOLDER.Text = "Separate video folders" + TT_MAIN.SetToolTip(Me.CH_SEPARATE_VIDEO_FOLDER, resources.GetString("CH_SEPARATE_VIDEO_FOLDER.ToolTip")) + Me.CH_SEPARATE_VIDEO_FOLDER.UseVisualStyleBackColor = True + ' + 'CH_CHANNELS_USERS_TEMP + ' + Me.CH_CHANNELS_USERS_TEMP.AutoSize = True + Me.CH_CHANNELS_USERS_TEMP.Dock = System.Windows.Forms.DockStyle.Fill + Me.CH_CHANNELS_USERS_TEMP.Location = New System.Drawing.Point(4, 88) + Me.CH_CHANNELS_USERS_TEMP.Name = "CH_CHANNELS_USERS_TEMP" + Me.CH_CHANNELS_USERS_TEMP.Size = New System.Drawing.Size(562, 19) + Me.CH_CHANNELS_USERS_TEMP.TabIndex = 3 + Me.CH_CHANNELS_USERS_TEMP.Text = "Create temporary users" + TT_MAIN.SetToolTip(Me.CH_CHANNELS_USERS_TEMP, "Users added from channels will be created with this parameter") + Me.CH_CHANNELS_USERS_TEMP.UseVisualStyleBackColor = True + ' + 'TP_CHANNELS_IMGS + ' + TP_CHANNELS_IMGS.ColumnCount = 2 + TP_CHANNELS_IMGS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) + TP_CHANNELS_IMGS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) + TP_CHANNELS_IMGS.Controls.Add(Me.TXT_CHANNELS_ROWS, 0, 0) + TP_CHANNELS_IMGS.Controls.Add(Me.TXT_CHANNELS_COLUMNS, 1, 0) + TP_CHANNELS_IMGS.Dock = System.Windows.Forms.DockStyle.Fill + TP_CHANNELS_IMGS.Location = New System.Drawing.Point(1, 1) + TP_CHANNELS_IMGS.Margin = New System.Windows.Forms.Padding(0) + TP_CHANNELS_IMGS.Name = "TP_CHANNELS_IMGS" + TP_CHANNELS_IMGS.RowCount = 1 + TP_CHANNELS_IMGS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + TP_CHANNELS_IMGS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) + TP_CHANNELS_IMGS.Size = New System.Drawing.Size(568, 28) + TP_CHANNELS_IMGS.TabIndex = 0 + ' + 'TXT_CHANNELS_ROWS + ' + Me.TXT_CHANNELS_ROWS.CaptionText = "Channels rows" + Me.TXT_CHANNELS_ROWS.CaptionToolTipEnabled = True + Me.TXT_CHANNELS_ROWS.CaptionToolTipText = "How many lines of images should be shown in the channels form" + Me.TXT_CHANNELS_ROWS.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown + Me.TXT_CHANNELS_ROWS.Dock = System.Windows.Forms.DockStyle.Fill + Me.TXT_CHANNELS_ROWS.Location = New System.Drawing.Point(3, 3) + Me.TXT_CHANNELS_ROWS.Name = "TXT_CHANNELS_ROWS" + Me.TXT_CHANNELS_ROWS.Size = New System.Drawing.Size(278, 22) + Me.TXT_CHANNELS_ROWS.TabIndex = 0 + Me.TXT_CHANNELS_ROWS.Text = "0" + Me.TXT_CHANNELS_ROWS.TextBoxTextAlign = System.Windows.Forms.HorizontalAlignment.Center + ' + 'TXT_CHANNELS_COLUMNS + ' + Me.TXT_CHANNELS_COLUMNS.CaptionText = "Channels columns" + Me.TXT_CHANNELS_COLUMNS.CaptionToolTipEnabled = True + Me.TXT_CHANNELS_COLUMNS.CaptionToolTipText = "How many columns of images should be shown in the channels form" + Me.TXT_CHANNELS_COLUMNS.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown + Me.TXT_CHANNELS_COLUMNS.Dock = System.Windows.Forms.DockStyle.Fill + Me.TXT_CHANNELS_COLUMNS.Location = New System.Drawing.Point(287, 3) + Me.TXT_CHANNELS_COLUMNS.Name = "TXT_CHANNELS_COLUMNS" + Me.TXT_CHANNELS_COLUMNS.Size = New System.Drawing.Size(278, 22) + Me.TXT_CHANNELS_COLUMNS.TabIndex = 1 + Me.TXT_CHANNELS_COLUMNS.Text = "0" + Me.TXT_CHANNELS_COLUMNS.TextBoxTextAlign = System.Windows.Forms.HorizontalAlignment.Center + ' + 'TAB_BASIS + ' + TAB_BASIS.Controls.Add(TP_BASIS) + 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, 347) + TAB_BASIS.TabIndex = 0 + TAB_BASIS.Text = "Basis" + ' + 'TAB_DEFAULTS + ' + TAB_DEFAULTS.Controls.Add(TP_DEFS) + 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, 358) + TAB_DEFAULTS.TabIndex = 1 + TAB_DEFAULTS.Text = "Defaults" + ' + 'TP_DEFS + ' + TP_DEFS.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] + TP_DEFS.ColumnCount = 1 + TP_DEFS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + TP_DEFS.Controls.Add(Me.CH_SEPARATE_VIDEO_FOLDER, 0, 0) + TP_DEFS.Controls.Add(Me.CH_DOWN_VIDEOS, 0, 3) + TP_DEFS.Controls.Add(Me.CH_DOWN_IMAGES, 0, 2) + TP_DEFS.Controls.Add(Me.CH_DEF_TEMP, 0, 1) + 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 = 5 + 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, 352) + TP_DEFS.TabIndex = 0 + ' + 'TAB_DEFS_CHANNELS + ' + TAB_DEFS_CHANNELS.Controls.Add(TP_CHANNELS) + 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, 358) + TAB_DEFS_CHANNELS.TabIndex = 4 + TAB_DEFS_CHANNELS.Text = "Channels" + ' + 'TP_CHANNELS + ' + TP_CHANNELS.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] + TP_CHANNELS.ColumnCount = 1 + TP_CHANNELS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + TP_CHANNELS.Controls.Add(Me.TXT_CHANNEL_USER_POST_LIMIT, 0, 1) + TP_CHANNELS.Controls.Add(TP_CHANNELS_IMGS, 0, 0) + TP_CHANNELS.Controls.Add(Me.CH_COPY_CHANNEL_USER_IMAGE, 0, 2) + TP_CHANNELS.Controls.Add(Me.CH_CHANNELS_USERS_TEMP, 0, 3) + TP_CHANNELS.Dock = System.Windows.Forms.DockStyle.Fill + TP_CHANNELS.Location = New System.Drawing.Point(3, 3) + TP_CHANNELS.Name = "TP_CHANNELS" + TP_CHANNELS.RowCount = 5 + TP_CHANNELS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) + TP_CHANNELS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.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.Absolute, 25.0!)) + TP_CHANNELS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + TP_CHANNELS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20.0!)) + TP_CHANNELS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20.0!)) + TP_CHANNELS.Size = New System.Drawing.Size(570, 352) + TP_CHANNELS.TabIndex = 0 + ' + 'TXT_CHANNEL_USER_POST_LIMIT + ' + Me.TXT_CHANNEL_USER_POST_LIMIT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox + Me.TXT_CHANNEL_USER_POST_LIMIT.CaptionSizeType = System.Windows.Forms.SizeType.Percent + Me.TXT_CHANNEL_USER_POST_LIMIT.CaptionText = "Download limit for channel user" + Me.TXT_CHANNEL_USER_POST_LIMIT.CaptionToolTipEnabled = True + Me.TXT_CHANNEL_USER_POST_LIMIT.CaptionToolTipText = "Set a limit on the number of downloads of posts limit if the user is added from t" & + "he channel" + Me.TXT_CHANNEL_USER_POST_LIMIT.CaptionWidth = 50.0R + Me.TXT_CHANNEL_USER_POST_LIMIT.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown + Me.TXT_CHANNEL_USER_POST_LIMIT.Dock = System.Windows.Forms.DockStyle.Fill + Me.TXT_CHANNEL_USER_POST_LIMIT.Location = New System.Drawing.Point(4, 33) + Me.TXT_CHANNEL_USER_POST_LIMIT.Name = "TXT_CHANNEL_USER_POST_LIMIT" + Me.TXT_CHANNEL_USER_POST_LIMIT.NumberMaximum = New Decimal(New Integer() {1000, 0, 0, 0}) + Me.TXT_CHANNEL_USER_POST_LIMIT.NumberMinimum = New Decimal(New Integer() {1, 0, 0, 0}) + Me.TXT_CHANNEL_USER_POST_LIMIT.Size = New System.Drawing.Size(562, 22) + Me.TXT_CHANNEL_USER_POST_LIMIT.TabIndex = 1 + Me.TXT_CHANNEL_USER_POST_LIMIT.Text = "1" + Me.TXT_CHANNEL_USER_POST_LIMIT.TextBoxTextAlign = System.Windows.Forms.HorizontalAlignment.Center + ' + 'TAB_DEFS_REDDIT + ' + TAB_DEFS_REDDIT.Controls.Add(Me.DEFS_REDDIT) + TAB_DEFS_REDDIT.Location = New System.Drawing.Point(4, 22) + TAB_DEFS_REDDIT.Name = "TAB_DEFS_REDDIT" + TAB_DEFS_REDDIT.Padding = New System.Windows.Forms.Padding(3) + TAB_DEFS_REDDIT.Size = New System.Drawing.Size(576, 358) + TAB_DEFS_REDDIT.TabIndex = 2 + TAB_DEFS_REDDIT.Text = "Reddit" + ' + 'DEFS_REDDIT + ' + Me.DEFS_REDDIT.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] + Me.DEFS_REDDIT.ColumnCount = 1 + Me.DEFS_REDDIT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + Me.DEFS_REDDIT.Controls.Add(Me.TXT_REDDIT_SAVED_POSTS_USER, 0, 3) + Me.DEFS_REDDIT.Dock = System.Windows.Forms.DockStyle.Fill + Me.DEFS_REDDIT.Location = New System.Drawing.Point(3, 3) + Me.DEFS_REDDIT.Name = "DEFS_REDDIT" + Me.DEFS_REDDIT.RowCount = 5 + Me.DEFS_REDDIT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) + Me.DEFS_REDDIT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) + Me.DEFS_REDDIT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) + Me.DEFS_REDDIT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) + Me.DEFS_REDDIT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + Me.DEFS_REDDIT.Size = New System.Drawing.Size(570, 352) + Me.DEFS_REDDIT.TabIndex = 1 + ' + 'TXT_REDDIT_SAVED_POSTS_USER + ' + Me.TXT_REDDIT_SAVED_POSTS_USER.CaptionText = "Saved posts user" + Me.TXT_REDDIT_SAVED_POSTS_USER.Dock = System.Windows.Forms.DockStyle.Fill + Me.TXT_REDDIT_SAVED_POSTS_USER.Location = New System.Drawing.Point(4, 82) + Me.TXT_REDDIT_SAVED_POSTS_USER.Name = "TXT_REDDIT_SAVED_POSTS_USER" + Me.TXT_REDDIT_SAVED_POSTS_USER.Size = New System.Drawing.Size(562, 22) + Me.TXT_REDDIT_SAVED_POSTS_USER.TabIndex = 3 + ' + 'TAB_DEFS_TWITTER + ' + TAB_DEFS_TWITTER.Controls.Add(Me.DEFS_TWITTER) + TAB_DEFS_TWITTER.Location = New System.Drawing.Point(4, 22) + TAB_DEFS_TWITTER.Name = "TAB_DEFS_TWITTER" + TAB_DEFS_TWITTER.Padding = New System.Windows.Forms.Padding(3) + TAB_DEFS_TWITTER.Size = New System.Drawing.Size(576, 358) + TAB_DEFS_TWITTER.TabIndex = 3 + TAB_DEFS_TWITTER.Text = "Twitter" + ' + 'DEFS_TWITTER + ' + Me.DEFS_TWITTER.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] + Me.DEFS_TWITTER.ColumnCount = 1 + Me.DEFS_TWITTER.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + Me.DEFS_TWITTER.Controls.Add(Me.CH_TWITTER_USER_MEDIA, 0, 3) + Me.DEFS_TWITTER.Dock = System.Windows.Forms.DockStyle.Fill + Me.DEFS_TWITTER.Location = New System.Drawing.Point(3, 3) + Me.DEFS_TWITTER.Name = "DEFS_TWITTER" + Me.DEFS_TWITTER.RowCount = 5 + Me.DEFS_TWITTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) + Me.DEFS_TWITTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) + Me.DEFS_TWITTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) + Me.DEFS_TWITTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) + Me.DEFS_TWITTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + Me.DEFS_TWITTER.Size = New System.Drawing.Size(570, 352) + Me.DEFS_TWITTER.TabIndex = 1 + ' + 'CH_TWITTER_USER_MEDIA + ' + Me.CH_TWITTER_USER_MEDIA.AutoSize = True + Me.CH_TWITTER_USER_MEDIA.Dock = System.Windows.Forms.DockStyle.Fill + Me.CH_TWITTER_USER_MEDIA.Location = New System.Drawing.Point(4, 82) + Me.CH_TWITTER_USER_MEDIA.Name = "CH_TWITTER_USER_MEDIA" + Me.CH_TWITTER_USER_MEDIA.Size = New System.Drawing.Size(562, 19) + Me.CH_TWITTER_USER_MEDIA.TabIndex = 3 + Me.CH_TWITTER_USER_MEDIA.Text = "Get user media only" + Me.CH_TWITTER_USER_MEDIA.UseVisualStyleBackColor = True + ' + 'TXT_REQ_WAIT_TIMER + ' + Me.TXT_REQ_WAIT_TIMER.CaptionText = "Request timer" + Me.TXT_REQ_WAIT_TIMER.CaptionWidth = 120.0R + Me.TXT_REQ_WAIT_TIMER.Dock = System.Windows.Forms.DockStyle.Fill + Me.TXT_REQ_WAIT_TIMER.Location = New System.Drawing.Point(4, 82) + Me.TXT_REQ_WAIT_TIMER.Name = "TXT_REQ_WAIT_TIMER" + Me.TXT_REQ_WAIT_TIMER.Size = New System.Drawing.Size(568, 22) + Me.TXT_REQ_WAIT_TIMER.TabIndex = 3 + ' + 'TXT_REQ_COUNT + ' + Me.TXT_REQ_COUNT.CaptionText = "Request timer counter" + Me.TXT_REQ_COUNT.CaptionWidth = 120.0R + Me.TXT_REQ_COUNT.Dock = System.Windows.Forms.DockStyle.Fill + Me.TXT_REQ_COUNT.Location = New System.Drawing.Point(4, 111) + Me.TXT_REQ_COUNT.Name = "TXT_REQ_COUNT" + Me.TXT_REQ_COUNT.Size = New System.Drawing.Size(568, 22) + Me.TXT_REQ_COUNT.TabIndex = 4 + ' + 'TXT_LIMIT_TIMER + ' + Me.TXT_LIMIT_TIMER.CaptionText = "Posts limit timer" + Me.TXT_LIMIT_TIMER.CaptionWidth = 120.0R + Me.TXT_LIMIT_TIMER.Dock = System.Windows.Forms.DockStyle.Fill + Me.TXT_LIMIT_TIMER.Location = New System.Drawing.Point(4, 140) + Me.TXT_LIMIT_TIMER.Name = "TXT_LIMIT_TIMER" + Me.TXT_LIMIT_TIMER.Size = New System.Drawing.Size(568, 22) + Me.TXT_LIMIT_TIMER.TabIndex = 5 + ' + 'TAB_MAIN + ' + Me.TAB_MAIN.Controls.Add(TAB_BASIS) + Me.TAB_MAIN.Controls.Add(TAB_DEFAULTS) + Me.TAB_MAIN.Controls.Add(TAB_DEFS_CHANNELS) + Me.TAB_MAIN.Controls.Add(TAB_DEFS_REDDIT) + Me.TAB_MAIN.Controls.Add(TAB_DEFS_TWITTER) + Me.TAB_MAIN.Controls.Add(Me.TAB_DEFS_INSTAGRAM) + Me.TAB_MAIN.Controls.Add(Me.TAB_DEFS_REDGIFS) + Me.TAB_MAIN.Dock = System.Windows.Forms.DockStyle.Fill + 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, 373) + Me.TAB_MAIN.TabIndex = 1 + ' + 'TAB_DEFS_INSTAGRAM + ' + Me.TAB_DEFS_INSTAGRAM.BackColor = System.Drawing.SystemColors.Control + Me.TAB_DEFS_INSTAGRAM.Controls.Add(Me.DEFS_INST) + Me.TAB_DEFS_INSTAGRAM.Location = New System.Drawing.Point(4, 22) + Me.TAB_DEFS_INSTAGRAM.Name = "TAB_DEFS_INSTAGRAM" + Me.TAB_DEFS_INSTAGRAM.Size = New System.Drawing.Size(576, 358) + Me.TAB_DEFS_INSTAGRAM.TabIndex = 5 + Me.TAB_DEFS_INSTAGRAM.Text = "Instagram" + ' + 'DEFS_INST + ' + Me.DEFS_INST.BaseControlsPadding = New System.Windows.Forms.Padding(120, 0, 0, 0) + Me.DEFS_INST.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] + Me.DEFS_INST.ColumnCount = 1 + Me.DEFS_INST.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + Me.DEFS_INST.Controls.Add(Me.TXT_LIMIT_TIMER, 0, 5) + Me.DEFS_INST.Controls.Add(Me.TXT_REQ_COUNT, 0, 4) + Me.DEFS_INST.Controls.Add(Me.TXT_REQ_WAIT_TIMER, 0, 3) + Me.DEFS_INST.Controls.Add(Me.TXT_INST_SAVED_POSTS_USER, 0, 6) + Me.DEFS_INST.Dock = System.Windows.Forms.DockStyle.Fill + Me.DEFS_INST.Location = New System.Drawing.Point(0, 0) + Me.DEFS_INST.Name = "DEFS_INST" + Me.DEFS_INST.RowCount = 8 + Me.DEFS_INST.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) + Me.DEFS_INST.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) + Me.DEFS_INST.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) + Me.DEFS_INST.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) + Me.DEFS_INST.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) + Me.DEFS_INST.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) + Me.DEFS_INST.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) + Me.DEFS_INST.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + Me.DEFS_INST.Size = New System.Drawing.Size(576, 358) + Me.DEFS_INST.TabIndex = 1 + ' + 'TXT_INST_SAVED_POSTS_USER + ' + Me.TXT_INST_SAVED_POSTS_USER.CaptionText = "Saved posts user" + Me.TXT_INST_SAVED_POSTS_USER.CaptionWidth = 120.0R + Me.TXT_INST_SAVED_POSTS_USER.Dock = System.Windows.Forms.DockStyle.Fill + Me.TXT_INST_SAVED_POSTS_USER.Location = New System.Drawing.Point(4, 169) + Me.TXT_INST_SAVED_POSTS_USER.Name = "TXT_INST_SAVED_POSTS_USER" + Me.TXT_INST_SAVED_POSTS_USER.Size = New System.Drawing.Size(568, 22) + Me.TXT_INST_SAVED_POSTS_USER.TabIndex = 9 + ' + 'TAB_DEFS_REDGIFS + ' + Me.TAB_DEFS_REDGIFS.BackColor = System.Drawing.SystemColors.Control + Me.TAB_DEFS_REDGIFS.Controls.Add(Me.DEFS_REDGIFS) + Me.TAB_DEFS_REDGIFS.Location = New System.Drawing.Point(4, 22) + Me.TAB_DEFS_REDGIFS.Name = "TAB_DEFS_REDGIFS" + Me.TAB_DEFS_REDGIFS.Size = New System.Drawing.Size(576, 358) + Me.TAB_DEFS_REDGIFS.TabIndex = 6 + Me.TAB_DEFS_REDGIFS.Text = "RedGifs" + ' + 'DEFS_REDGIFS + ' + Me.DEFS_REDGIFS.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] + Me.DEFS_REDGIFS.ColumnCount = 1 + Me.DEFS_REDGIFS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + Me.DEFS_REDGIFS.Dock = System.Windows.Forms.DockStyle.Fill + Me.DEFS_REDGIFS.Location = New System.Drawing.Point(0, 0) + Me.DEFS_REDGIFS.Name = "DEFS_REDGIFS" + Me.DEFS_REDGIFS.RowCount = 4 + Me.DEFS_REDGIFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) + Me.DEFS_REDGIFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) + Me.DEFS_REDGIFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) + Me.DEFS_REDGIFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + Me.DEFS_REDGIFS.Size = New System.Drawing.Size(576, 358) + Me.DEFS_REDGIFS.TabIndex = 0 + ' + 'CONTAINER_MAIN + ' + ' + 'CONTAINER_MAIN.ContentPanel + ' + Me.CONTAINER_MAIN.ContentPanel.Controls.Add(Me.TAB_MAIN) + Me.CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(584, 373) + 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, 398) + Me.CONTAINER_MAIN.TabIndex = 0 + Me.CONTAINER_MAIN.TopToolStripPanelVisible = False + ' + 'CH_SHOW_NOTIFY + ' + Me.CH_SHOW_NOTIFY.AutoSize = True + Me.CH_SHOW_NOTIFY.Dock = System.Windows.Forms.DockStyle.Fill + Me.CH_SHOW_NOTIFY.Location = New System.Drawing.Point(4, 318) + Me.CH_SHOW_NOTIFY.Name = "CH_SHOW_NOTIFY" + Me.CH_SHOW_NOTIFY.Size = New System.Drawing.Size(562, 19) + Me.CH_SHOW_NOTIFY.TabIndex = 11 + Me.CH_SHOW_NOTIFY.Text = "Show notifications" + Me.CH_SHOW_NOTIFY.UseVisualStyleBackColor = True + ' 'GlobalSettingsForm ' Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font - Me.ClientSize = New System.Drawing.Size(584, 384) + Me.ClientSize = New System.Drawing.Size(584, 398) Me.Controls.Add(Me.CONTAINER_MAIN) Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon) Me.KeyPreview = True Me.MaximizeBox = False - Me.MaximumSize = New System.Drawing.Size(600, 423) + Me.MaximumSize = New System.Drawing.Size(600, 437) Me.MinimizeBox = False - Me.MinimumSize = New System.Drawing.Size(600, 423) + Me.MinimumSize = New System.Drawing.Size(600, 437) Me.Name = "GlobalSettingsForm" Me.ShowInTaskbar = False Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide @@ -931,10 +928,13 @@ CType(Me.TXT_MAX_JOBS_USERS, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_MAX_JOBS_CHANNELS, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_IMGUR_CLIENT_ID, System.ComponentModel.ISupportInitialize).EndInit() + TP_FILE_NAME.ResumeLayout(False) + TP_FILE_NAME.PerformLayout() + TP_FILE_PATTERNS.ResumeLayout(False) + TP_FILE_PATTERNS.PerformLayout() TP_CHANNELS_IMGS.ResumeLayout(False) CType(Me.TXT_CHANNELS_ROWS, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_CHANNELS_COLUMNS, System.ComponentModel.ISupportInitialize).EndInit() - TAB_MAIN.ResumeLayout(False) TAB_BASIS.ResumeLayout(False) TAB_DEFAULTS.ResumeLayout(False) TP_DEFS.ResumeLayout(False) @@ -944,22 +944,22 @@ TP_CHANNELS.PerformLayout() CType(Me.TXT_CHANNEL_USER_POST_LIMIT, System.ComponentModel.ISupportInitialize).EndInit() TAB_DEFS_REDDIT.ResumeLayout(False) - TP_REDDIT.ResumeLayout(False) - TP_REDDIT.PerformLayout() + Me.DEFS_REDDIT.ResumeLayout(False) CType(Me.TXT_REDDIT_SAVED_POSTS_USER, System.ComponentModel.ISupportInitialize).EndInit() TAB_DEFS_TWITTER.ResumeLayout(False) - TP_TWITTER.ResumeLayout(False) - TP_TWITTER.PerformLayout() + Me.DEFS_TWITTER.ResumeLayout(False) + Me.DEFS_TWITTER.PerformLayout() + CType(Me.TXT_REQ_WAIT_TIMER, System.ComponentModel.ISupportInitialize).EndInit() + CType(Me.TXT_REQ_COUNT, System.ComponentModel.ISupportInitialize).EndInit() + CType(Me.TXT_LIMIT_TIMER, System.ComponentModel.ISupportInitialize).EndInit() + Me.TAB_MAIN.ResumeLayout(False) Me.TAB_DEFS_INSTAGRAM.ResumeLayout(False) - TP_INSTAGRAM.ResumeLayout(False) - TP_INSTAGRAM.PerformLayout() + Me.DEFS_INST.ResumeLayout(False) + CType(Me.TXT_INST_SAVED_POSTS_USER, System.ComponentModel.ISupportInitialize).EndInit() + Me.TAB_DEFS_REDGIFS.ResumeLayout(False) Me.CONTAINER_MAIN.ContentPanel.ResumeLayout(False) Me.CONTAINER_MAIN.ResumeLayout(False) Me.CONTAINER_MAIN.PerformLayout() - TP_FILE_NAME.ResumeLayout(False) - TP_FILE_NAME.PerformLayout() - TP_FILE_PATTERNS.ResumeLayout(False) - TP_FILE_PATTERNS.PerformLayout() Me.ResumeLayout(False) End Sub @@ -980,18 +980,9 @@ Private WithEvents CH_DOWN_VIDEOS As CheckBox Private WithEvents CH_DOWN_IMAGES As CheckBox Private WithEvents CH_DEF_TEMP As CheckBox - Private WithEvents CH_TWITTER_TEMP As CheckBox - Private WithEvents CH_TWITTER_DOWN_IMG As CheckBox - Private WithEvents CH_TWITTER_DOWN_VID As CheckBox Private WithEvents CH_TWITTER_USER_MEDIA As CheckBox - Private WithEvents CH_REDDIT_TEMP As CheckBox - Private WithEvents CH_REDDIT_DOWN_IMG As CheckBox - Private WithEvents CH_REDDIT_DOWN_VID As CheckBox Private WithEvents CH_CHANNELS_USERS_TEMP As CheckBox Private WithEvents TAB_DEFS_INSTAGRAM As TabPage - Private WithEvents CH_INSTA_TEMP As CheckBox - Private WithEvents CH_INSTA_DOWN_IMG As CheckBox - Private WithEvents CH_INSTA_DOWN_VID As CheckBox Private WithEvents TXT_IMGUR_CLIENT_ID As PersonalUtilities.Forms.Controls.TextBoxExtended Private WithEvents TXT_REDDIT_SAVED_POSTS_USER As PersonalUtilities.Forms.Controls.TextBoxExtended Private WithEvents OPT_FILE_NAME_REPLACE As RadioButton @@ -1001,5 +992,18 @@ Private WithEvents CH_FILE_TIME As CheckBox Private WithEvents OPT_FILE_DATE_START As RadioButton Private WithEvents OPT_FILE_DATE_END As RadioButton + Private WithEvents CH_EXIT_CONFIRM As CheckBox + Private WithEvents CH_CLOSE_TO_TRAY As CheckBox + Private WithEvents TXT_REQ_WAIT_TIMER As PersonalUtilities.Forms.Controls.TextBoxExtended + Private WithEvents TXT_REQ_COUNT As PersonalUtilities.Forms.Controls.TextBoxExtended + Private WithEvents TXT_LIMIT_TIMER As PersonalUtilities.Forms.Controls.TextBoxExtended + Private WithEvents TAB_DEFS_REDGIFS As TabPage + Friend WithEvents TAB_MAIN As TabControl + Private WithEvents DEFS_TWITTER As SiteDefaults + Private WithEvents DEFS_REDDIT As SiteDefaults + Private WithEvents DEFS_INST As SiteDefaults + Private WithEvents DEFS_REDGIFS As SiteDefaults + Private WithEvents TXT_INST_SAVED_POSTS_USER As PersonalUtilities.Forms.Controls.TextBoxExtended + Private WithEvents CH_SHOW_NOTIFY As CheckBox End Class End Namespace \ No newline at end of file diff --git a/SCrawler/Editors/GlobalSettingsForm.resx b/SCrawler/Editors/GlobalSettingsForm.resx index a01ffec..3777f31 100644 --- a/SCrawler/Editors/GlobalSettingsForm.resx +++ b/SCrawler/Editors/GlobalSettingsForm.resx @@ -214,9 +214,6 @@ If checked, videos will be stored in separate folder; otherwise, videos will be False - - False - False @@ -235,18 +232,9 @@ If checked, videos will be stored in separate folder; otherwise, videos will be False - - False - False - - False - - - False - AAABAA8AAAAQAAEABAAwOgAA9gAAADAwEAABAAQAaAYAACg7AAAgIBAAAQAEAOgCAACQQQAAGBgQAAEA diff --git a/SCrawler/Editors/GlobalSettingsForm.vb b/SCrawler/Editors/GlobalSettingsForm.vb index 81bcbea..2483b40 100644 --- a/SCrawler/Editors/GlobalSettingsForm.vb +++ b/SCrawler/Editors/GlobalSettingsForm.vb @@ -12,6 +12,7 @@ Imports PersonalUtilities.Forms.Toolbars Namespace Editors Friend Class GlobalSettingsForm : Implements IOkCancelToolbar Private ReadOnly MyDefs As DefaultFormProps(Of FieldsChecker) +#Region "Checkers declarations" Private Class SavedPostsChecker : Implements ICustomProvider Private Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider, Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert @@ -25,6 +26,24 @@ Namespace Editors Throw New NotImplementedException() End Function End Class + Private Class InstaTimersChecker : Implements ICustomProvider + Private ReadOnly _LowestValue As Integer + Friend Sub New(ByVal LowestValue As Integer) + _LowestValue = LowestValue + End Sub + Private Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider, + Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert + If ACheck(Of Integer)(Value) AndAlso CInt(Value) >= _LowestValue Then + Return Value + Else + Return Nothing + End If + End Function + Private Function GetFormat(ByVal FormatType As Type) As Object Implements IFormatProvider.GetFormat + Throw New NotImplementedException() + End Function + End Class +#End Region Friend Sub New() InitializeComponent() MyDefs = New DefaultFormProps(Of FieldsChecker) @@ -65,32 +84,39 @@ Namespace Editors CH_FILE_TIME.Checked = .FileAddTimeToFileName OPT_FILE_DATE_START.Checked = Not .FileDateTimePositionEnd OPT_FILE_DATE_END.Checked = .FileDateTimePositionEnd + 'Other program settings + CH_EXIT_CONFIRM.Checked = .ExitConfirm + CH_CLOSE_TO_TRAY.Checked = .CloseToTray + CH_SHOW_NOTIFY.Checked = .ShowNotifications 'Reddit With .Site(Sites.Reddit) - SetChecker(CH_REDDIT_TEMP, .Temporary) - SetChecker(CH_REDDIT_DOWN_IMG, .DownloadImages) - SetChecker(CH_REDDIT_DOWN_VID, .DownloadVideos) + SetChecker(DEFS_REDDIT, Sites.Reddit) TXT_REDDIT_SAVED_POSTS_USER.Text = .SavedPostsUserName End With 'Twitter With .Site(Sites.Twitter) - SetChecker(CH_TWITTER_TEMP, .Temporary) - SetChecker(CH_TWITTER_DOWN_IMG, .DownloadImages) - SetChecker(CH_TWITTER_DOWN_VID, .DownloadVideos) + SetChecker(DEFS_TWITTER, Sites.Twitter) CH_TWITTER_USER_MEDIA.Checked = .GetUserMediaOnly End With 'Instagram With .Site(Sites.Instagram) - SetChecker(CH_INSTA_TEMP, .Temporary) - SetChecker(CH_INSTA_DOWN_IMG, .DownloadImages) - SetChecker(CH_INSTA_DOWN_VID, .DownloadVideos) + SetChecker(DEFS_INST, Sites.Instagram) + TXT_REQ_WAIT_TIMER.Text = .RequestsWaitTimer + TXT_REQ_COUNT.Text = .RequestsWaitTimerTaskCount + TXT_LIMIT_TIMER.Text = .SleepTimerOnPostsLimit + TXT_INST_SAVED_POSTS_USER.Text = .SavedPostsUserName End With + 'RedGifs + SetChecker(DEFS_REDGIFS, Sites.RedGifs) End With .MyFieldsChecker = New FieldsChecker With .MyFieldsChecker .AddControl(Of String)(TXT_GLOBAL_PATH, TXT_GLOBAL_PATH.CaptionText) .AddControl(Of String)(TXT_COLLECTIONS_PATH, TXT_COLLECTIONS_PATH.CaptionText) .AddControl(Of String)(TXT_REDDIT_SAVED_POSTS_USER, TXT_REDDIT_SAVED_POSTS_USER.CaptionText, True, New SavedPostsChecker) + .AddControl(Of Integer)(TXT_REQ_WAIT_TIMER, TXT_REQ_WAIT_TIMER.CaptionText,, New InstaTimersChecker(100)) + .AddControl(Of Integer)(TXT_REQ_COUNT, TXT_REQ_COUNT.CaptionText,, New InstaTimersChecker(1)) + .AddControl(Of Integer)(TXT_LIMIT_TIMER, TXT_LIMIT_TIMER.CaptionText,, New InstaTimersChecker(10000)) .EndLoaderOperations() End With .AppendDetectors() @@ -101,15 +127,30 @@ Namespace Editors MyDefs.InvokeLoaderError(ex) End Try End Sub - Private Sub SetChecker(ByRef CH As CheckBox, ByVal Prop As XML.Base.XMLValue(Of Boolean)) + Private Overloads Sub SetChecker(ByRef CH As SiteDefaults, ByVal s As Sites) + With Settings(s) + SetChecker(CH.MyTemporary, .Temporary) + SetChecker(CH.MyImagesDown, .DownloadImages) + SetChecker(CH.MyVideosDown, .DownloadVideos) + End With + End Sub + Private Overloads Sub SetChecker(ByRef State As CheckState, ByVal Prop As XML.Base.XMLValue(Of Boolean)) If Prop.ValueF.Exists Then - CH.Checked = Prop.Value + State = If(Prop.Value, CheckState.Checked, CheckState.Unchecked) Else - CH.CheckState = CheckState.Indeterminate + State = CheckState.Indeterminate End If End Sub - Private Sub SetPropByChecker(ByRef Prop As XML.Base.XMLValue(Of Boolean), ByRef CH As CheckBox) - Select Case CH.CheckState + Private Overloads Sub SetPropByChecker(ByRef CH As SiteDefaults, ByVal s As Sites) + With Settings(s) + SetPropByChecker(CH.MyTemporary, .Temporary) + SetPropByChecker(CH.MyTemporary, .Temporary) + SetPropByChecker(CH.MyImagesDown, .DownloadImages) + SetPropByChecker(CH.MyVideosDown, .DownloadVideos) + End With + End Sub + Private Overloads Sub SetPropByChecker(ByVal State As CheckState, ByRef Prop As XML.Base.XMLValue(Of Boolean)) + Select Case State Case CheckState.Checked : Prop.Value = True Case CheckState.Unchecked : Prop.Value = False Case CheckState.Indeterminate : Prop.ValueF = Nothing @@ -167,6 +208,10 @@ Namespace Editors .FromChannelDownloadTopUse.Value = TXT_CHANNEL_USER_POST_LIMIT.Checked .FromChannelCopyImageToUser.Value = CH_COPY_CHANNEL_USER_IMAGE.Checked .ChannelsDefaultTemporary.Value = CH_CHANNELS_USERS_TEMP.Checked + 'Other program settings + .ExitConfirm.Value = CH_EXIT_CONFIRM.Checked + .CloseToTray.Value = CH_CLOSE_TO_TRAY.Checked + .ShowNotifications.Value = CH_SHOW_NOTIFY.Checked If CH_FILE_NAME_CHANGE.Checked Then .FileReplaceNameByDate.Value = OPT_FILE_NAME_REPLACE.Checked @@ -180,24 +225,24 @@ Namespace Editors End If 'Reddit With .Site(Sites.Reddit) - SetPropByChecker(.Temporary, CH_REDDIT_TEMP) - SetPropByChecker(.DownloadImages, CH_REDDIT_DOWN_IMG) - SetPropByChecker(.DownloadVideos, CH_REDDIT_DOWN_VID) + SetPropByChecker(DEFS_REDDIT, Sites.Reddit) .SavedPostsUserName.Value = TXT_REDDIT_SAVED_POSTS_USER.Text End With 'Twitter With .Site(Sites.Twitter) - SetPropByChecker(.Temporary, CH_TWITTER_TEMP) - SetPropByChecker(.DownloadImages, CH_TWITTER_DOWN_IMG) - SetPropByChecker(.DownloadVideos, CH_TWITTER_DOWN_VID) + SetPropByChecker(DEFS_TWITTER, Sites.Twitter) .GetUserMediaOnly.Value = CH_TWITTER_USER_MEDIA.Checked End With 'Instagram With .Site(Sites.Instagram) - SetPropByChecker(.Temporary, CH_INSTA_TEMP) - SetPropByChecker(.DownloadImages, CH_INSTA_DOWN_IMG) - SetPropByChecker(.DownloadVideos, CH_INSTA_DOWN_VID) + SetPropByChecker(DEFS_INST, Sites.Instagram) + .RequestsWaitTimer.Value = AConvert(Of Integer)(TXT_REQ_WAIT_TIMER.Text) + .RequestsWaitTimerTaskCount.Value = AConvert(Of Integer)(TXT_REQ_COUNT.Text) + .SleepTimerOnPostsLimit.Value = AConvert(Of Integer)(TXT_LIMIT_TIMER.Text) + .SavedPostsUserName.Value = TXT_INST_SAVED_POSTS_USER.Text End With + 'RedGifs + SetPropByChecker(DEFS_REDGIFS, Sites.RedGifs) .EndUpdate() End With diff --git a/SCrawler/Editors/LabelsForm.Designer.vb b/SCrawler/Editors/LabelsForm.Designer.vb index 2cd983d..d0a572e 100644 --- a/SCrawler/Editors/LabelsForm.Designer.vb +++ b/SCrawler/Editors/LabelsForm.Designer.vb @@ -13,10 +13,10 @@ Partial Friend Class LabelsForm : Inherits System.Windows.Forms.Form Private components As System.ComponentModel.IContainer Private Sub InitializeComponent() - Dim ActionButton4 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(LabelsForm)) - 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 ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() + Dim ActionButton3 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer() Me.CMB_LABELS = New PersonalUtilities.Forms.Controls.ComboBoxExtended() Me.CONTAINER_MAIN.ContentPanel.SuspendLayout() @@ -42,21 +42,21 @@ Partial Friend Class LabelsForm : Inherits System.Windows.Forms.Form ' 'CMB_LABELS ' - ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image) - ActionButton4.Index = 0 - ActionButton4.Name = "BTT_COMBOBOX_ARROW" - ActionButton4.Visible = False - ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image) - ActionButton5.Index = 1 - ActionButton5.Name = "BTT_ADD" - ActionButton5.ToolTipText = "Add new label (Insert)" - ActionButton6.BackgroundImage = CType(resources.GetObject("ActionButton6.BackgroundImage"), System.Drawing.Image) - ActionButton6.Index = 2 - ActionButton6.Name = "BTT_CLEAR" - ActionButton6.ToolTipText = "Clear checked labels" - Me.CMB_LABELS.Buttons.Add(ActionButton4) - Me.CMB_LABELS.Buttons.Add(ActionButton5) - Me.CMB_LABELS.Buttons.Add(ActionButton6) + ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image) + ActionButton1.Index = 0 + ActionButton1.Name = "BTT_COMBOBOX_ARROW" + ActionButton1.Visible = False + ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image) + ActionButton2.Index = 1 + ActionButton2.Name = "BTT_ADD" + ActionButton2.ToolTipText = "Add new label (Insert)" + ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image) + ActionButton3.Index = 2 + ActionButton3.Name = "BTT_CLEAR" + ActionButton3.ToolTipText = "Clear checked labels" + Me.CMB_LABELS.Buttons.Add(ActionButton1) + Me.CMB_LABELS.Buttons.Add(ActionButton2) + Me.CMB_LABELS.Buttons.Add(ActionButton3) Me.CMB_LABELS.Dock = System.Windows.Forms.DockStyle.Fill Me.CMB_LABELS.ListCheckBoxes = True Me.CMB_LABELS.ListDropDownStyle = PersonalUtilities.Forms.Controls.ComboBoxExtended.ListMode.Simple diff --git a/SCrawler/Editors/LabelsForm.resx b/SCrawler/Editors/LabelsForm.resx index 52699eb..22fe23b 100644 --- a/SCrawler/Editors/LabelsForm.resx +++ b/SCrawler/Editors/LabelsForm.resx @@ -118,7 +118,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE65JREFUeF7t 3X2sJWddB/DdLi2lQG2hdOHuvfM887J7Cxca4ELTQMDWKigIFpBAEAgi9g+CJpJo9Q8NJhgBiYZIYspL @@ -208,7 +208,7 @@ AAAASUVORK5CYII= - + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAADmUlE @@ -230,7 +230,7 @@ 0AUyNxOP1DOwcaG/8I+/LRB+At7psBnyDBG0AAAAAElFTkSuQmCC - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go diff --git a/SCrawler/Editors/LabelsForm.vb b/SCrawler/Editors/LabelsForm.vb index 10c5a67..f66c1bc 100644 --- a/SCrawler/Editors/LabelsForm.vb +++ b/SCrawler/Editors/LabelsForm.vb @@ -27,21 +27,18 @@ Friend Class LabelsForm : Implements IOkCancelToolbar Try With MyDefs .MyViewInitialize(Me, Settings.Design) - .MyOkCancel = New OkCancelToolbar(Me, Me, CONTAINER_MAIN.BottomToolStripPanel) - .MyOkCancel.AddThisToolbar() + .AddOkCancelToolbar() .DelegateClosingChecker() - If Settings.Labels.Count > 0 Then Dim items As New List(Of Integer) CMB_LABELS.BeginUpdate() For i% = 0 To Settings.Labels.Count - 1 If LabelsList.Contains(Settings.Labels(i)) Then items.Add(i) - CMB_LABELS.Items.Add(New ListItem(Settings.Labels(i))) + CMB_LABELS.Items.Add(Settings.Labels(i)) Next CMB_LABELS.EndUpdate() CMB_LABELS.ListCheckedIndexes = items End If - .AppendDetectors() .EndLoaderOperations() End With @@ -60,8 +57,8 @@ Friend Class LabelsForm : Implements IOkCancelToolbar If MultiUser Then Dim m As New MMessage("You are changing labels for more one user" & vbNewLine & "What do you want to do?", "MultiUser labels changing", - {New MsgBoxButton("Replace exists") With {.ToolTip = "For each user: all exists labels will be deleted and replaced to these labels"}, - New MsgBoxButton("Add to exists") With {.ToolTip = "For each user: these labels will be appended to exists labels"}, + {New MsgBoxButton("Replace exists") With {.ToolTip = "Per user: all existing labels will be removed and replaced with these labels"}, + New MsgBoxButton("Add to exists") With {.ToolTip = "Per user: these labels will be add to existing labels"}, New MsgBoxButton("Cancel")}, MsgBoxStyle.Exclamation) Select Case MsgBoxE(m).Index @@ -70,11 +67,7 @@ Friend Class LabelsForm : Implements IOkCancelToolbar Case 2 : Exit Sub End Select End If - LabelsList.Clear() - Dim s As List(Of Integer) = CMB_LABELS.ListCheckedIndexes.ListIfNothing - If s.Count > 0 Then - For Each i% In s : LabelsList.Add(Settings.Labels(i)) : Next - End If + LabelsList.ListAddList(CMB_LABELS.Items.CheckedItems.Select(Function(l) CStr(l.Value(0))), LAP.ClearBeforeAdd, LAP.NotContainsOnly) If _AnyLabelAdd Then Settings.Labels.Update() MyDefs.CloseForm() Catch ex As Exception @@ -98,7 +91,7 @@ Friend Class LabelsForm : Implements IOkCancelToolbar Else Settings.Labels.Add(nl) _AnyLabelAdd = True - CMB_LABELS.Items.Add(New ListItem(nl)) + CMB_LABELS.Items.Add(nl) End If End If End Sub diff --git a/SCrawler/Editors/SiteDefaults.vb b/SCrawler/Editors/SiteDefaults.vb new file mode 100644 index 0000000..3342afa --- /dev/null +++ b/SCrawler/Editors/SiteDefaults.vb @@ -0,0 +1,102 @@ +' Copyright (C) 2022 Andy +' 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 +Namespace Editors + Public Class SiteDefaults : Inherits TableLayoutPanel + Private ReadOnly CH_TEMP As CheckBox + Private ReadOnly CH_IMG As CheckBox + Private ReadOnly CH_VID As CheckBox + Public Sub New() + InitCheckBox(CH_TEMP, "Temporary") + InitCheckBox(CH_IMG, "Download images") + InitCheckBox(CH_VID, "Download videos") + End Sub + Private Sub InitCheckBox(ByRef CH As CheckBox, ByVal Caption As String) + CH = New CheckBox With {.Text = Caption, .Dock = DockStyle.Fill, .UseVisualStyleBackColor = True, + .ThreeState = True, .CheckState = CheckState.Indeterminate} + AddHandler CH.CheckedChanged, AddressOf Checker_CheckedChanged + AddHandler CH.CheckStateChanged, AddressOf Checker_CheckedChanged + End Sub + Private Sub SiteDefaults_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed + CH_TEMP.Dispose() + CH_IMG.Dispose() + CH_VID.Dispose() + End Sub + Protected Overrides Sub InitLayout() + MyBase.InitLayout() + If ColumnStyles.Count = 2 Or RowStyles.Count = 2 Then + ColumnStyles.Clear() + RowStyles.Clear() + CellBorderStyle = TableLayoutPanelCellBorderStyle.Single + ColumnCount = 1 + ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 100)) + RowCount = 4 + RowStyles.Add(New RowStyle(SizeType.Absolute, 25)) + RowStyles.Add(New RowStyle(SizeType.Absolute, 25)) + RowStyles.Add(New RowStyle(SizeType.Absolute, 25)) + RowStyles.Add(New RowStyle(SizeType.Percent, 100)) + End If + Controls.Add(CH_TEMP, 0, 0) + Controls.Add(CH_IMG, 0, 1) + Controls.Add(CH_VID, 0, 2) + End Sub + Private _BaseControlsPadding As New Padding(0) + + Public Property BaseControlsPadding As Padding + Get + Return _BaseControlsPadding + End Get + Set(ByVal p As Padding) + _BaseControlsPadding = p + CH_TEMP.Padding = p + CH_IMG.Padding = p + CH_VID.Padding = p + End Set + End Property + Private Function ShouldSerializeBaseControlsPadding() As Boolean + Return Not _BaseControlsPadding.Equals(New Padding(0)) + End Function + + Public Property ChangesDetected As Boolean = False + Private Sub Checker_CheckedChanged(sender As Object, e As EventArgs) + ChangesDetected = True + End Sub + + Public Property MyTemporary As CheckState + Get + Return CH_TEMP.CheckState + End Get + Set(ByVal s As CheckState) + CH_TEMP.CheckState = s + End Set + End Property + + Public Property MyImagesDown As CheckState + Get + Return CH_IMG.CheckState + End Get + Set(ByVal s As CheckState) + CH_IMG.CheckState = s + End Set + End Property + + Public Property MyVideosDown As CheckState + Get + Return CH_VID.CheckState + End Get + Set(ByVal s As CheckState) + CH_VID.CheckState = s + End Set + End Property + End Class +End Namespace \ No newline at end of file diff --git a/SCrawler/Editors/SiteEditorForm.vb b/SCrawler/Editors/SiteEditorForm.vb index 755bac6..6dd2361 100644 --- a/SCrawler/Editors/SiteEditorForm.vb +++ b/SCrawler/Editors/SiteEditorForm.vb @@ -44,24 +44,28 @@ Namespace Editors TXT_AUTH.Text = .Headers(API.Base.SiteSettings.Header_Twitter_Authorization) End If End With - If MySite = Sites.Instagram Then TXT_TOKEN.Text = .InstaHash + If MySite = Sites.Instagram Then + TXT_TOKEN.Text = .InstaHash + TXT_AUTH.Text = .InstaHash_SP + End If End With - If Not MySite = Sites.Twitter Then - Dim p As PaddingE = PaddingE.GetOf({TP_MAIN}) - Dim s As New Size(Size.Width, Size.Height - p.Vertical - TXT_AUTH.NeededHeight) - TXT_AUTH.Visible = False - If Not MySite = Sites.Instagram Then - s.Height -= (p.Vertical + TXT_TOKEN.NeededHeight) - TXT_TOKEN.Visible = False - Else + If MySite = Sites.Twitter Or MySite = Sites.Instagram Then + If MySite = Sites.Instagram Then TXT_TOKEN.CaptionText = "Hash" TXT_TOKEN.CaptionToolTipText = "Instagram session hash" TXT_TOKEN.Buttons.Clear() TXT_TOKEN.Buttons.AddRange({ActionButton.DefaultButtons.Refresh, ActionButton.DefaultButtons.Clear}) + TXT_AUTH.CaptionText = "Hash 2" + TXT_AUTH.CaptionToolTipText = "Instagram session hash for saved posts" End If + Else + TXT_AUTH.Visible = False + TXT_TOKEN.Visible = False + Dim p As PaddingE = PaddingE.GetOf({TP_MAIN}) + Dim s As New Size(Size.Width, Size.Height - p.Vertical(2) - TXT_AUTH.NeededHeight - TXT_TOKEN.NeededHeight) With TP_MAIN - If Not MySite = Sites.Instagram Then .RowStyles(2).Height = 0 + .RowStyles(2).Height = 0 .RowStyles(3).Height = 0 End With MinimumSize = s @@ -71,9 +75,9 @@ Namespace Editors .MyFieldsChecker = New FieldsChecker With .MyFieldsChecker - If MySite = Sites.Twitter Then + If MySite = Sites.Twitter Or MySite = Sites.Instagram Then .AddControl(Of String)(TXT_TOKEN, TXT_TOKEN.CaptionText) - .AddControl(Of String)(TXT_AUTH, TXT_AUTH.CaptionText) + .AddControl(Of String)(TXT_AUTH, TXT_AUTH.CaptionText, MySite = Sites.Instagram) End If .EndLoaderOperations() End With @@ -86,6 +90,12 @@ Namespace Editors End Sub Private Sub ToolbarBttOK() Implements IOkCancelToolbar.ToolbarBttOK If MyDefs.MyFieldsChecker.AllParamsOK Then + If MySite = Sites.Instagram Then + If Not TXT_TOKEN.IsEmptyString AndAlso Not TXT_AUTH.IsEmptyString AndAlso TXT_TOKEN.Text = TXT_AUTH.Text Then + MsgBoxE({"InstaHash for saved posts must be different from InstaHash!", "InstaHash are equal"}, vbCritical) + Exit Sub + End If + End If With Settings(MySite) If TXT_PATH.IsEmptyString Then .Path = Nothing Else .Path = TXT_PATH.Text Select Case MySite @@ -96,6 +106,7 @@ Namespace Editors End With Case Sites.Instagram .InstaHash.Value = TXT_TOKEN.Text + .InstaHash_SP.Value = TXT_AUTH.Text End Select .Update() End With diff --git a/SCrawler/Editors/SiteSelectionForm.vb b/SCrawler/Editors/SiteSelectionForm.vb index fd14c78..e601395 100644 --- a/SCrawler/Editors/SiteSelectionForm.vb +++ b/SCrawler/Editors/SiteSelectionForm.vb @@ -25,15 +25,11 @@ Namespace Editors .DelegateClosingChecker() .AddOkCancelToolbar() CMB_SITES.BeginUpdate() - CMB_SITES.Items.AddRange({New ListItem({Sites.Reddit.ToString, CInt(Sites.Reddit)}), - New ListItem({Sites.Twitter.ToString, CInt(Sites.Twitter)}), - New ListItem({Sites.Instagram.ToString, CInt(Sites.Instagram)})}) + Dim sl As List(Of Sites) = ListAddList(Of Sites)(Nothing, [Enum].GetValues(GetType(Sites))).ListWithRemove(Sites.Undefined) + CMB_SITES.Items.AddRange(sl.Select(Function(s) New ListItem({s.ToString, CInt(s)}))) Dim l As New List(Of Integer) - If SelectedSites.Count > 0 Then - If SelectedSites.Contains(Sites.Reddit) Then l.Add(0) - If SelectedSites.Contains(Sites.Twitter) Then l.Add(1) - If SelectedSites.Contains(Sites.Instagram) Then l.Add(2) - End If + If SelectedSites.Count > 0 Then sl.ForEach(Sub(s) If SelectedSites.Contains(s) Then l.Add(sl.IndexOf(s))) + sl.Clear() CMB_SITES.EndUpdate() If l.Count > 0 Then CMB_SITES.ListCheckedIndexes = l : l.Clear() .EndLoaderOperations() @@ -45,17 +41,7 @@ Namespace Editors End Sub Public Sub ToolbarBttOK() Implements IOkCancelToolbar.ToolbarBttOK Try - SelectedSites.Clear() - Dim l As List(Of Integer) = CMB_SITES.ListCheckedIndexes - If l.ListExists Then - For Each i% In l - Select Case i - Case 0 : SelectedSites.Add(Sites.Reddit) - Case 1 : SelectedSites.Add(Sites.Twitter) - Case 2 : SelectedSites.Add(Sites.Instagram) - End Select - Next - End If + SelectedSites.ListAddList(CMB_SITES.Items.CheckedItems.Select(Function(i) DirectCast(i.Value(1), Sites)), LAP.ClearBeforeAdd) MyDefs.CloseForm() Catch ex As Exception ErrorsDescriber.Execute(EDP.LogMessageValue, ex) diff --git a/SCrawler/Editors/UserCreatorForm.Designer.vb b/SCrawler/Editors/UserCreatorForm.Designer.vb index f4df2b7..bd93345 100644 --- a/SCrawler/Editors/UserCreatorForm.Designer.vb +++ b/SCrawler/Editors/UserCreatorForm.Designer.vb @@ -16,7 +16,6 @@ Private Sub InitializeComponent() Me.components = New System.ComponentModel.Container() Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel - Dim TP_SITE As System.Windows.Forms.TableLayoutPanel Dim TP_PARAMS As System.Windows.Forms.TableLayoutPanel Dim TP_OTHER As System.Windows.Forms.TableLayoutPanel Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() @@ -28,10 +27,12 @@ Dim ActionButton5 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim TT_MAIN As System.Windows.Forms.ToolTip Me.TXT_USER = New PersonalUtilities.Forms.Controls.TextBoxExtended() + Me.TP_SITE = New System.Windows.Forms.TableLayoutPanel() Me.OPT_REDDIT = New System.Windows.Forms.RadioButton() Me.OPT_TWITTER = New System.Windows.Forms.RadioButton() Me.CH_IS_CHANNEL = New System.Windows.Forms.CheckBox() Me.OPT_INSTAGRAM = New System.Windows.Forms.RadioButton() + Me.OPT_REDGIFS = New System.Windows.Forms.RadioButton() Me.CH_TEMP = New System.Windows.Forms.CheckBox() Me.CH_FAV = New System.Windows.Forms.CheckBox() Me.CH_PARSE_USER_MEDIA = New System.Windows.Forms.CheckBox() @@ -47,14 +48,13 @@ Me.TXT_SPEC_FOLDER = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer() TP_MAIN = New System.Windows.Forms.TableLayoutPanel() - TP_SITE = New System.Windows.Forms.TableLayoutPanel() TP_PARAMS = New System.Windows.Forms.TableLayoutPanel() TP_OTHER = New System.Windows.Forms.TableLayoutPanel() TP_DOWN_OPTIONS = New System.Windows.Forms.TableLayoutPanel() TT_MAIN = New System.Windows.Forms.ToolTip(Me.components) TP_MAIN.SuspendLayout() CType(Me.TXT_USER, System.ComponentModel.ISupportInitialize).BeginInit() - TP_SITE.SuspendLayout() + Me.TP_SITE.SuspendLayout() TP_PARAMS.SuspendLayout() TP_OTHER.SuspendLayout() CType(Me.TXT_DESCR, System.ComponentModel.ISupportInitialize).BeginInit() @@ -73,7 +73,7 @@ TP_MAIN.ColumnCount = 1 TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) TP_MAIN.Controls.Add(Me.TXT_USER, 0, 0) - TP_MAIN.Controls.Add(TP_SITE, 0, 3) + TP_MAIN.Controls.Add(Me.TP_SITE, 0, 3) TP_MAIN.Controls.Add(TP_PARAMS, 0, 4) TP_MAIN.Controls.Add(TP_OTHER, 0, 6) TP_MAIN.Controls.Add(Me.TXT_DESCR, 0, 9) @@ -112,24 +112,26 @@ ' 'TP_SITE ' - TP_SITE.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] - TP_SITE.ColumnCount = 4 - TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25.0!)) - TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25.0!)) - TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25.0!)) - TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25.0!)) - TP_SITE.Controls.Add(Me.OPT_REDDIT, 0, 0) - TP_SITE.Controls.Add(Me.OPT_TWITTER, 2, 0) - TP_SITE.Controls.Add(Me.CH_IS_CHANNEL, 1, 0) - TP_SITE.Controls.Add(Me.OPT_INSTAGRAM, 3, 0) - TP_SITE.Dock = System.Windows.Forms.DockStyle.Fill - TP_SITE.Location = New System.Drawing.Point(1, 88) - TP_SITE.Margin = New System.Windows.Forms.Padding(0) - TP_SITE.Name = "TP_SITE" - TP_SITE.RowCount = 1 - TP_SITE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_SITE.Size = New System.Drawing.Size(452, 31) - TP_SITE.TabIndex = 3 + Me.TP_SITE.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] + Me.TP_SITE.ColumnCount = 5 + Me.TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 20.0!)) + Me.TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 20.0!)) + Me.TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 20.0!)) + Me.TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 20.0!)) + Me.TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 20.0!)) + Me.TP_SITE.Controls.Add(Me.OPT_REDDIT, 0, 0) + Me.TP_SITE.Controls.Add(Me.OPT_TWITTER, 2, 0) + Me.TP_SITE.Controls.Add(Me.CH_IS_CHANNEL, 1, 0) + Me.TP_SITE.Controls.Add(Me.OPT_INSTAGRAM, 3, 0) + Me.TP_SITE.Controls.Add(Me.OPT_REDGIFS, 4, 0) + Me.TP_SITE.Dock = System.Windows.Forms.DockStyle.Fill + Me.TP_SITE.Location = New System.Drawing.Point(1, 88) + Me.TP_SITE.Margin = New System.Windows.Forms.Padding(0) + Me.TP_SITE.Name = "TP_SITE" + Me.TP_SITE.RowCount = 1 + Me.TP_SITE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) + Me.TP_SITE.Size = New System.Drawing.Size(452, 31) + Me.TP_SITE.TabIndex = 3 ' 'OPT_REDDIT ' @@ -137,7 +139,7 @@ Me.OPT_REDDIT.Dock = System.Windows.Forms.DockStyle.Fill Me.OPT_REDDIT.Location = New System.Drawing.Point(4, 4) Me.OPT_REDDIT.Name = "OPT_REDDIT" - Me.OPT_REDDIT.Size = New System.Drawing.Size(105, 23) + Me.OPT_REDDIT.Size = New System.Drawing.Size(83, 23) Me.OPT_REDDIT.TabIndex = 0 Me.OPT_REDDIT.TabStop = True Me.OPT_REDDIT.Text = "Reddit" @@ -147,9 +149,9 @@ ' Me.OPT_TWITTER.AutoSize = True Me.OPT_TWITTER.Dock = System.Windows.Forms.DockStyle.Fill - Me.OPT_TWITTER.Location = New System.Drawing.Point(228, 4) + Me.OPT_TWITTER.Location = New System.Drawing.Point(184, 4) Me.OPT_TWITTER.Name = "OPT_TWITTER" - Me.OPT_TWITTER.Size = New System.Drawing.Size(105, 23) + Me.OPT_TWITTER.Size = New System.Drawing.Size(83, 23) Me.OPT_TWITTER.TabIndex = 1 Me.OPT_TWITTER.TabStop = True Me.OPT_TWITTER.Text = "Twitter" @@ -159,9 +161,9 @@ ' Me.CH_IS_CHANNEL.AutoSize = True Me.CH_IS_CHANNEL.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_IS_CHANNEL.Location = New System.Drawing.Point(116, 4) + Me.CH_IS_CHANNEL.Location = New System.Drawing.Point(94, 4) Me.CH_IS_CHANNEL.Name = "CH_IS_CHANNEL" - Me.CH_IS_CHANNEL.Size = New System.Drawing.Size(105, 23) + Me.CH_IS_CHANNEL.Size = New System.Drawing.Size(83, 23) Me.CH_IS_CHANNEL.TabIndex = 2 Me.CH_IS_CHANNEL.Text = "Channel" Me.CH_IS_CHANNEL.UseVisualStyleBackColor = True @@ -170,14 +172,26 @@ ' Me.OPT_INSTAGRAM.AutoSize = True Me.OPT_INSTAGRAM.Dock = System.Windows.Forms.DockStyle.Fill - Me.OPT_INSTAGRAM.Location = New System.Drawing.Point(340, 4) + Me.OPT_INSTAGRAM.Location = New System.Drawing.Point(274, 4) Me.OPT_INSTAGRAM.Name = "OPT_INSTAGRAM" - Me.OPT_INSTAGRAM.Size = New System.Drawing.Size(108, 23) + Me.OPT_INSTAGRAM.Size = New System.Drawing.Size(83, 23) Me.OPT_INSTAGRAM.TabIndex = 3 Me.OPT_INSTAGRAM.TabStop = True Me.OPT_INSTAGRAM.Text = "Instagram" Me.OPT_INSTAGRAM.UseVisualStyleBackColor = True ' + 'OPT_REDGIFS + ' + Me.OPT_REDGIFS.AutoSize = True + Me.OPT_REDGIFS.Dock = System.Windows.Forms.DockStyle.Fill + Me.OPT_REDGIFS.Location = New System.Drawing.Point(364, 4) + Me.OPT_REDGIFS.Name = "OPT_REDGIFS" + Me.OPT_REDGIFS.Size = New System.Drawing.Size(84, 23) + Me.OPT_REDGIFS.TabIndex = 4 + Me.OPT_REDGIFS.TabStop = True + Me.OPT_REDGIFS.Text = "RedGifs" + Me.OPT_REDGIFS.UseVisualStyleBackColor = True + ' 'TP_PARAMS ' TP_PARAMS.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] @@ -442,8 +456,8 @@ Me.Text = "Create User" TP_MAIN.ResumeLayout(False) CType(Me.TXT_USER, System.ComponentModel.ISupportInitialize).EndInit() - TP_SITE.ResumeLayout(False) - TP_SITE.PerformLayout() + Me.TP_SITE.ResumeLayout(False) + Me.TP_SITE.PerformLayout() TP_PARAMS.ResumeLayout(False) TP_PARAMS.PerformLayout() TP_OTHER.ResumeLayout(False) @@ -482,5 +496,7 @@ Private WithEvents CH_IS_CHANNEL As CheckBox Private WithEvents OPT_INSTAGRAM As RadioButton Private WithEvents TXT_SPEC_FOLDER As PersonalUtilities.Forms.Controls.TextBoxExtended + Private WithEvents OPT_REDGIFS As RadioButton + Private WithEvents TP_SITE As TableLayoutPanel End Class End Namespace \ No newline at end of file diff --git a/SCrawler/Editors/UserCreatorForm.resx b/SCrawler/Editors/UserCreatorForm.resx index 7f54305..de954cd 100644 --- a/SCrawler/Editors/UserCreatorForm.resx +++ b/SCrawler/Editors/UserCreatorForm.resx @@ -120,9 +120,6 @@ False - - False - False diff --git a/SCrawler/Editors/UserCreatorForm.vb b/SCrawler/Editors/UserCreatorForm.vb index 53c71e7..cdfbad6 100644 --- a/SCrawler/Editors/UserCreatorForm.vb +++ b/SCrawler/Editors/UserCreatorForm.vb @@ -8,7 +8,6 @@ ' but WITHOUT ANY WARRANTY Imports System.ComponentModel Imports PersonalUtilities.Forms -Imports PersonalUtilities.Forms.Controls Imports PersonalUtilities.Forms.Controls.Base Imports PersonalUtilities.Forms.Toolbars Imports SCrawler.API.Base @@ -119,13 +118,11 @@ Namespace Editors Case Sites.Reddit : OPT_REDDIT.Checked = True : CH_PARSE_USER_MEDIA.Enabled = False Case Sites.Twitter : OPT_TWITTER.Checked = True Case Sites.Instagram : OPT_INSTAGRAM.Checked = True + Case Sites.RedGifs : OPT_REDGIFS.Checked = True End Select SetParamsBySite() - OPT_REDDIT.Enabled = False - OPT_TWITTER.Enabled = False - OPT_INSTAGRAM.Enabled = False + TP_SITE.Enabled = False CH_IS_CHANNEL.Checked = User.IsChannel - CH_IS_CHANNEL.Enabled = False If Not UserInstance Is Nothing Then TXT_USER.Enabled = False TXT_SPEC_FOLDER.TextBoxReadOnly = True @@ -179,6 +176,7 @@ Namespace Editors Case OPT_REDDIT.Checked : Return Sites.Reddit Case OPT_TWITTER.Checked : Return Sites.Twitter Case OPT_INSTAGRAM.Checked : Return Sites.Instagram + Case OPT_REDGIFS.Checked : Return Sites.RedGifs Case Else : Return Sites.Undefined End Select End Function @@ -239,6 +237,7 @@ CloseForm: Private ReadOnly RedditChannelRegEx1 As New RegexStructure("[htps:/]{7,8}.*?reddit.com/r/([^/]+)", 1) Private ReadOnly RedditChannelRegEx2 As New RegexStructure(".?r/([^/]+)", 1) Private ReadOnly InstagramRegEx As New RegexStructure("[htps:/]{7,8}.*?instagram.com/([^/]+)", 1) + Private ReadOnly RedGifsRegEx As New RegexStructure("[htps:/]{7,8}.*?redgifs.com/users/([^/]+)", 1) Private _TextChangeInvoked As Boolean = False Private Sub TXT_USER_ActionOnTextChange() Handles TXT_USER.ActionOnTextChange Try @@ -250,6 +249,7 @@ CloseForm: Case Sites.Twitter : OPT_TWITTER.Checked = True Case Sites.Reddit : OPT_REDDIT.Checked = True Case Sites.Instagram : OPT_INSTAGRAM.Checked = True + Case Sites.RedGifs : OPT_REDGIFS.Checked = True Case Else : OPT_TWITTER.Checked = False : OPT_REDDIT.Checked = False : OPT_INSTAGRAM.Checked = False End Select CH_IS_CHANNEL.Checked = CBool(s(1)) @@ -269,6 +269,8 @@ CloseForm: Return {Sites.Reddit, True} ElseIf CheckRegex(TXT, InstagramRegEx) Then Return {Sites.Instagram, False} + ElseIf CheckRegex(TXT, RedGifsRegEx) Then + Return {Sites.RedGifs, False} End If End If Return {Sites.Undefined, False} @@ -286,6 +288,9 @@ CloseForm: Private Sub OPT_INSTAGRAM_CheckedChanged(sender As Object, e As EventArgs) Handles OPT_INSTAGRAM.CheckedChanged If OPT_INSTAGRAM.Checked Then CH_IS_CHANNEL.Checked = False : CH_IS_CHANNEL.Enabled = False : SetParamsBySite() End Sub + Private Sub OPT_REDGIFS_CheckedChanged(sender As Object, e As EventArgs) Handles OPT_REDGIFS.CheckedChanged + If OPT_REDGIFS.Checked Then CH_IS_CHANNEL.Checked = False : CH_IS_CHANNEL.Enabled = False : SetParamsBySite() + End Sub Private Sub TXT_SPEC_FOLDER_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_SPEC_FOLDER.ActionOnButtonClick If Sender.DefaultButton = ActionButton.DefaultButtons.Open Then Dim f As SFile = Nothing diff --git a/SCrawler/MainFrame.Designer.vb b/SCrawler/MainFrame.Designer.vb index 472a809..289307e 100644 --- a/SCrawler/MainFrame.Designer.vb +++ b/SCrawler/MainFrame.Designer.vb @@ -1,8 +1,5 @@  -Partial Class MainFrame - Inherits System.Windows.Forms.Form - - 'Form overrides dispose to clean up the component list. +Partial Public Class MainFrame : Inherits System.Windows.Forms.Form Protected Overrides Sub Dispose(ByVal disposing As Boolean) Try @@ -13,13 +10,7 @@ Partial Class MainFrame MyBase.Dispose(disposing) End Try End Sub - - 'Required by the Windows Form Designer Private components As System.ComponentModel.IContainer - - 'NOTE: The following procedure is required by the Windows Form Designer - 'It can be modified using the Windows Form Designer. - 'Do not modify it using the code editor. Private Sub InitializeComponent() Me.components = New System.ComponentModel.Container() @@ -37,10 +28,12 @@ Partial Class MainFrame Dim MENU_VIEW_SEP_1 As System.Windows.Forms.ToolStripSeparator Dim MENU_VIEW_SEP_3 As System.Windows.Forms.ToolStripSeparator Dim MENU_VIEW_SEP_2 As System.Windows.Forms.ToolStripSeparator + Dim TRAY_SEP_1 As System.Windows.Forms.ToolStripSeparator Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(MainFrame)) Me.BTT_SETTINGS_REDDIT = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_SETTINGS_TWITTER = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_SETTINGS_INSTAGRAM = New System.Windows.Forms.ToolStripMenuItem() + Me.BTT_SETTINGS_REDGIFS = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_SETTINGS = New System.Windows.Forms.ToolStripMenuItem() Me.Toolbar_TOP = New System.Windows.Forms.ToolStrip() Me.BTT_ADD_USER = New System.Windows.Forms.ToolStripButton() @@ -69,11 +62,14 @@ Partial Class MainFrame Me.BTT_SELECT_LABELS = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_LOG = New System.Windows.Forms.ToolStripButton() Me.BTT_VERSION_INFO = New System.Windows.Forms.ToolStripButton() + Me.BTT_DONATE = New System.Windows.Forms.ToolStripButton() Me.Toolbar_BOTTOM = New System.Windows.Forms.StatusStrip() - Me.PR_SAVED = New System.Windows.Forms.ToolStripProgressBar() Me.PR_MAIN = New System.Windows.Forms.ToolStripProgressBar() Me.LBL_JOBS_COUNT = New System.Windows.Forms.ToolStripStatusLabel() Me.LBL_STATUS = New System.Windows.Forms.ToolStripStatusLabel() + Me.PR_INST = New System.Windows.Forms.ToolStripProgressBar() + Me.LBL_JOBS_INST_COUNT = New System.Windows.Forms.ToolStripStatusLabel() + Me.LBL_STATUS_INST = New System.Windows.Forms.ToolStripStatusLabel() Me.LIST_PROFILES = New System.Windows.Forms.ListView() Me.USER_CONTEXT = New System.Windows.Forms.ContextMenuStrip(Me.components) Me.BTT_CONTEXT_DOWN = New System.Windows.Forms.ToolStripMenuItem() @@ -91,6 +87,10 @@ Partial Class MainFrame Me.BTT_CONTEXT_OPEN_PATH = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_CONTEXT_OPEN_SITE = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_CONTEXT_INFO = New System.Windows.Forms.ToolStripMenuItem() + Me.TrayIcon = New System.Windows.Forms.NotifyIcon(Me.components) + Me.TRAY_CONTEXT = New System.Windows.Forms.ContextMenuStrip(Me.components) + Me.BTT_TRAY_SHOW_HIDE = New System.Windows.Forms.ToolStripMenuItem() + Me.BTT_TRAY_CLOSE = New System.Windows.Forms.ToolStripMenuItem() SEP_1 = New System.Windows.Forms.ToolStripSeparator() SEP_2 = New System.Windows.Forms.ToolStripSeparator() CONTEXT_SEP_1 = New System.Windows.Forms.ToolStripSeparator() @@ -105,9 +105,11 @@ Partial Class MainFrame MENU_VIEW_SEP_1 = New System.Windows.Forms.ToolStripSeparator() MENU_VIEW_SEP_3 = New System.Windows.Forms.ToolStripSeparator() MENU_VIEW_SEP_2 = New System.Windows.Forms.ToolStripSeparator() + TRAY_SEP_1 = New System.Windows.Forms.ToolStripSeparator() Me.Toolbar_TOP.SuspendLayout() Me.Toolbar_BOTTOM.SuspendLayout() Me.USER_CONTEXT.SuspendLayout() + Me.TRAY_CONTEXT.SuspendLayout() Me.SuspendLayout() ' 'SEP_1 @@ -128,7 +130,7 @@ Partial Class MainFrame 'MENU_SETTINGS ' MENU_SETTINGS.AutoToolTip = False - MENU_SETTINGS.DropDownItems.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_SETTINGS_REDDIT, Me.BTT_SETTINGS_TWITTER, Me.BTT_SETTINGS_INSTAGRAM, MENU_SETTINGS_SEP_1, Me.BTT_SETTINGS}) + MENU_SETTINGS.DropDownItems.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_SETTINGS_REDDIT, Me.BTT_SETTINGS_TWITTER, Me.BTT_SETTINGS_INSTAGRAM, Me.BTT_SETTINGS_REDGIFS, MENU_SETTINGS_SEP_1, Me.BTT_SETTINGS}) MENU_SETTINGS.ImageTransparentColor = System.Drawing.Color.Magenta MENU_SETTINGS.Name = "MENU_SETTINGS" MENU_SETTINGS.Size = New System.Drawing.Size(62, 22) @@ -155,6 +157,12 @@ Partial Class MainFrame Me.BTT_SETTINGS_INSTAGRAM.Size = New System.Drawing.Size(127, 22) Me.BTT_SETTINGS_INSTAGRAM.Text = "Instagram" ' + 'BTT_SETTINGS_REDGIFS + ' + Me.BTT_SETTINGS_REDGIFS.Name = "BTT_SETTINGS_REDGIFS" + Me.BTT_SETTINGS_REDGIFS.Size = New System.Drawing.Size(127, 22) + Me.BTT_SETTINGS_REDGIFS.Text = "RedGifs" + ' 'MENU_SETTINGS_SEP_1 ' MENU_SETTINGS_SEP_1.Name = "MENU_SETTINGS_SEP_1" @@ -212,10 +220,15 @@ Partial Class MainFrame MENU_VIEW_SEP_2.Name = "MENU_VIEW_SEP_2" MENU_VIEW_SEP_2.Size = New System.Drawing.Size(141, 6) ' + 'TRAY_SEP_1 + ' + TRAY_SEP_1.Name = "TRAY_SEP_1" + TRAY_SEP_1.Size = New System.Drawing.Size(130, 6) + ' 'Toolbar_TOP ' Me.Toolbar_TOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden - Me.Toolbar_TOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {MENU_SETTINGS, SEP_1, Me.BTT_ADD_USER, Me.BTT_EDIT_USER, Me.BTT_DELETE_USER, Me.BTT_REFRESH, Me.BTT_SHOW_INFO, Me.BTT_CHANNELS, Me.BTT_DOWN_SAVED, SEP_2, Me.BTT_DOWN_SELECTED, Me.BTT_DOWN_ALL, Me.BTT_DOWN_VIDEO, Me.BTT_DOWN_STOP, SEP_3, Me.MENU_VIEW, SEP_4, Me.BTT_LOG, Me.BTT_VERSION_INFO}) + Me.Toolbar_TOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {MENU_SETTINGS, SEP_1, Me.BTT_ADD_USER, Me.BTT_EDIT_USER, Me.BTT_DELETE_USER, Me.BTT_REFRESH, Me.BTT_SHOW_INFO, Me.BTT_CHANNELS, Me.BTT_DOWN_SAVED, SEP_2, Me.BTT_DOWN_SELECTED, Me.BTT_DOWN_ALL, Me.BTT_DOWN_VIDEO, Me.BTT_DOWN_STOP, SEP_3, Me.MENU_VIEW, SEP_4, Me.BTT_LOG, Me.BTT_VERSION_INFO, Me.BTT_DONATE}) Me.Toolbar_TOP.Location = New System.Drawing.Point(0, 0) Me.Toolbar_TOP.Name = "Toolbar_TOP" Me.Toolbar_TOP.Size = New System.Drawing.Size(934, 25) @@ -426,20 +439,25 @@ Partial Class MainFrame Me.BTT_VERSION_INFO.Text = "Info" Me.BTT_VERSION_INFO.ToolTipText = "Show program information and check for new version" ' + 'BTT_DONATE + ' + Me.BTT_DONATE.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right + Me.BTT_DONATE.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image + Me.BTT_DONATE.Image = Global.SCrawler.My.Resources.Resources.HeartPic_32 + Me.BTT_DONATE.ImageTransparentColor = System.Drawing.Color.Magenta + Me.BTT_DONATE.Name = "BTT_DONATE" + Me.BTT_DONATE.Size = New System.Drawing.Size(23, 20) + Me.BTT_DONATE.Text = "Donate" + Me.BTT_DONATE.ToolTipText = "Donate" + ' 'Toolbar_BOTTOM ' - Me.Toolbar_BOTTOM.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.PR_SAVED, Me.PR_MAIN, Me.LBL_JOBS_COUNT, Me.LBL_STATUS}) + Me.Toolbar_BOTTOM.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.PR_MAIN, Me.LBL_JOBS_COUNT, Me.LBL_STATUS, Me.PR_INST, Me.LBL_JOBS_INST_COUNT, Me.LBL_STATUS_INST}) Me.Toolbar_BOTTOM.Location = New System.Drawing.Point(0, 439) Me.Toolbar_BOTTOM.Name = "Toolbar_BOTTOM" Me.Toolbar_BOTTOM.Size = New System.Drawing.Size(934, 22) Me.Toolbar_BOTTOM.TabIndex = 2 ' - 'PR_SAVED - ' - Me.PR_SAVED.Name = "PR_SAVED" - Me.PR_SAVED.Size = New System.Drawing.Size(100, 16) - Me.PR_SAVED.Visible = False - ' 'PR_MAIN ' Me.PR_MAIN.Name = "PR_MAIN" @@ -456,6 +474,22 @@ Partial Class MainFrame Me.LBL_STATUS.Name = "LBL_STATUS" Me.LBL_STATUS.Size = New System.Drawing.Size(0, 17) ' + 'PR_INST + ' + Me.PR_INST.Name = "PR_INST" + Me.PR_INST.Size = New System.Drawing.Size(200, 16) + Me.PR_INST.Visible = False + ' + 'LBL_JOBS_INST_COUNT + ' + Me.LBL_JOBS_INST_COUNT.Name = "LBL_JOBS_INST_COUNT" + Me.LBL_JOBS_INST_COUNT.Size = New System.Drawing.Size(0, 17) + ' + 'LBL_STATUS_INST + ' + Me.LBL_STATUS_INST.Name = "LBL_STATUS_INST" + Me.LBL_STATUS_INST.Size = New System.Drawing.Size(0, 17) + ' 'LIST_PROFILES ' Me.LIST_PROFILES.Activation = System.Windows.Forms.ItemActivation.OneClick @@ -580,6 +614,35 @@ Partial Class MainFrame Me.BTT_CONTEXT_INFO.Size = New System.Drawing.Size(221, 22) Me.BTT_CONTEXT_INFO.Text = "Information" ' + 'TrayIcon + ' + Me.TrayIcon.BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info + Me.TrayIcon.BalloonTipTitle = "Social networks crawler" + Me.TrayIcon.ContextMenuStrip = Me.TRAY_CONTEXT + Me.TrayIcon.Icon = CType(resources.GetObject("TrayIcon.Icon"), System.Drawing.Icon) + Me.TrayIcon.Text = "Social networks crawler" + ' + 'TRAY_CONTEXT + ' + Me.TRAY_CONTEXT.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_TRAY_SHOW_HIDE, TRAY_SEP_1, Me.BTT_TRAY_CLOSE}) + Me.TRAY_CONTEXT.Name = "TRAY_CONTEXT" + Me.TRAY_CONTEXT.Size = New System.Drawing.Size(134, 54) + ' + 'BTT_TRAY_SHOW_HIDE + ' + Me.BTT_TRAY_SHOW_HIDE.Name = "BTT_TRAY_SHOW_HIDE" + Me.BTT_TRAY_SHOW_HIDE.Size = New System.Drawing.Size(133, 22) + Me.BTT_TRAY_SHOW_HIDE.Text = "Show/Hide" + ' + 'BTT_TRAY_CLOSE + ' + Me.BTT_TRAY_CLOSE.BackColor = System.Drawing.Color.FromArgb(CType(CType(255, Byte), Integer), CType(CType(192, Byte), Integer), CType(CType(192, Byte), Integer)) + Me.BTT_TRAY_CLOSE.ForeColor = System.Drawing.Color.Maroon + Me.BTT_TRAY_CLOSE.Image = CType(resources.GetObject("BTT_TRAY_CLOSE.Image"), System.Drawing.Image) + Me.BTT_TRAY_CLOSE.Name = "BTT_TRAY_CLOSE" + Me.BTT_TRAY_CLOSE.Size = New System.Drawing.Size(133, 22) + Me.BTT_TRAY_CLOSE.Text = "Close" + ' 'MainFrame ' Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) @@ -598,6 +661,7 @@ Partial Class MainFrame Me.Toolbar_BOTTOM.ResumeLayout(False) Me.Toolbar_BOTTOM.PerformLayout() Me.USER_CONTEXT.ResumeLayout(False) + Me.TRAY_CONTEXT.ResumeLayout(False) Me.ResumeLayout(False) Me.PerformLayout() @@ -654,6 +718,14 @@ Partial Class MainFrame Private WithEvents BTT_SITE_ALL As ToolStripMenuItem Private WithEvents BTT_SITE_SPECIFIC As ToolStripMenuItem Private WithEvents BTT_CONTEXT_CHANGE_FOLDER As ToolStripMenuItem - Private WithEvents PR_SAVED As ToolStripProgressBar Private WithEvents BTT_DOWN_SAVED As ToolStripButton -End Class + Private WithEvents PR_INST As ToolStripProgressBar + Private WithEvents LBL_JOBS_INST_COUNT As ToolStripStatusLabel + Private WithEvents LBL_STATUS_INST As ToolStripStatusLabel + Private WithEvents TrayIcon As NotifyIcon + Private WithEvents TRAY_CONTEXT As ContextMenuStrip + Private WithEvents BTT_TRAY_SHOW_HIDE As ToolStripMenuItem + Private WithEvents BTT_TRAY_CLOSE As ToolStripMenuItem + Private WithEvents BTT_SETTINGS_REDGIFS As ToolStripMenuItem + Private WithEvents BTT_DONATE As ToolStripButton +End Class \ No newline at end of file diff --git a/SCrawler/MainFrame.resx b/SCrawler/MainFrame.resx index 2d3179e..073a238 100644 --- a/SCrawler/MainFrame.resx +++ b/SCrawler/MainFrame.resx @@ -159,6 +159,9 @@ False + + False + 132, 17 @@ -295,6 +298,207 @@ At+48gfYvPlXp/n+iqDm2Lj4f73w4kt1S+yWJa3+1e9fQ5Bp8ZkfwPMCwN9yOBn2+KfAk+ChX8G+Dps/ r1u/xd3D6+rf/v5+9YqVq6Sv/vF9Xh2XnFf8yCt5XGzeWrdeY+/glPLrtRte+M1bG1dBlPfP4uvT/xKb N95xYLfifeVScsnnXMZvA+8pi/7fhb+CbP4D9GPXvMEwYYwAAAAASUVORK5CYII= + + + + 525, 17 + + + 623, 17 + + + + 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 + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI8vLx+OMzL/jjMy/44zMv+OMzL/jjMy/4w4NOJTs2//U7Nv/1Oz + b/9Ts2//U7Nv/1O0cuI91/H/Pdfx/z3X8f891/H/Pdfx/z3X8f8ukuD/LpLg/y6S4P8ukuD/LpLg/y6S + 4P8vOs7/LzrO/y86zv8vOs7/LzrO/y86zv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI0yMjeOMzL/jjMy/44zMv+OMzL/jjMy/4tD + N9NTs2//U7Nv/1Ozb/9Ts2//U7Nv/1K1fNM91/H/Pdfx/z3X8f891/H/Pdfx/zzW8OkukuD/LpLg/y6S + 4P8ukuD/LpLg/y6R4PcvOs7/LzrO/y86zv8vOs7/LzrO/y86zuYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIwzM0+OMzL/jjMy/44z + Mv+OMzL/jjMy/4hRPcdTs2//U7Nv/1Ozb/9Ts2//U7Nv/1G4h8c91/H/Pdfx/z3X8f891/H/Pdfx/zzV + 8eIukuD/LpLg/y6S4P8ukuD/LpLg/y2R4OIvOs7/LzrO/y86zv8vOs7/LzrO/y46zd4AAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI4z + MZ6OMzL/jjMy/44zMv+OMzL/jjMy/4NiRMBTs2//U7Nv/1Ozb/9Ts2//U7Nv/067mMA91/H/Pdfx/z3X + 8f891/H/Pdfx/zzR78sukuD/LpLg/y6S4P8ukuD/LpLg/y2Q39cvOs7/LzrO/y86zv8vOs7/LzrO/y86 + ztYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAI0zMu6OMzL/jjMy/44zMv+OMzL/jjMy/26RXMdTs2//U7Nv/1Ozb/9Ts2//U7Nv/0vB + rr491/H/Pdfx/z3X8f891/H/Pdfx/zjI7b8ukuD/LpLg/y6S4P8ukuD/LpLg/y2J3cUvOs7/LzrO/y86 + zv8vOs7/LzrO/y46zq4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAjzMzP44zMv+OMzL/jjMy/44zMv+OMzL/jjIx91SwbvZTs2//U7Nv/1Oz + b/9Ts2//U7Nv/0XM1M491/H/Pdfx/z3X8f891/H/Pdfx/za66cAukuD/LpLg/y6S4P8ukuD/LpLg/y55 + 2b4vOs7/LzrO/y86zv8vOs7/LzrO/y46zo4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjjIxro4zMv+OMzL/jjMy/44zMv+OMzL/iUw7y1Oz + b/9Ts2//U7Nv/1Ozb/9Ts2//U7Nv7z3X8f891/H/Pdfx/z3X8f891/H/Pdfx/zCk49cukuD/LpLg/y6S + 4P8ukuD/LpLg/y1p1ccvOs7/LzrO/y86zv8vOs7/LzrO/y46zWcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPNC4vjjMy/44zMv+OMzL/jjMy/44z + Mv+OMzL/dIdXwlOzb/9Ts2//U7Nv/1Ozb/9Ts2//T7qSwj3X8f891/H/Pdfx/z3X8f891/H/PNXx4i6S + 4P8ukuD/LpLg/y6S4P8ukuD/LpLg/y5N0OIvOs7/LzrO/y86zv8vOs7/LzrO/y07zDcAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNMjLOjjMy/44z + Mv+OMzL/jjMy/44zMv+NNDLvWqpr6FOzb/9Ts2//U7Nv/1Ozb/9Ts2//RsnKxz3X8f891/H/Pdfx/z3X + 8f891/H/OcvtwC6S4P8ukuD/LpLg/y6S4P8ukuD/LZHg4i86zv8vOs7/LzrO/y86zv8vOs7/LzrO/y4+ + zw8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI4z + MHeOMzL/jjMy/44zMv+OMzL/jjMy/44zMv95flG/U7Nv/1Ozb/9Ts2//U7Nv/1Ozb/9Ssm/3PdXt9j3X + 8f891/H/Pdfx/z3X8f891/H/M63myi6S4P8ukuD/LpLg/y6S4P8ukuD/Lobcwi86zv8vOs7/LzrO/y86 + zv8vOs7/LjnNzgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAjDMzT44zMv+OMzL/jjMy/44zMv+OMzL/jjMy/441MulUsG72U7Nv/1Ozb/9Ts2//U7Nv/1Oz + b/9PuI3FPdfx/z3X8f891/H/Pdfx/z3X8f881/HvLpTh9i6S4P8ukuD/LpLg/y6S4P8ukuD/LXDXwi86 + zv8vOs7/LzrO/y86zv8vOs7/LjrOjgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACvhoQ4jzg39o4zMv+OMzL/jjMy/44zMv+OMzL/jjMy/3SHV8JTs2//U7Nv/1Oz + b/9Ts2//U7Nv/1Ozb/9D0NzXPdfx/z3X8f891/H/Pdfx/z3X8f87zu7FLpLg/y6S4P8ukuD/LpLg/y6S + 4P8ukuD/Lk3Q4i86zv8vOs7/LzrO/y86zv8vOs7/LznMTwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAALKPjmi5mpn4roaG/485OP+OMzL/jjMy/44zMv+OMzL/i0c5zlOz + b/9Ts2//U7Nv/1Ozb/9Ts2//U7Nv/067mMA91/H/Pdfx/z3X8f891/H/Pdfx/z3X8f82uOjCLpLg/y6S + 4P8ukuD/LpLg/y6S4P8ujt/ULzrO/y86zv8vOs7/LzrO/y86zv8vOs7/Lj7PDwAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtJKSkrmamv+5mpr/uZqa/66Ghv+POTj/jjMy/44z + Mv+MODTiWqpr6FOzb/9Ts2//U7Nv/1Ozb/9Ts2//UrJv9z/U5+g91/H/Pdfx/z3X8f891/H/Pdfx/zzW + 8OkulOH2LpLg/y6S4P8ukuD/LpLg/y6S4P8ucdfFLzrO/y86zv8vOs7/LzrO/y86zv8uOs6+AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALKPj1+4l5fguZqa/7mamv+5mpr/uZqa/7ma + mv+uhob/jzk4/44yMfdkoGTXU7Nv/1Ozb/9Ts2//U7Nv/1Ozb/9Ts2//Tr2dvz3X8f891/H/Pdfx/z3X + 8f891/H/Pdfx/za46MIukuD/LpLg/y6S4P8ukuD/LpLg/y6R4PcvQ8/2LzrO/y86zv8vOs7/LzrO/y86 + zv8uOs1nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKd+fhuzkJBxtZKS2bmamv+5mpr/uZqa/7ma + mv+5mpr/uZqa/7mamv+5mpr/roaG/3GTYMdTs2//U7Nv/1Ozb/9Ts2//U7Nv/1Ozb/9SsnHpP9Tn6D3X + 8f891/H/Pdfx/z3X8f891/H/PNXw1y6S4P8ukuD/LpLg/y6S4P8ukuD/LpLg/y6C278vOs7/LzrO/y86 + zv8vOs7/LzrO/y85zvYuPs8PAAAAAAAAAACzjY1Ns42NTbOQkHG0kpKSt5aWzLmamv+5mpr/uZqa/7ma + mv+5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+7nZzzssOu2ZHGnf9WtHH/U7Nv/1Ozb/9Ts2//U7Nv/1Ky + b/dFzNTOPdfx/z3X8f891/H/Pdfx/z3X8f891/H/NLDmxy6S4P8ukuD/LpLg/y6S4P8ukuD/LpHg9y5K + 0OgvOs7/LzrO/y86zv8vOs7/LzrO/y46zq4AAAAAAAAAAAAAAAC5mpr/uZqa/7mamv+5mpr/uZqa/7ma + mv+5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+5mpr/uZqa/72hoOerya7mos2s/6LNrP+Rxp3/VrRx/1Oz + b/9Ts2//U7Nv/0nFusA91/H/Pdfx/z3X8f891/H/Pdfx/z3X8f880vDOLpLg/y6S4P8ukuD/LpLg/y6S + 4P8ukuD/LoDbyS86zv8vOs7/LzrO/y86zv8vOs7/LzrO/y85zE8AAAAAAAAAAAAAAAC5mpr/uZqa/7ma + mv+5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+5mpr/vaml2qbMrPOizaz/os2s/6LN + rP+izaz/kcad/1a0cf9Ts2//Tr2dvz3X8f891/H/Pdfx/z3X8f891/H/Pdfx/z3X8f8wpOPXLpLg/y6S + 4P8ukuD/LpLg/y6S4P8ukODpLkDP9i86zv8vOs7/LzrO/y86zv8vOs7/LjnNzgAAAAAAAAAAAAAAAAAA + AAC5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+5mpr/uZqa/72jouOyw67Zos2s/6LN + rP+izaz/os2s/6LNrP+izaz/os2s/5HGnf9VuIbLPdfx/z3X8f891/H/Pdfx/z3X8f891/H/Pdfx/zjG + 7L4ukuD/LpLg/y6S4P8ukuD/LpLg/y6S4P8td9i/LzrO/y86zv8vOs7/LzrO/y86zv8vOs7/LznMTwAA + AAAAAAAAAAAAAAAAAAC5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+8np7vtr6t1KLN + rP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6vUvdeK3/H3Qtfx/z3X8f891/H/Pdfx/z3X + 8f891/H/O9Dvxy6S4P8ukuD/LpLg/y6S4P8ukuD/LpLg/y6Q4OsuQM/2LzrO/y86zv8vOs7/LzrO/y86 + zv8uOc3OAAAAAAAAAAAAAAAAAAAAAAAAAAC5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+8oJ/qvLGp07LD + rtmizaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/rNjL0Zzk9f+c5PX/ieD0/0LX + 8f891/H/Pdfx/z3X8f871O/eLpTh9i6S4P8ukuD/LpLg/y6S4P8ukuD/LpLg/y1p1ccvOs7/LzrO/y86 + zv8vOs7/LzrO/y86zv8vOcxPAAAAAAAAAAAAAAAAAAAAAAAAAAC+p6Tcvqek3L2vqNS6t6vSurms0a3H + reOizaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6PNrfmp3dzVnOT1/5zk + 9f+c5PX/nOT1/4ng9P9C1/H/Pdfx/zzX8fAwnuLiLpLg/y6S4P8ukuD/LpLg/y6S4P8ukuD/Lo3e0C86 + zv8vOs7/LzrO/y86zv8vOs7/LzrO/y45zc4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACizaz/os2s/6LN + rP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/pc6v76Xg + 5d+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+J4PT/Qdbw9zKr5dQukuD/LpLg/y6S4P8ukuD/LpLg/y6S + 4P8tkeDjLkPO7y86zv8vOs7/LzrO/y86zv8vOs7/LzrO/y46zy8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACizaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6TP + rvOr2tDRnePy+Jzk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+d4/T5j8nt2TST4P8ukuD/LpLg/y6S + 4P8ukuD/LpLg/y6R4PcuVdHkLzrO/y86zv8vOs7/LzrO/y86zv8vOs7/LjnOngAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACizaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LN + rP+jza35rNjI0p/j8fOc5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5/k9e+hyu7jmbvq/4Wx + 5/80k+D/LpLg/y6S4P8ukuD/LpLg/y5o1cwvOs7/LzrO/y86zv8vOs7/LzrO/y86zv8uOc3uKTTJFwAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACizaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LN + rP+izaz/ptCx6qvXxdOh4e3qnOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/ouP15JzD + 6/SZu+r/mbvq/5m76v+Fsef/NJPg/y6S4P8ukuD/LXvZxi86zv8vOs7/LzrO/y86zv8vOs7/LzrO/y86 + zv8uOM1HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACizaz/os2s/6LNrP+izaz/os2s/6LN + rP+izaz/p9Cz56vZztKk4ejjnOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk + 9f+l4PTZmr3q+Jm76v+Zu+r/mbvq/5m76v+Zu+r/hbHn/zST4P8uiN3MLzrO/y86zv8vOs7/LzrO/y86 + zv8vOs7/LzrO/y84zG8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACp0rjcqdK43KvW + wtSr2c7Sq9rQ0aff5Nyh4e3qnOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk + 9f+c5PX/nOT1/6ba8teZu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/42z5941Rc/2LzrO/y86 + zv8vOs7/LzrO/y86zv8vOs7/LznOlgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACc5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk + 9f+c5PX/nOT1/5zk9f+l4fTbncPr75m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/o73p2Zqe + 3/iFiNr/NT/O/y86zv8vOs7/LzrO/y86zv8uOs6+HD2+BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACc5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk + 9f+c5PX/nOT1/5zk9f+c5PX/pOL13qHK7uOZu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m7 + 6v+ltufVmZve/5mb3v+Zm97/hYja/zU/zv8vOs7/LzrO/y46zd4uPs8PAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACc5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk + 9f+c5PX/nOT1/5zk9f+c5PX/nOT1/6Hj9Oeiz+/fmbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m7 + 6v+Zu+r/nL3q86Ku5N6Zm97/mZve/5mb3v+Zm97/mZve/4WI2v81P87/LjnN7iw5zCcAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACc5PX/nOT1/5zk9f+c5PX/nOT1/5zk + 9f+c5PX/nOT1/5zk9f+c5PX/nOT1/6Hj9eun3vPSoszu4Jm76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m7 + 6v+Zu+r/mbvq/5m76v+fvurnn6fh5pmb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Fh9n3LjjNRwAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACc5PX/nOT1/5zk + 9f+c5PX/nOT1/5zk9f+c5PX/nOT1/6Tk9OCn2PHSoMfs5pm76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m7 + 6v+Zu+r/mbvq/5m76v+Zu+r/mbvq/6O/6tqcoN/zmZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5aY + 3fJ/gtlJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACl4/XcpeP13KXj9dyl4/Xcp93z0afY8dKjze7cnMDr85m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m7 + 6v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+gv+rjoq7j3Jmb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb + 3v+Zm97/lJbc2X6A2SUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACZu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m7 + 6v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/nr7q6qWz5dWZm97/mZve/5mb3v+Zm97/mZve/5mb + 3v+Zm97/mZve/5mb3v+Sld2+aXDWEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m7 + 6v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5y96vOmuOfSmp7f+Jmb3v+Zm97/mZve/5mb + 3v+Zm97/mZve/5mb3v+Zm97/mZve/4mL2pYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZu+r/mbvq/5m76v+Zu+r/mbvq/5m7 + 6v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+dvervprrn0pyg3/OZm97/mZve/5mb + 3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+WmN34io3aZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZu+r/mbvq/5m7 + 6v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+avOr5pL7q1qOw5NmZm97/mZve/5mb + 3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5OW3eyEh9o4AAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACZu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+iv+rcprrn0qKu49yZm97/mZve/5mb + 3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm974i43al4SLzwgAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACiv+rcor/q3KK/6tyiv+rcpL7q16a659KksuXXoKni45mb3v+Zm97/mZve/5mb + 3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5SW3cWEh9gvAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb + 3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Vl93MjY/cTQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZm97/mZve/5mb3v+Zm97/mZve/5mb + 3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/kJLcy42P + 3E0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZm97/mZve/5mb + 3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/lZfd7I2P + 26aEh9o4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACZm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mJre7JOV + 3bCHitlUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACZm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Ymt3ylJbdvo+R + 23mMj9oxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVl93MlZfdzJWX3cyVl93MlJbdxZGT25KPkdpxjY/cTYSL + zwgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//8AAAAAAAP//gAAAAAAA//+AAAAA + AAD//4AAAAAAAP//gAAAAAAA//+AAAAAAAD//wAAAAAAAP//AAAAAAAA//4AAAAAAAD//gAAAAAAAP/8 + AAAAAQAA//gAAAABAAD/8AAAAAEAAP/gAAAAAQAA/8AAAAADAAD/AAAAAAMAAPgAAAAAAwAAAAAAAAAH + AAAAAAAAAAcAAAAAAAAADwAAAAAAAAAPAAAAAAAAAB8AAAAAAAAAHwAAAAAAAAA/AAAAAAAAAD8AAAAA + AAAAfwAAAAAAAAB/AAAAAAAAAP8AAAAAAAAB/wAAAAAAAAP/AAAAAAAAA/8AAAAAAAAH/wAAAAAAAA// + AAAAAAAAH/8AAAAAAAA//wAAAAAAAH//AAAAAAAA//8AAAAAAAP//wAAAAAAB///AAAAAAAP//8AAAAA + AB///wAAAAAAf///AAAAAAH///8AAAAAB////wAAAAAf////AAAAAP////8AAAAH/////wAAAH////// + AAA= diff --git a/SCrawler/MainFrame.vb b/SCrawler/MainFrame.vb index 79332e7..719e0c3 100644 --- a/SCrawler/MainFrame.vb +++ b/SCrawler/MainFrame.vb @@ -17,6 +17,7 @@ Public Class MainFrame Private MyView As FormsView Private ReadOnly _VideoDownloadingMode As Boolean = False Private MyChannels As ChannelViewForm + Private MySavedPosts As DownloadSavedPostsForm Private _UFinit As Boolean = True Public Sub New() InitializeComponent() @@ -29,21 +30,24 @@ Public Class MainFrame If Args.ListExists(2) AndAlso Args(1) = "v" Then Using f As New VideosDownloaderForm : f.ShowDialog() : End Using _VideoDownloadingMode = True - Else - Downloader = New TDownloader End If End Sub Private Sub MainFrame_Load(sender As Object, e As EventArgs) Handles Me.Load If _VideoDownloadingMode Then GoTo FormClosingInvoker + Settings.DeleteCachPath() + MainProgress = New Toolbars.MyProgress(Toolbar_BOTTOM, PR_MAIN, LBL_STATUS) With {.DropCurrentProgressOnTotalChange = False, .Enabled = False} + MainProgressInst = New Toolbars.MyProgress(Toolbar_BOTTOM, PR_INST, LBL_STATUS_INST) With {.DropCurrentProgressOnTotalChange = False, .Enabled = False} + Downloader = New TDownloader InfoForm = New DownloadedInfoForm AddHandler Downloader.OnJobsChange, AddressOf Downloader_UpdateJobsCount AddHandler Downloader.OnDownloading, AddressOf Downloader_OnDownloading AddHandler Downloader.OnDownloadCountChange, AddressOf InfoForm.Downloader_OnDownloadCountChange + AddHandler Downloader.SendNotification, AddressOf NotificationMessage Settings.LoadUsers() MyView = New FormsView(Me) MyView.ImportFromXML(Settings.Design) MyView.SetMeSize() - MainProgress = New Toolbars.MyProgress(Toolbar_BOTTOM, PR_MAIN, LBL_STATUS) With {.DropCurrentProgressOnTotalChange = False} + If Settings.CloseToTray Then TrayIcon.Visible = True Dim gk$ With LIST_PROFILES.Groups 'Collections @@ -92,40 +96,80 @@ FormClosingInvoker: EndFunction: End Sub Private _CloseInvoked As Boolean = False + Private _IgnoreTrayOptions As Boolean = False + Private _IgnoreCloseConfirm As Boolean = False Private Async Sub MainFrame_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing - If Not _VideoDownloadingMode Then - If _CloseInvoked Then GoTo CloseResume - Dim ChannelsWorking As Func(Of Boolean) = Function() If(MyChannels?.Working, False) - If (Not Downloader.Working And Not ChannelsWorking.Invoke) OrElse - MsgBoxE({"Program still downloading something..." & vbNewLine & - "Do you really want to stop downloading and exit of program?", - "Downloading in progress"}, - MsgBoxStyle.Exclamation,,, - {"Stop downloading and close", "Cancel"}) = 0 Then - If Downloader.Working Then _CloseInvoked = True : Downloader.Stop() : Downloader.DownloadSavedPostsStop() - If Downloader.SavedPostsDownloading Then _CloseInvoked = True : Downloader.DownloadSavedPostsStop() - If ChannelsWorking.Invoke Then _CloseInvoked = True : MyChannels.Stop(False) - If _CloseInvoked Then - e.Cancel = True - Await Task.Run(Sub() - While Downloader.Working Or ChannelsWorking.Invoke Or Downloader.SavedPostsDownloading : Thread.Sleep(500) : End While - End Sub) + If Settings.CloseToTray And Not _IgnoreTrayOptions Then + e.Cancel = True + Hide() + Else + If Not _VideoDownloadingMode Then + If CheckForClose(_IgnoreCloseConfirm) Then + If _CloseInvoked Then GoTo CloseResume + Dim ChannelsWorking As Func(Of Boolean) = Function() If(MyChannels?.Working, False) + Dim SP_Working As Func(Of Boolean) = Function() If(MySavedPosts?.Working, False) + If (Not Downloader.Working And Not ChannelsWorking.Invoke And Not SP_Working.Invoke) OrElse + MsgBoxE({"Program still downloading something..." & vbNewLine & + "Do you really want to stop downloading and exit of program?", + "Downloading in progress"}, + MsgBoxStyle.Exclamation,,, + {"Stop downloading and close", "Cancel"}) = 0 Then + If Downloader.Working Then _CloseInvoked = True : Downloader.Stop() + If ChannelsWorking.Invoke Then _CloseInvoked = True : MyChannels.Stop(False) + If SP_Working.Invoke Then _CloseInvoked = True : MySavedPosts.Stop() + If _CloseInvoked Then + e.Cancel = True + Await Task.Run(Sub() + While Downloader.Working Or ChannelsWorking.Invoke Or SP_Working.Invoke : Thread.Sleep(500) : End While + End Sub) + End If + Downloader.Dispose() + InfoForm.Dispose() + If Not MyChannels Is Nothing Then MyChannels.Dispose() + If Not VideoDownloader Is Nothing Then VideoDownloader.Dispose() + If Not MySavedPosts Is Nothing Then MySavedPosts.Dispose() + MyView.Dispose(Settings.Design) + Settings.Dispose() + Else + GoTo DropCloseParams + End If + Else + GoTo DropCloseParams End If - Downloader.Dispose() - InfoForm.Dispose() - If Not MyChannels Is Nothing Then MyChannels.Dispose() - If Not VideoDownloader Is Nothing Then VideoDownloader.Dispose() - MyView.Dispose(Settings.Design) - Settings.Dispose() - Else - e.Cancel = True - Exit Sub End If - End If - If Not MyMainLOG.IsEmptyString Then SaveLogToFile() - If _CloseInvoked Then Close() + GoTo CloseContinue +DropCloseParams: + e.Cancel = True + _IgnoreTrayOptions = False + _IgnoreCloseConfirm = False + _CloseInvoked = False + Exit Sub +CloseContinue: + If Not MyMainLOG.IsEmptyString Then SaveLogToFile() + If _CloseInvoked Then Close() CloseResume: + End If End Sub +#Region "Tray" + Private Sub TrayIcon_MouseClick(sender As Object, e As MouseEventArgs) Handles TrayIcon.MouseClick + If e.Button = MouseButtons.Left Then + If Visible Then Hide() Else Show() + End If + End Sub + Private Sub BTT_TRAY_SHOW_HIDE_Click(sender As Object, e As EventArgs) Handles BTT_TRAY_SHOW_HIDE.Click + If Visible Then Hide() Else Show() + End Sub + Private Sub BTT_TRAY_CLOSE_Click(sender As Object, e As EventArgs) Handles BTT_TRAY_CLOSE.Click + If CheckForClose(False) Then _IgnoreTrayOptions = True : _IgnoreCloseConfirm = True : Close() + End Sub + Private Function CheckForClose(ByVal _Ignore As Boolean) As Boolean + If Settings.ExitConfirm And Not _Ignore Then + Return MsgBoxE({"Do you want to close the program?", "Closing the program"}, MsgBoxStyle.YesNo) = MsgBoxResult.Yes + Else + Return True + End If + End Function +#End Region Private Sub MainFrame_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown Dim b As Boolean = True Select Case e.KeyCode @@ -262,6 +306,9 @@ CloseResume: Private Sub BTT_SETTINGS_INSTAGRAM_Click(sender As Object, e As EventArgs) Handles BTT_SETTINGS_INSTAGRAM.Click Using f As New SiteEditorForm(Sites.Instagram) : f.ShowDialog() : End Using End Sub + Private Sub BTT_SETTINGS_REDGIFS_Click(sender As Object, e As EventArgs) Handles BTT_SETTINGS_REDGIFS.Click + Using f As New SiteEditorForm(Sites.RedGifs) : f.ShowDialog() : End Using + End Sub Private Sub BTT_SETTINGS_Click(sender As Object, e As EventArgs) Handles BTT_SETTINGS.Click Dim mhl% = Settings.MaxLargeImageHeigh.Value Dim mhs% = Settings.MaxSmallImageHeigh.Value @@ -269,6 +316,7 @@ CloseResume: f.ShowDialog() If f.DialogResult = DialogResult.OK Then If Not Settings.MaxLargeImageHeigh = mhl Or Not Settings.MaxSmallImageHeigh = mhs Then RefillList() + TrayIcon.Visible = Settings.CloseToTray End If End Using End Sub @@ -356,11 +404,18 @@ CloseResume: If MyChannels Is Nothing Then MyChannels = New ChannelViewForm AddHandler MyChannels.OnUsersAdded, AddressOf OnUsersAddedHandler + AddHandler MyChannels.OnDownloadDone, AddressOf NotificationMessage End If If MyChannels.Visible Then MyChannels.BringToFront() Else MyChannels.Show() End Sub Private Sub BTT_DOWN_SAVED_Click(sender As Object, e As EventArgs) Handles BTT_DOWN_SAVED.Click - Downloader.DownloadSavedPostsStart(Toolbar_BOTTOM, PR_SAVED) + If MySavedPosts Is Nothing Then + MySavedPosts = New DownloadSavedPostsForm + AddHandler MySavedPosts.OnDownloadDone, AddressOf NotificationMessage + End If + With MySavedPosts + If .Visible Then .BringToFront() Else .Show() + End With End Sub #End Region #Region "Download" @@ -507,6 +562,9 @@ CloseResume: Private Sub BTT_LOG_Click(sender As Object, e As EventArgs) Handles BTT_LOG.Click MyMainLOG_ShowForm(Settings.Design) End Sub + Private Sub BTT_DONATE_Click(sender As Object, e As EventArgs) Handles BTT_DONATE.Click + Try : Process.Start("https://ko-fi.com/andyprogram") : Catch : End Try + End Sub #Region "List functions" Private _LatestSelected As Integer = -1 Private Sub LIST_PROFILES_SelectedIndexChanged(sender As Object, e As EventArgs) Handles LIST_PROFILES.SelectedIndexChanged @@ -988,18 +1046,30 @@ ResumeDownloadingOperation: Friend Sub User_OnUserUpdated(ByVal User As IUserData) UserListUpdate(User, False) End Sub - Private _LogVisible As Boolean = False - Private Sub Downloader_UpdateJobsCount(ByVal TotalCount As Integer) - Dim a As Action = Sub() LBL_JOBS_COUNT.Text = IIf(TotalCount = 0, String.Empty, $"[Jobs {TotalCount}]") + Private _LogColorChanged As Boolean = False + Private Sub Downloader_UpdateJobsCount(ByVal Site As Sites, ByVal TotalCount As Integer) + Dim a As Action + If Site = Sites.Instagram Then + a = Sub() LBL_JOBS_INST_COUNT.Text = IIf(TotalCount = 0, String.Empty, $"[Jobs {TotalCount}]") + Else + a = Sub() LBL_JOBS_COUNT.Text = IIf(TotalCount = 0, String.Empty, $"[Jobs {TotalCount}]") + End If If Toolbar_BOTTOM.InvokeRequired Then Toolbar_BOTTOM.Invoke(a) Else a.Invoke - If Not _LogVisible AndAlso Not MyMainLOG.IsEmptyString Then + If Not _LogColorChanged AndAlso Not MyMainLOG.IsEmptyString Then a = Sub() BTT_LOG.ControlChangeColor(False) If Toolbar_TOP.InvokeRequired Then Toolbar_TOP.Invoke(a) Else a.Invoke - _LogVisible = True + _LogColorChanged = True + ElseIf _LogColorChanged And MyMainLOG.IsEmptyString Then + a = Sub() BTT_LOG.ControlChangeColor(SystemColors.Control, SystemColors.ControlText) + If Toolbar_TOP.InvokeRequired Then Toolbar_TOP.Invoke(a) Else a.Invoke + _LogColorChanged = False End If End Sub Private Sub Downloader_OnDownloading(ByVal Value As Boolean) Dim a As Action = Sub() BTT_DOWN_STOP.Enabled = Value If Toolbar_TOP.InvokeRequired Then Toolbar_TOP.Invoke(a) Else a.Invoke End Sub + Private Sub NotificationMessage(ByVal Message As String) + If Settings.ShowNotifications Then TrayIcon.ShowBalloonTip(2000, TrayIcon.BalloonTipTitle, Message, ToolTipIcon.Info) + End Sub End Class \ No newline at end of file diff --git a/SCrawler/MainMod.vb b/SCrawler/MainMod.vb index 451e976..a2e2a5a 100644 --- a/SCrawler/MainMod.vb +++ b/SCrawler/MainMod.vb @@ -8,6 +8,7 @@ ' but WITHOUT ANY WARRANTY Imports PersonalUtilities.Functions.XML Imports PersonalUtilities.Tools.WEB +Imports PersonalUtilities.Forms.Toolbars Imports SCrawler.API Imports SCrawler.API.Base Friend Module MainMod @@ -44,11 +45,12 @@ Friend Module MainMod Friend Class NumberedFile : Inherits SFileNumbers Friend Sub New(ByVal f As SFile) FileName = f.Name - NumberProvider = New ANumbers With {.FormatMode = ANumbers.Formats.NumberGroup, .GroupSize = 5} + NumberProvider = New ANumbers With {.Format = ANumbers.Formats.NumberGroup, .GroupSize = 5} End Sub End Class #End Region - Friend Property MainProgress As PersonalUtilities.Forms.Toolbars.MyProgress + Friend Property MainProgress As MyProgress + Friend Property MainProgressInst As MyProgress Friend Function GetLviGroupName(ByVal Site As Sites, ByVal Temp As Boolean, ByVal Fav As Boolean, ByVal IsCollection As Boolean, ByVal IsChannel As Boolean) As String Dim Opt$ = String.Empty @@ -71,6 +73,7 @@ Friend Module MainMod Reddit = 1 Twitter = 2 Instagram = 3 + RedGifs = 4 End Enum Friend Structure UserInfo : Implements IComparable(Of UserInfo), IEquatable(Of UserInfo), ICloneable Friend Const Name_Site As String = "Site" @@ -208,7 +211,7 @@ Friend Module MainMod End Function Friend Function GetNewVideoURL() As String Dim b$ = GetCurrentBuffer() - Dim URL$ = InputBox("Enter video URL:", "Download video by URL", b) + Dim URL$ = InputBoxE("Enter video URL:", "Download video by URL", b) If Not URL.IsEmptyString Then Return URL Else Return String.Empty End Function Friend Sub DownloadVideoByURL() diff --git a/SCrawler/My Project/AssemblyInfo.vb b/SCrawler/My Project/AssemblyInfo.vb index 9f970da..ab12c70 100644 --- a/SCrawler/My Project/AssemblyInfo.vb +++ b/SCrawler/My Project/AssemblyInfo.vb @@ -10,7 +10,7 @@ Imports System.Runtime.InteropServices ' Review the values of the assembly attributes - + @@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices ' by using the '*' as shown below: ' - - + + diff --git a/SCrawler/My Project/Resources.Designer.vb b/SCrawler/My Project/Resources.Designer.vb index ca8e314..7df0ec4 100644 --- a/SCrawler/My Project/Resources.Designer.vb +++ b/SCrawler/My Project/Resources.Designer.vb @@ -110,6 +110,16 @@ Namespace My.Resources End Get End Property + ''' + ''' Looks up a localized resource of type System.Drawing.Bitmap. + ''' + Friend ReadOnly Property HeartPic_32() As System.Drawing.Bitmap + Get + Dim obj As Object = ResourceManager.GetObject("HeartPic_32", resourceCulture) + Return CType(obj,System.Drawing.Bitmap) + End Get + End Property + ''' ''' Looks up a localized resource of type System.Drawing.Bitmap. ''' diff --git a/SCrawler/My Project/Resources.resx b/SCrawler/My Project/Resources.resx index b3f56db..027e42f 100644 --- a/SCrawler/My Project/Resources.resx +++ b/SCrawler/My Project/Resources.resx @@ -124,12 +124,18 @@ ..\Content\Pictures\PrevPIC2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Content\Pictures\StartPic_01_Green_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Content\Pictures\PencilPic_01_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Content\Pictures\NextPIC2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Content\Pictures\BookmarkBlack_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Content\Pictures\Folder_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -142,14 +148,11 @@ ..\Content\Icons\TwitterIcon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Content\Pictures\SettingsPic_16.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Content\Pictures\Delete.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Content\Pictures\InfoPic_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Content\Pictures\InstagramPic76.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Content\Icons\InstagramIcon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -157,18 +160,18 @@ ..\Content\Pictures\GlobeBlue_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Content\Pictures\PicturePic_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Content\Pictures\InfoPic_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Content\Pictures\Refresh.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Content\Pictures\PicturePic_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Content\Icons\RedditIcon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Content\Pictures\InstagramPic76.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Content\Icons\Rainbow.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -181,10 +184,10 @@ ..\Content\Pictures\DBPic_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Content\Pictures\StartPic_01_Green_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Content\Pictures\SettingsPic_16.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Content\Pictures\BookmarkBlack_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Content\Pictures\HeartPic_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a \ No newline at end of file diff --git a/SCrawler/SCrawler.vbproj b/SCrawler/SCrawler.vbproj index 02f2ea9..a63aad7 100644 --- a/SCrawler/SCrawler.vbproj +++ b/SCrawler/SCrawler.vbproj @@ -139,6 +139,7 @@ + @@ -146,9 +147,17 @@ + + + + ChannelsStatsForm.vb + + + Form + ChannelViewForm.vb @@ -161,6 +170,12 @@ Form + + DownloadSavedPostsForm.vb + + + Form + CollectionEditorForm.vb @@ -179,6 +194,9 @@ Form + + Component + SiteSelectionForm.vb @@ -233,12 +251,18 @@ + + ChannelsStatsForm.vb + ChannelViewForm.vb DownloadedInfoForm.vb + + DownloadSavedPostsForm.vb + CollectionEditorForm.vb @@ -296,6 +320,7 @@ + PreserveNewest diff --git a/SCrawler/SettingsCLS.vb b/SCrawler/SettingsCLS.vb index b99f86c..4606045 100644 --- a/SCrawler/SettingsCLS.vb +++ b/SCrawler/SettingsCLS.vb @@ -61,7 +61,8 @@ Friend Class SettingsCLS : Implements IDisposable MySites = New Dictionary(Of Sites, SiteSettings) From { {Sites.Reddit, New SiteSettings(Sites.Reddit, MyXML, GlobalPath.Value, DefaultTemporary, DefaultDownloadImages, DefaultDownloadVideos)}, {Sites.Twitter, New SiteSettings(Sites.Twitter, MyXML, GlobalPath.Value, DefaultTemporary, DefaultDownloadImages, DefaultDownloadVideos)}, - {Sites.Instagram, New SiteSettings(Sites.Instagram, MyXML, GlobalPath.Value, DefaultTemporary, DefaultDownloadImages, DefaultDownloadVideos)} + {Sites.Instagram, New SiteSettings(Sites.Instagram, MyXML, GlobalPath.Value, DefaultTemporary, DefaultDownloadImages, DefaultDownloadVideos)}, + {Sites.RedGifs, New SiteSettings(Sites.RedGifs, MyXML, GlobalPath.Value, DefaultTemporary, DefaultDownloadImages, DefaultDownloadVideos)} } MySites(Sites.Reddit).Responser.Decoders.Add(SymbolsConverter.Converters.Unicode) @@ -120,7 +121,12 @@ Friend Class SettingsCLS : Implements IDisposable ShowNewVersionNotification = New XMLValue(Of Boolean)("ShowNewVersionNotification", True, MyXML) LatestVersion = New XMLValue(Of String)("LatestVersion", String.Empty, MyXML) + ExitConfirm = New XMLValue(Of Boolean)("ExitConfirm", True, MyXML) + CloseToTray = New XMLValue(Of Boolean)("CloseToTray", True, MyXML) + ShowNotifications = New XMLValue(Of Boolean)("ShowNotifications", True, MyXML) + If MyXML.ChangesDetected Then MyXML.Sort() : MyXML.UpdateData() + Labels = New LabelsKeeper If Not LatestSelectedLabels.IsEmptyString Then Labels.CurrentSelection.ListAddList(LatestSelectedLabels.Value.StringToList(Of String, List(Of String))("|")) If BlackListFile.Exists Then @@ -253,6 +259,10 @@ Friend Class SettingsCLS : Implements IDisposable If BlackListFile.Exists Then BlackListFile.Delete() End If End Sub + Friend Sub DeleteCachPath() + If Reddit.ChannelsCollection.ChannelsPathCache.Exists(SFO.Path, False) Then _ + Reddit.ChannelsCollection.ChannelsPathCache.Delete(SFO.Path, False, False, EDP.None) + End Sub Friend Overloads Function UserExists(ByVal s As Sites, ByVal UserID As String) As Boolean Dim UserFinderBase As Predicate(Of IUserData) = Function(user) user.Site = s And user.Name = UserID Dim UserFinder As Predicate(Of IUserData) = Function(ByVal user As IUserData) As Boolean @@ -369,6 +379,11 @@ Friend Class SettingsCLS : Implements IDisposable Friend ReadOnly Property ShowNewVersionNotification As XMLValue(Of Boolean) Friend ReadOnly Property LatestVersion As XMLValue(Of String) #End Region +#Region "Other program properties" + Friend ReadOnly Property ExitConfirm As XMLValue(Of Boolean) + Friend ReadOnly Property CloseToTray As XMLValue(Of Boolean) + Friend ReadOnly Property ShowNotifications As XMLValue(Of Boolean) +#End Region #Region "IDisposable Support" Private disposedValue As Boolean = False Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean) @@ -377,8 +392,7 @@ Friend Class SettingsCLS : Implements IDisposable If UserListUpdateRequired Then UpdateUsersList() If Not Channels Is Nothing Then Channels.Dispose() - If Reddit.ChannelsCollection.ChannelsPathCache.Exists(SFO.Path, False) Then _ - Reddit.ChannelsCollection.ChannelsPathCache.Delete(SFO.Path, False, False, EDP.None) + DeleteCachPath() End If For Each kv In MySites : kv.Value.Dispose() : Next MySites.Clear() diff --git a/SCrawler/TDownloader.vb b/SCrawler/TDownloader.vb index b0fffa8..f5f51aa 100644 --- a/SCrawler/TDownloader.vb +++ b/SCrawler/TDownloader.vb @@ -7,102 +7,206 @@ ' This program is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY Imports System.Threading -Imports EOptions = PersonalUtilities.Forms.Toolbars.MyProgress.EnableOptions +Imports PersonalUtilities.Forms.Toolbars +Imports EOptions = PersonalUtilities.Forms.Toolbars.IMyProgress.EnableOptions Imports SCrawler.API Imports SCrawler.API.Base Friend Class TDownloader : Implements IDisposable - Friend Event OnJobsChange(ByVal JobsCount As Integer) + Friend Event OnJobsChange(ByVal Site As Sites, ByVal JobsCount As Integer) Friend Event OnDownloadCountChange() Friend Event OnDownloading(ByVal Value As Boolean) - Private TokenSource As CancellationTokenSource - Private ReadOnly Items As List(Of IUserData) + Friend Event SendNotification(ByVal Message As String) Friend ReadOnly Property Downloaded As List(Of IUserData) Private ReadOnly NProv As IFormatProvider - Private _Working As Boolean = False - Friend ReadOnly Property Working As Boolean + Friend ReadOnly Property Working(Optional ByVal Site As Sites = Sites.Undefined) As Boolean Get - Return _Working + If Site = Sites.Instagram Then + Return JobInst.Working + Else + Return JobDefault.Working Or JobInst.Working + End If End Get End Property - Private DThread As Thread - Friend ReadOnly Property Count As Integer - Get - Return Items.Count - End Get - End Property - Friend Sub New() - Items = New List(Of IUserData) - Downloaded = New List(Of IUserData) - NProv = New ANumbers(ANumbers.Modes.USA) With { - .FormatMode = ANumbers.Formats.Number, - .GroupSize = 3, - .GroupSeparator = ANumbers.DefaultGroupSeparator, - .DecimalDigits = 0 - } - End Sub - Friend Sub [Start]() - If Not _Working AndAlso Count > 0 AndAlso Not If(DThread?.IsAlive, False) Then - DThread = New Thread(New ThreadStart(AddressOf StartDownloading)) - DThread.SetApartmentState(ApartmentState.MTA) - DThread.Start() - End If - End Sub - Private Sub StartDownloading() - Dim Token As CancellationToken - RaiseEvent OnDownloading(True) - Try - _Working = True + Friend Property InstagramSavedPostsDownloading As Boolean = False +#Region "Jobs" + Friend Structure Job + Friend Site As Sites + Private TokenSource As CancellationTokenSource + Private Token As CancellationToken + Private [Thread] As Thread + Private _Working As Boolean + Friend ReadOnly Items As List(Of IUserData) + Friend ReadOnly Property Count As Integer + Get + Return Items.Count + End Get + End Property + Friend ReadOnly Property Working As Boolean + Get + Return _Working OrElse If(Thread?.IsAlive, False) + End Get + End Property + Friend ReadOnly Progress As MyProgress + Friend Sub New(ByRef _Progress As MyProgress) + Progress = _Progress + Items = New List(Of IUserData) + End Sub + Public Shared Widening Operator CType(ByVal j As Job) As CancellationToken + Return j.Token + End Operator + Public Shared Widening Operator CType(ByVal j As Job) As Boolean + Return j.Working + End Operator + Public Shared Operator And(ByVal x As Job, ByVal y As Job) As Boolean + Return x.Working And y.Working + End Operator + Public Shared Operator And(ByVal x As Job, ByVal y As Boolean) As Boolean + Return x.Working And y + End Operator + Public Shared Operator And(ByVal x As Boolean, ByVal y As Job) As Boolean + Return x And y.Working + End Operator + Public Shared Operator Or(ByVal x As Job, ByVal y As Job) As Boolean + Return x.Working Or y.Working + End Operator + Public Shared Operator Or(ByVal x As Job, ByVal y As Boolean) As Boolean + Return x.Working Or y + End Operator + Public Shared Operator Or(ByVal x As Boolean, ByVal y As Job) As Boolean + Return x Or y.Working + End Operator + Public Shared Operator Not(ByVal j As Job) As Boolean + Return Not j.Working + End Operator + Friend Sub ThrowIfCancellationRequested() + Token.ThrowIfCancellationRequested() + End Sub + Friend ReadOnly Property IsCancellationRequested As Boolean + Get + Return Token.IsCancellationRequested + End Get + End Property + Friend ReadOnly Property IsInstagram As Boolean + Get + Return Site = Sites.Instagram + End Get + End Property + Friend Sub [Start](ByVal [ThreadStart] As ThreadStart) + Thread = New Thread(ThreadStart) With {.IsBackground = True} + Thread.SetApartmentState(ApartmentState.MTA) + Thread.Start() + End Sub + Friend Sub [Start]() TokenSource = New CancellationTokenSource Token = TokenSource.Token - MainProgress.TotalCount = 0 - MainProgress.CurrentCounter = 0 - Do While Count > 0 - Token.ThrowIfCancellationRequested() - UpdateJobsLabel() - DownloadData(Token) - Token.ThrowIfCancellationRequested() - Thread.Sleep(500) - Loop - MainProgress.InformationTemporary = "All data downloaded" - Catch oex As OperationCanceledException When Token.IsCancellationRequested - MainProgress.InformationTemporary = "Downloading canceled" - Catch ex As Exception - MainProgress.InformationTemporary = "Downloading error" - ErrorsDescriber.Execute(EDP.SendInLog, ex, "TDownloader.Start") - Finally + _Working = True + End Sub + Friend Sub [Stop]() + If Not TokenSource Is Nothing Then TokenSource.Cancel() + End Sub + Friend Sub Stopped() _Working = False TokenSource = Nothing - UpdateJobsLabel() - If Settings(Sites.Instagram).InstaHashUpdateRequired Then MyMainLOG = "Check your Instagram credentials" + Try + If Not Thread Is Nothing Then + If Thread.IsAlive Then Thread.Abort() + Thread = Nothing + End If + Catch ex As Exception + End Try + End Sub + End Structure + Private JobDefault As Job + Private JobInst As Job +#End Region + Friend Sub New() + Downloaded = New List(Of IUserData) + NProv = New ANumbers With {.FormatOptions = ANumbers.Options.GroupIntegral} + JobDefault = New Job(MainProgress) + JobInst = New Job(MainProgressInst) With {.Site = Sites.Instagram} + End Sub + Friend Sub [Start]() + If Not JobDefault.Working And JobDefault.Count > 0 Then JobDefault.Start(New ThreadStart(Sub() StartDownloading(JobDefault))) + If Not JobInst.Working And JobInst.Count > 0 And Not InstagramSavedPostsDownloading Then _ + JobInst.Start(New ThreadStart(Sub() StartDownloading(JobInst))) + End Sub + Private Sub StartDownloading(ByRef _Job As Job) + RaiseEvent OnDownloading(True) + Dim isInst As Boolean = _Job.IsInstagram + Dim pt As Func(Of String, String) = Function(ByVal t As String) As String + Dim _t$ = If(isInst, $"Instagram {Left(t, 1).ToLower}{Right(t, t.Length - 1)}", t) + RaiseEvent SendNotification(_t) + Return _t + End Function + Try + _Job.Start() + _Job.Progress.TotalCount = 0 + _Job.Progress.CurrentCounter = 0 + _Job.Progress.Enabled = True + Do While _Job.Count > 0 + _Job.ThrowIfCancellationRequested() + UpdateJobsLabel(_Job) + DownloadData(_Job, _Job) + _Job.ThrowIfCancellationRequested() + Thread.Sleep(500) + Loop + _Job.Progress.InformationTemporary = pt("All data downloaded") + Catch oex As OperationCanceledException When _Job.IsCancellationRequested + _Job.Progress.InformationTemporary = pt("Downloading canceled") + Catch ex As Exception + _Job.Progress.InformationTemporary = pt("Downloading error") + ErrorsDescriber.Execute(EDP.SendInLog, ex, "TDownloader.Start") + Finally + _Job.Stopped() + UpdateJobsLabel(_Job) + If _Job.Site = Sites.Instagram Then + Settings(Sites.Instagram).InstagramLastDownloadDate.Value = Now + If Settings(Sites.Instagram).InstaHashUpdateRequired Then MyMainLOG = "Check your Instagram credentials" + End If + _Job.Progress.Enabled(EOptions.ProgressBar) = False RaiseEvent OnDownloading(False) End Try End Sub Friend Sub [Stop]() - If _Working Then TokenSource.Cancel() + If JobDefault.Working Then JobDefault.Stop() + If JobInst.Working Then JobInst.Stop() End Sub - Private Sub UpdateJobsLabel() - RaiseEvent OnJobsChange(Count) + Private Overloads Sub UpdateJobsLabel() + UpdateJobsLabel(JobDefault) + UpdateJobsLabel(JobInst) End Sub - Private _CurrentDownloadingTasks As Integer = 0 - Private Sub DownloadData(ByVal Token As CancellationToken) + Private Overloads Sub UpdateJobsLabel(ByVal _Job As Job) + RaiseEvent OnJobsChange(_Job.Site, _Job.Count) + End Sub + Private _InstagramNextWNM As Instagram.UserData.WNM = Instagram.UserData.WNM.Notify + Private Sub DownloadData(ByRef _Job As Job, ByVal Token As CancellationToken) Try - If Items.Count > 0 Then + If _Job.Count > 0 Then Const nf As ANumbers.Formats = ANumbers.Formats.Number Dim t As New List(Of Task) Dim i% = -1 Dim j% = Settings.MaxUsersJobsCount - 1 + Dim limit% = IIf(_Job.Site = Sites.Instagram, 1, j) Dim Keys As New List(Of String) Dim h As Boolean = False Dim InstaReady As Boolean = Settings(Sites.Instagram).InstagramReadyForDownload - For Each _Item As IUserData In Items + For Each _Item As IUserData In _Job.Items If Not _Item.Disposed Then Keys.Add(_Item.LVIKey) If Not _Item.Site = Sites.Instagram Or InstaReady Then - If _Item.Site = Sites.Instagram Then h = True : Settings(Sites.Instagram).InstagramTooManyRequestsReadyForCatch = True - Token.ThrowIfCancellationRequested() + If _Item.Site = Sites.Instagram Then + h = True + With DirectCast(_Item, Instagram.UserData) + .WaitNotificationMode = _InstagramNextWNM + If Settings(Sites.Instagram).InstagramLastDownloadDate.Value < Now.AddMinutes(60) Then + .RequestsCount = Settings(Sites.Instagram).InstagramLastRequestsCount + End If + End With + End If + _Job.ThrowIfCancellationRequested() t.Add(Task.Run(Sub() _Item.DownloadData(Token))) i += 1 - If i >= j Then Exit For + If i >= limit Then Exit For End If End If Next @@ -112,38 +216,46 @@ Friend Class TDownloader : Implements IDisposable If .InstaHash.IsEmptyString Or .InstaHashUpdateRequired Then .GatherInstaHash() End With End If - _CurrentDownloadingTasks = t.Count - With MainProgress + With _Job.Progress .Enabled(EOptions.All) = True - .Information = $"Downloading {_CurrentDownloadingTasks.NumToString(nf, NProv)}/{Items.Count.NumToString(nf, NProv)} profiles' data" + .Information = IIf(_Job.IsInstagram, "Instagram d", "D") + .Information &= $"ownloading {t.Count.NumToString(nf, NProv)}/{_Job.Items.Count.NumToString(nf, NProv)} profiles' data" .InformationTemporary = .Information End With If t.Count > 0 Then Task.WaitAll(t.ToArray) Dim dcc As Boolean = False If Keys.Count > 0 Then For Each k$ In Keys - i = Items.FindIndex(Function(ii) ii.LVIKey = k) + i = _Job.Items.FindIndex(Function(ii) ii.LVIKey = k) If i >= 0 Then - With Items(i) + With _Job.Items(i) + If _Job.Site = Sites.Instagram Then + With DirectCast(.Self, Instagram.UserData) + _InstagramNextWNM = .WaitNotificationMode + If _InstagramNextWNM = Instagram.UserData.WNM.SkipTemp Or _InstagramNextWNM = Instagram.UserData.WNM.SkipCurrent Then _ + _InstagramNextWNM = Instagram.UserData.WNM.Notify + Settings(Sites.Instagram).InstagramLastRequestsCount.Value = .RequestsCount + End With + End If If Not .Disposed AndAlso Not .IsCollection AndAlso .DownloadedTotal(False) > 0 Then If Not Downloaded.Contains(.Self) Then Downloaded.Add(GetUserFromMainCollection(.Self)) dcc = True End If End With - Items.RemoveAt(i) + _Job.Items.RemoveAt(i) End If Next End If Keys.Clear() - Items.RemoveAll(Function(ii) ii.Disposed) + _Job.Items.RemoveAll(Function(ii) ii.Disposed) If dcc Then Downloaded.RemoveAll(Function(u) u Is Nothing) If dcc And Downloaded.Count > 0 Then RaiseEvent OnDownloadCountChange() t.Clear() End If End If Catch aoex As ArgumentOutOfRangeException - ErrorsDescriber.Execute(EDP.SendInLog, aoex, $"TDownloader.DownloadData: index out of range ({Count})") - Catch oex As OperationCanceledException When Token.IsCancellationRequested + ErrorsDescriber.Execute(EDP.SendInLog, aoex, $"TDownloader.DownloadData: index out of range ({_Job.Count})") + Catch oex As OperationCanceledException When _Job.IsCancellationRequested Catch ex As Exception ErrorsDescriber.Execute(EDP.SendInLog, ex, "TDownloader.DownloadData") Finally @@ -151,7 +263,7 @@ Friend Class TDownloader : Implements IDisposable Task.WaitAll(Task.Run(Sub() While Settings.UserListUpdateRequired : Settings.UpdateUsersList() : End While End Sub)) - MainProgress.Enabled(EOptions.ProgressBar) = False + If _Job.Site = Sites.Instagram Then Settings(Sites.Instagram).InstagramLastDownloadDate.Value = Now End Try End Sub Private Function GetUserFromMainCollection(ByVal User As IUserData) As IUserData @@ -178,50 +290,37 @@ Friend Class TDownloader : Implements IDisposable End If Return Nothing End Function -#Region "Saved posts downloading" - Friend ReadOnly Property SavedPostsDownloading As Boolean - Get - Return If(_SavedPostsThread?.IsAlive, False) - End Get - End Property - Private _SavedPostsThread As Thread - Friend Sub DownloadSavedPostsStart(ByVal Toolbar As StatusStrip, ByVal PR As ToolStripProgressBar) - If Not SavedPostsDownloading Then - If Settings(Sites.Reddit).SavedPostsUserName.IsEmptyString Then - MsgBoxE($"Username of saved posts not set{vbNewLine}Operation canceled", MsgBoxStyle.Critical) + Private Sub AddItem(ByVal Item As IUserData, ByVal _UpdateJobsLabel As Boolean) + If Not Contains(Item) Then + If Item.IsCollection Then + Item.DownloadData(Nothing) + ElseIf Item.Site = Sites.Instagram Then + JobInst.Items.Add(Item) + If _UpdateJobsLabel Then UpdateJobsLabel(JobInst) Else - _SavedPostsThread = New Thread(New ThreadStart(Sub() Reddit.ProfileSaved.Download(Toolbar, PR))) - _SavedPostsThread.SetApartmentState(ApartmentState.MTA) - _SavedPostsThread.Start() + JobDefault.Items.Add(Item) + If _UpdateJobsLabel Then UpdateJobsLabel(JobDefault) End If - Else - MsgBoxE("Saved posts are already downloading", MsgBoxStyle.Exclamation) End If End Sub - Friend Sub DownloadSavedPostsStop() - Try - If SavedPostsDownloading Then _SavedPostsThread.Abort() - Catch ex As Exception - End Try - End Sub -#End Region Friend Sub Add(ByVal Item As IUserData) - If Not Items.Contains(Item) Then - If Item.IsCollection Then Item.DownloadData(Nothing) Else Items.Add(Item) - UpdateJobsLabel() - End If - If Items.Count > 0 Then Start() + AddItem(Item, True) + If JobDefault.Count > 0 Or JobInst.Count > 0 Then Start() End Sub Friend Sub AddRange(ByVal _Items As IEnumerable(Of IUserData)) If _Items.ListExists Then - For i% = 0 To _Items.Count - 1 - 'If i = 5 Then UpdateJobsLabel() : Start() - If _Items(i).IsCollection Then _Items(i).DownloadData(Nothing) Else Items.Add(_Items(i)) - Next + For i% = 0 To _Items.Count - 1 : AddItem(_Items(i), False) : Next UpdateJobsLabel() End If - If Items.Count > 0 Then Start() + If JobDefault.Count > 0 Or JobInst.Count > 0 Then Start() End Sub + Private Function Contains(ByVal _Item As IUserData) + If _Item.Site = Sites.Instagram Then + Return JobInst.Items.Contains(_Item) + Else + Return JobDefault.Items.Contains(_Item) + End If + End Function Friend Sub UserRemove(ByVal _Item As IUserData) If Downloaded.Count > 0 AndAlso Downloaded.Contains(_Item) Then Downloaded.Remove(_Item) : RaiseEvent OnDownloadCountChange() End Sub @@ -231,7 +330,8 @@ Friend Class TDownloader : Implements IDisposable If Not disposedValue Then If disposing Then [Stop]() - Items.Clear() + JobDefault.Items.Clear() + JobInst.Items.Clear() Downloaded.Clear() End If disposedValue = True