diff --git a/Changelog.md b/Changelog.md index eacaf26..e19df0d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,13 @@ +# 3.0.0.2 + +- Added + - **LPSG** site plugin + - **XVIDEOS** site plugin +- Updated + - Plugin provider +- Fixed + - Minor bugs + # 3.0.0.1 - Added diff --git a/Plugins.md b/Plugins.md index 4649f13..fc657aa 100644 --- a/Plugins.md +++ b/Plugins.md @@ -1 +1,3 @@ -List of available plugins \ No newline at end of file +List of available plugins: +- LPSG +- XVIDEOS \ No newline at end of file diff --git a/README.md b/README.md index 22f4757..a72b590 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,8 @@ Do you like this program? Consider adding to my coffee fund by making a donation - RedGifs - Imgur - Gfycat +- LPSG +- XVIDEOS - [Other sites](Plugins.md) # How does it works: diff --git a/SCrawler.Plugin.LPSG/.editorconfig b/SCrawler.Plugin.LPSG/.editorconfig new file mode 100644 index 0000000..ea98747 --- /dev/null +++ b/SCrawler.Plugin.LPSG/.editorconfig @@ -0,0 +1,3 @@ +[*.vb] +# Modifier preferences +file_header_template = Copyright (C) 2022 Andy\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program. If not, see \ No newline at end of file diff --git a/SCrawler.Plugin.LPSG/Content/Icons/Icon32.ico b/SCrawler.Plugin.LPSG/Content/Icons/Icon32.ico new file mode 100644 index 0000000..af8c0b6 Binary files /dev/null and b/SCrawler.Plugin.LPSG/Content/Icons/Icon32.ico differ diff --git a/SCrawler.Plugin.LPSG/Content/Pictures/IconPic_32.png b/SCrawler.Plugin.LPSG/Content/Pictures/IconPic_32.png new file mode 100644 index 0000000..1393992 Binary files /dev/null and b/SCrawler.Plugin.LPSG/Content/Pictures/IconPic_32.png differ diff --git a/SCrawler.Plugin.LPSG/Declarations.vb b/SCrawler.Plugin.LPSG/Declarations.vb new file mode 100644 index 0000000..98cf79b --- /dev/null +++ b/SCrawler.Plugin.LPSG/Declarations.vb @@ -0,0 +1,26 @@ +' 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.RegularExpressions +Friend Module Declarations + Friend ReadOnly Property PhotoRegEx As RParams = RParams.DM("(https://www.lpsg.com/attachments)(.+?)(?="")", 0, RegexReturn.List) + Friend ReadOnly Property NextPageRegex As RParams = RParams.DMS(" +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + diff --git a/SCrawler.Plugin.LPSG/My Project/Application.myapp b/SCrawler.Plugin.LPSG/My Project/Application.myapp new file mode 100644 index 0000000..758895d --- /dev/null +++ b/SCrawler.Plugin.LPSG/My Project/Application.myapp @@ -0,0 +1,10 @@ + + + false + false + 0 + true + 0 + 1 + true + diff --git a/SCrawler.Plugin.LPSG/My Project/AssemblyInfo.vb b/SCrawler.Plugin.LPSG/My Project/AssemblyInfo.vb new file mode 100644 index 0000000..e3203da --- /dev/null +++ b/SCrawler.Plugin.LPSG/My Project/AssemblyInfo.vb @@ -0,0 +1,37 @@ +Imports System.Resources +Imports System +Imports System.Reflection +Imports System.Runtime.InteropServices + +' General Information about an assembly is controlled through the following +' set of attributes. Change these attribute values to modify the information +' associated with an assembly. + +' Review the values of the assembly attributes + + + + + + + + + + +'The following GUID is for the ID of the typelib if this project is exposed to COM + + +' Version information for an assembly consists of the following four values: +' +' Major Version +' Minor Version +' Build Number +' Revision +' +' You can specify all the values or you can default the Build and Revision Numbers +' by using the '*' as shown below: +' + + + + diff --git a/SCrawler.Plugin.LPSG/My Project/Resources.Designer.vb b/SCrawler.Plugin.LPSG/My Project/Resources.Designer.vb new file mode 100644 index 0000000..f5f0db7 --- /dev/null +++ b/SCrawler.Plugin.LPSG/My Project/Resources.Designer.vb @@ -0,0 +1,83 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + +Imports System + +Namespace My.Resources + + 'This class was auto-generated by the StronglyTypedResourceBuilder + 'class via a tool like ResGen or Visual Studio. + 'To add or remove a member, edit your .ResX file then rerun ResGen + 'with the /str option, or rebuild your VS project. + ''' + ''' A strongly-typed resource class, for looking up localized strings, etc. + ''' + _ + Friend Module Resources + + Private resourceMan As Global.System.Resources.ResourceManager + + Private resourceCulture As Global.System.Globalization.CultureInfo + + ''' + ''' Returns the cached ResourceManager instance used by this class. + ''' + _ + Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager + Get + If Object.ReferenceEquals(resourceMan, Nothing) Then + Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("LPSG.Resources", GetType(Resources).Assembly) + resourceMan = temp + End If + Return resourceMan + End Get + End Property + + ''' + ''' Overrides the current thread's CurrentUICulture property for all + ''' resource lookups using this strongly typed resource class. + ''' + _ + Friend Property Culture() As Global.System.Globalization.CultureInfo + Get + Return resourceCulture + End Get + Set + resourceCulture = value + End Set + End Property + + ''' + ''' Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + ''' + Friend ReadOnly Property Icon32() As System.Drawing.Icon + Get + Dim obj As Object = ResourceManager.GetObject("Icon32", resourceCulture) + Return CType(obj,System.Drawing.Icon) + End Get + End Property + + ''' + ''' Looks up a localized resource of type System.Drawing.Bitmap. + ''' + Friend ReadOnly Property IconPic_32() As System.Drawing.Bitmap + Get + Dim obj As Object = ResourceManager.GetObject("IconPic_32", resourceCulture) + Return CType(obj,System.Drawing.Bitmap) + End Get + End Property + End Module +End Namespace diff --git a/SCrawler.Plugin.LPSG/My Project/Resources.resx b/SCrawler.Plugin.LPSG/My Project/Resources.resx new file mode 100644 index 0000000..5d2d7d8 --- /dev/null +++ b/SCrawler.Plugin.LPSG/My Project/Resources.resx @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + ..\Content\Icons\Icon32.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Content\Pictures\IconPic_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.Plugin.LPSG/My Project/Settings.Designer.vb b/SCrawler.Plugin.LPSG/My Project/Settings.Designer.vb new file mode 100644 index 0000000..c0e6172 --- /dev/null +++ b/SCrawler.Plugin.LPSG/My Project/Settings.Designer.vb @@ -0,0 +1,73 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My + + _ + Partial Friend NotInheritable Class MySettings + Inherits Global.System.Configuration.ApplicationSettingsBase + + Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings) + +#Region "My.Settings Auto-Save Functionality" +#If _MyType = "WindowsForms" Then + Private Shared addedHandler As Boolean + + Private Shared addedHandlerLockObject As New Object + + _ + Private Shared Sub AutoSaveSettings(sender As Global.System.Object, e As Global.System.EventArgs) + If My.Application.SaveMySettingsOnExit Then + My.Settings.Save() + End If + End Sub +#End If +#End Region + + Public Shared ReadOnly Property [Default]() As MySettings + Get + +#If _MyType = "WindowsForms" Then + If Not addedHandler Then + SyncLock addedHandlerLockObject + If Not addedHandler Then + AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings + addedHandler = True + End If + End SyncLock + End If +#End If + Return defaultInstance + End Get + End Property + End Class +End Namespace + +Namespace My + + _ + Friend Module MySettingsProperty + + _ + Friend ReadOnly Property Settings() As Global.LPSG.My.MySettings + Get + Return Global.LPSG.My.MySettings.Default + End Get + End Property + End Module +End Namespace diff --git a/SCrawler.Plugin.LPSG/My Project/Settings.settings b/SCrawler.Plugin.LPSG/My Project/Settings.settings new file mode 100644 index 0000000..85b890b --- /dev/null +++ b/SCrawler.Plugin.LPSG/My Project/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/SCrawler.Plugin.LPSG/SCrawler.Plugin.LPSG.vbproj b/SCrawler.Plugin.LPSG/SCrawler.Plugin.LPSG.vbproj new file mode 100644 index 0000000..32611ab --- /dev/null +++ b/SCrawler.Plugin.LPSG/SCrawler.Plugin.LPSG.vbproj @@ -0,0 +1,166 @@ + + + + + Debug + AnyCPU + {22A130B2-DDF4-4FB5-BA38-E5DB4CF1B8A2} + Library + LPSG + SCrawler.Plugin.LPSG + 512 + Windows + v4.6.1 + true + + + true + full + true + true + bin\Debug\ + + + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + pdbonly + false + true + true + bin\Release\ + + + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + On + + + Binary + + + Off + + + On + + + true + true + true + bin\x64\Debug\ + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + full + x64 + + + true + bin\x64\Release\ + true + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + pdbonly + x64 + + + true + true + true + bin\x86\Debug\ + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + full + x86 + + + true + bin\x86\Release\ + true + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + pdbonly + x86 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + Application.myapp + True + + + True + True + Resources.resx + + + True + Settings.settings + True + + + + + + + VbMyResourcesResXFileCodeGenerator + Resources.Designer.vb + My.Resources + Designer + + + + + + MyApplicationCodeGenerator + Application.Designer.vb + + + SettingsSingleFileGenerator + My + Settings.Designer.vb + + + + + {8405896b-2685-4916-bc93-1fb514c323a9} + PersonalUtilities + + + {d4650f6b-5a54-44b6-999b-6c675b7116b1} + SCrawler.PluginProvider + + + + + + + + + + \ No newline at end of file diff --git a/SCrawler.Plugin.LPSG/SiteSettings.vb b/SCrawler.Plugin.LPSG/SiteSettings.vb new file mode 100644 index 0000000..3e721c4 --- /dev/null +++ b/SCrawler.Plugin.LPSG/SiteSettings.vb @@ -0,0 +1,100 @@ +' 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.Drawing +Imports PersonalUtilities.Functions.RegularExpressions + +Public Class SiteSettings : Implements ISiteSettings + Public ReadOnly Property Icon As Icon Implements ISiteSettings.Icon + Get + Return My.Resources.Icon32 + End Get + End Property + Public ReadOnly Property Image As Image Implements ISiteSettings.Image + Get + Return My.Resources.IconPic_32 + End Get + End Property + Public ReadOnly Property Site As String = "LPSG" Implements ISiteSettings.Site + Public Property Logger As ILogProvider Implements ISiteSettings.Logger + Friend ReadOnly Property Responser As Response + Public Sub New() + Responser = New Response($"Settings\Responser_LPSG.xml") + With Responser + If .File.Exists Then + .LoadSettings() + Else + .CookiesDomain = "www.lpsg.com" + .Cookies = New CookieKeeper("www.lpsg.com") + End If + End With + End Sub + Public Sub BeginInit() Implements ISiteSettings.BeginInit + End Sub + Public Sub EndInit() Implements ISiteSettings.EndInit + End Sub + Public Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider Implements ISiteSettings.GetInstance + Return New UserData + End Function + Public Sub Load(ByVal XMLValues As IEnumerable(Of KeyValuePair(Of String, String))) Implements ISiteSettings.Load + End Sub +#Region "Download functions" + Public Sub DownloadStarted(ByVal What As ISiteSettings.Download) Implements ISiteSettings.DownloadStarted + End Sub + Public Sub BeforeStartDownload(ByVal User As Object, ByVal What As ISiteSettings.Download) Implements ISiteSettings.BeforeStartDownload + End Sub + Public Sub AfterDownload(ByVal User As Object, ByVal What As ISiteSettings.Download) Implements ISiteSettings.AfterDownload + End Sub + Public Sub DownloadDone(ByVal What As ISiteSettings.Download) Implements ISiteSettings.DownloadDone + End Sub +#End Region +#Region "Update" + Public Sub BeginUpdate() Implements ISiteSettings.BeginUpdate + End Sub + Public Sub EndUpdate() Implements ISiteSettings.EndUpdate + End Sub + Public Sub Update() Implements ISiteSettings.Update + Responser.SaveSettings() + End Sub +#End Region + Public Sub Reset() Implements ISiteSettings.Reset + End Sub + Public Sub OpenSettingsForm() Implements ISiteSettings.OpenSettingsForm + End Sub + Public Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean) Implements ISiteSettings.UserOptions + Options = Nothing + End Sub + Public Function GetUserUrl(ByVal UserName As String, ByVal Channel As Boolean) As String Implements ISiteSettings.GetUserUrl + Return $"https://www.lpsg.com/threads/{UserName}/" + End Function + Private ReadOnly UserRegEx As RParams = RParams.DMS(".+?lpsg.com/threads/([^/]+)", 1) + Public Function IsMyUser(ByVal UserURL As String) As ExchangeOptions Implements ISiteSettings.IsMyUser + Try + Dim r$ = RegexReplace(UserURL, UserRegEx) + If Not r.IsEmptyString Then + Return New ExchangeOptions(Site, r) + Else + Return Nothing + End If + Catch ex As Exception + Return Nothing + End Try + End Function + Public Function IsMyImageVideo(ByVal URL As String) As ExchangeOptions Implements ISiteSettings.IsMyImageVideo + Return Nothing + End Function + Public Function GetSpecialData(ByVal URL As String, ByVal Path As String, ByVal AskForPath As Boolean) As IEnumerable(Of PluginUserMedia) Implements ISiteSettings.GetSpecialData + Return Nothing + End Function + Public Function Available(ByVal What As ISiteSettings.Download) As Boolean Implements ISiteSettings.Available + Return True + End Function + Public Function ReadyToDownload(ByVal What As ISiteSettings.Download) As Boolean Implements ISiteSettings.ReadyToDownload + Return True + End Function +End Class \ No newline at end of file diff --git a/SCrawler.Plugin.LPSG/UserData.vb b/SCrawler.Plugin.LPSG/UserData.vb new file mode 100644 index 0000000..53889ce --- /dev/null +++ b/SCrawler.Plugin.LPSG/UserData.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 PersonalUtilities.Functions.RegularExpressions +Public Class UserData : Implements IPluginContentProvider +#Region "XML names" + Private Const Name_LatestPage As String = "LatestPage" +#End Region +#Region "Interface declarations" + Public Event ProgressChanged(ByVal Count As Integer) Implements IPluginContentProvider.ProgressChanged + Public Event TotalCountChanged(ByVal Count As Integer) Implements IPluginContentProvider.TotalCountChanged + Public Property Thrower As IThrower Implements IPluginContentProvider.Thrower + Public Property LogProvider As ILogProvider Implements IPluginContentProvider.LogProvider + Public Property ESettings As ISiteSettings Implements IPluginContentProvider.Settings + Private ReadOnly Property Settings As SiteSettings + Get + Return DirectCast(ESettings, SiteSettings) + End Get + End Property + Public Property Name As String Implements IPluginContentProvider.Name + Public Property ID As String Implements IPluginContentProvider.ID + Public Property ParseUserMediaOnly As Boolean Implements IPluginContentProvider.ParseUserMediaOnly + Public Property UserDescription As String Implements IPluginContentProvider.UserDescription + Public Property ExistingContentList As List(Of PluginUserMedia) Implements IPluginContentProvider.ExistingContentList + Public Property TempPostsList As List(Of String) Implements IPluginContentProvider.TempPostsList + Public Property TempMediaList As List(Of PluginUserMedia) Implements IPluginContentProvider.TempMediaList + Public Property UserExists As Boolean Implements IPluginContentProvider.UserExists + Public Property UserSuspended As Boolean Implements IPluginContentProvider.UserSuspended + Public Property IsSavedPosts As Boolean Implements IPluginContentProvider.IsSavedPosts + Public Property SeparateVideoFolder As Boolean Implements IPluginContentProvider.SeparateVideoFolder + Public Property DataPath As String Implements IPluginContentProvider.DataPath + Public Property PostsNumberLimit As Integer? Implements IPluginContentProvider.PostsNumberLimit + Public Property PostsDateLimit As Date? Implements IPluginContentProvider.PostsDateLimit +#End Region +#Region "Interface exchange options" + Public Sub ExchangeOptionsSet(ByVal Obj As Object) Implements IPluginContentProvider.ExchangeOptionsSet + End Sub + Public Function ExchangeOptionsGet() As Object Implements IPluginContentProvider.ExchangeOptionsGet + Return Nothing + End Function +#End Region +#Region "Interface XML" + Public Sub XmlFieldsSet(ByVal Fields As List(Of KeyValuePair(Of String, String))) Implements IPluginContentProvider.XmlFieldsSet + If Fields.ListExists Then + For Each f As KeyValuePair(Of String, String) In Fields + If f.Key = Name_LatestPage Then LatestPage = f.Value + Next + End If + End Sub + Public Function XmlFieldsGet() As List(Of KeyValuePair(Of String, String)) Implements IPluginContentProvider.XmlFieldsGet + Return New List(Of KeyValuePair(Of String, String)) From {New KeyValuePair(Of String, String)(Name_LatestPage, LatestPage)} + End Function +#End Region + Private Property LatestPage As String = String.Empty + Private Property Responser As Response = Nothing + Public Sub GetMedia() Implements IPluginContentProvider.GetMedia + Try + If Not Responser Is Nothing Then Responser.Dispose() + Responser = New Response + With Responser : .Copy(Settings.Responser) : .Error = EDP.ThrowException : End With + + Dim l As List(Of String) = Nothing + Dim NextPage$ = String.Empty + Dim r$ + Dim _LPage As Func(Of String) = Function() If(LatestPage.IsEmptyString, String.Empty, $"page-{LatestPage}") + + Do + r = Responser.GetResponse($"https://www.lpsg.com/threads/{Name}/{_LPage.Invoke}") + UserExists = True + UserSuspended = False + Thrower.ThrowAny() + If Not r.IsEmptyString Then + NextPage = RegexReplace(r, NextPageRegex) + l.ListAddList(RegexReplace(r, PhotoRegEx), LAP.NotContainsOnly) + If NextPage = LatestPage Or NextPage.IsEmptyString Then Exit Do Else LatestPage = NextPage + Else + Exit Do + End If + Loop + + If l.ListExists Then + Dim f As SFile + For Each u$ In l + If Not IsEmptyString(RegexReplace(u, FileExistsRegEx)) Then + f = CStr(RegexReplace(u, FileRegEx)) + f.Path = DataPath.CSFilePSN + f.Separator = "\" + TempMediaList.Add(New PluginUserMedia With {.ContentType = PluginUserMedia.Types.Picture, .URL = u, .File = f}) + End If + Next + If TempMediaList.ListExists And ExistingContentList.ListExists Then _ + TempMediaList.RemoveAll(Function(m) ExistingContentList.Exists(Function(mm) mm.URL = m.URL)) + End If + Catch oex As OperationCanceledException + Catch dex As ObjectDisposedException + Catch ex As Exception + LogProvider.Add(ex, "[LPSG.UserData.GetMedia]") + End Try + End Sub + Public Sub Download() Implements IPluginContentProvider.Download + Try + With Responser : .UseWebClient = True : .UseWebClientCookies = True : End With + If TempMediaList.ListExists Then + Dim m As PluginUserMedia + Dim eweb As ErrorsDescriber = EDP.ThrowException + RaiseEvent TotalCountChanged(TempMediaList.Count) + For i% = 0 To TempMediaList.Count - 1 + Thrower.ThrowAny() + m = TempMediaList(i) + m.DownloadState = PluginUserMedia.States.Tried + Try + If Not m.URL.IsEmptyString And Not m.File.IsEmptyString Then + Responser.DownloadFile(m.URL, m.File, eweb) + m.DownloadState = PluginUserMedia.States.Downloaded + Else + m.DownloadState = PluginUserMedia.States.Skipped + End If + Catch ex As Exception + End Try + RaiseEvent ProgressChanged(1) + TempMediaList(i) = m + Next + End If + Catch oex As OperationCanceledException + Catch dex As ObjectDisposedException + Catch ex As Exception + LogProvider.Add(ex, "[LPSG.UserData.Download]") + End Try + End Sub +#Region "IDisposable Support" + Private disposedValue As Boolean = False + Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean) + If Not disposedValue Then + If disposing Then + If Not Responser Is Nothing Then Responser.Dispose() + If ExistingContentList.ListExists Then ExistingContentList.Clear() + If TempPostsList.ListExists Then TempPostsList.Clear() + If TempMediaList.ListExists Then TempMediaList.Clear() + End If + disposedValue = True + End If + End Sub + Protected Overrides Sub Finalize() + Dispose(False) + MyBase.Finalize() + End Sub + Public Overloads Sub Dispose() Implements IDisposable.Dispose + Dispose(True) + GC.SuppressFinalize(Me) + End Sub +#End Region +End Class \ No newline at end of file diff --git a/SCrawler.Plugin.XVIDEOS/.editorconfig b/SCrawler.Plugin.XVIDEOS/.editorconfig new file mode 100644 index 0000000..ea98747 --- /dev/null +++ b/SCrawler.Plugin.XVIDEOS/.editorconfig @@ -0,0 +1,3 @@ +[*.vb] +# Modifier preferences +file_header_template = Copyright (C) 2022 Andy\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program. If not, see \ No newline at end of file diff --git a/SCrawler.Plugin.XVIDEOS/Content/Icons/Icon32.ico b/SCrawler.Plugin.XVIDEOS/Content/Icons/Icon32.ico new file mode 100644 index 0000000..f968966 Binary files /dev/null and b/SCrawler.Plugin.XVIDEOS/Content/Icons/Icon32.ico differ diff --git a/SCrawler.Plugin.XVIDEOS/Content/Pictures/IconPic32.png b/SCrawler.Plugin.XVIDEOS/Content/Pictures/IconPic32.png new file mode 100644 index 0000000..90330be Binary files /dev/null and b/SCrawler.Plugin.XVIDEOS/Content/Pictures/IconPic32.png differ diff --git a/SCrawler.Plugin.XVIDEOS/Declarations.vb b/SCrawler.Plugin.XVIDEOS/Declarations.vb new file mode 100644 index 0000000..f8fb965 --- /dev/null +++ b/SCrawler.Plugin.XVIDEOS/Declarations.vb @@ -0,0 +1,16 @@ +' 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.RegularExpressions +Friend Module Declarations + Friend ReadOnly Property M3U8Regex As RParams = RParams.DM("http.+?.m3u8.*?(?=')", 0) + Friend ReadOnly Property VideoTitleRegex As RParams = RParams.DMS("html5player.setVideoTitle\('(.+)(?='\);)", 1) + Friend ReadOnly Property VideoID As RParams = RParams.DMS(".*?www.xvideos.com/(video\d+).*", 1) + Friend ReadOnly Property M3U8Reparse As RParams = RParams.DM("NAME=""(\d+).*?""[\r\n]*?(.+)(?=(|[\r\n]+?))", 0, RegexReturn.List) + Friend ReadOnly Property M3U8Appender As RParams = RParams.DM("(.+)(?=/.+?\.m3u8.*?)", 0) +End Module \ No newline at end of file diff --git a/SCrawler.Plugin.XVIDEOS/M3U8.vb b/SCrawler.Plugin.XVIDEOS/M3U8.vb new file mode 100644 index 0000000..25a8ea6 --- /dev/null +++ b/SCrawler.Plugin.XVIDEOS/M3U8.vb @@ -0,0 +1,68 @@ +' 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.Net +Imports PersonalUtilities.Tools.WEB +Friend NotInheritable Class M3U8 + Private Sub New() + End Sub + Private Shared Function Save(ByVal URLs As List(Of String), ByVal ffmpegFile As SFile, ByVal f As SFile, ByRef Logger As ILogProvider) As SFile + Dim CachePath As SFile = Nothing + Try + If URLs.ListExists Then + Dim ConcatFile As SFile = f + If ConcatFile.Name.IsEmptyString Then ConcatFile.Name = "PlayListFile" + 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 With {.Format = ANumbers.Formats.General}) + ConcatFile = SFile.Indexed_IndexFile(ConcatFile,, p, EDP.ReturnValue) + Dim i% + Dim eFiles As New List(Of SFile) + Dim dFile As SFile = CachePath + dFile.Extension = "ts" + Using w As New WebClient + For i = 0 To URLs.Count - 1 + dFile.Name = $"ConPart_{i}" + w.DownloadFile(URLs(i), dFile) + eFiles.Add(dFile) + Next + End Using + f = FFMPEG.ConcatenateFiles(eFiles, ffmpegFile, ConcatFile, p, EDP.ThrowException) + eFiles.Clear() + Return f + End If + End If + Return Nothing + Catch ex As Exception + Logger.Add(ex, "[M3U8.Save]") + Return Nothing + Finally + CachePath.Delete(SFO.Path, SFODelete.None, EDP.None) + End Try + End Function + Friend Shared Function Download(ByVal URL As String, ByVal Appender As String, ByVal ffmpegFile As SFile, ByVal f As SFile, + ByRef Logger As ILogProvider) As SFile + Try + If Not URL.IsEmptyString Then + Using w As New WebClient + Dim r$ = w.DownloadString(URL) + If Not r.IsEmptyString Then + Dim l As List(Of String) = ListAddList(Nothing, r.StringFormatLines.StringToList(Of String)(vbNewLine).ListWithRemove(Function(v) v.Trim.StartsWith("#")), + New ListAddParams With {.Converter = Function(Input) $"{Appender}/{Input.ToString.Trim}"}) + If l.ListExists Then Return Save(l, ffmpegFile, f, Logger) + End If + End Using + End If + Return Nothing + Catch ex As Exception + Logger.Add(ex, "[M3U8.Download]") + Return Nothing + End Try + End Function +End Class \ No newline at end of file diff --git a/SCrawler.Plugin.XVIDEOS/My Project/Application.Designer.vb b/SCrawler.Plugin.XVIDEOS/My Project/Application.Designer.vb new file mode 100644 index 0000000..88dd01c --- /dev/null +++ b/SCrawler.Plugin.XVIDEOS/My Project/Application.Designer.vb @@ -0,0 +1,13 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + diff --git a/SCrawler.Plugin.XVIDEOS/My Project/Application.myapp b/SCrawler.Plugin.XVIDEOS/My Project/Application.myapp new file mode 100644 index 0000000..758895d --- /dev/null +++ b/SCrawler.Plugin.XVIDEOS/My Project/Application.myapp @@ -0,0 +1,10 @@ + + + false + false + 0 + true + 0 + 1 + true + diff --git a/SCrawler.Plugin.XVIDEOS/My Project/AssemblyInfo.vb b/SCrawler.Plugin.XVIDEOS/My Project/AssemblyInfo.vb new file mode 100644 index 0000000..29e8a9f --- /dev/null +++ b/SCrawler.Plugin.XVIDEOS/My Project/AssemblyInfo.vb @@ -0,0 +1,37 @@ +Imports System.Resources +Imports System +Imports System.Reflection +Imports System.Runtime.InteropServices + +' General Information about an assembly is controlled through the following +' set of attributes. Change these attribute values to modify the information +' associated with an assembly. + +' Review the values of the assembly attributes + + + + + + + + + + +'The following GUID is for the ID of the typelib if this project is exposed to COM + + +' Version information for an assembly consists of the following four values: +' +' Major Version +' Minor Version +' Build Number +' Revision +' +' You can specify all the values or you can default the Build and Revision Numbers +' by using the '*' as shown below: +' + + + + diff --git a/SCrawler.Plugin.XVIDEOS/My Project/Resources.Designer.vb b/SCrawler.Plugin.XVIDEOS/My Project/Resources.Designer.vb new file mode 100644 index 0000000..61d56b5 --- /dev/null +++ b/SCrawler.Plugin.XVIDEOS/My Project/Resources.Designer.vb @@ -0,0 +1,83 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + +Imports System + +Namespace My.Resources + + 'This class was auto-generated by the StronglyTypedResourceBuilder + 'class via a tool like ResGen or Visual Studio. + 'To add or remove a member, edit your .ResX file then rerun ResGen + 'with the /str option, or rebuild your VS project. + ''' + ''' A strongly-typed resource class, for looking up localized strings, etc. + ''' + _ + Friend Module Resources + + Private resourceMan As Global.System.Resources.ResourceManager + + Private resourceCulture As Global.System.Globalization.CultureInfo + + ''' + ''' Returns the cached ResourceManager instance used by this class. + ''' + _ + Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager + Get + If Object.ReferenceEquals(resourceMan, Nothing) Then + Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("XVIDEOS.Resources", GetType(Resources).Assembly) + resourceMan = temp + End If + Return resourceMan + End Get + End Property + + ''' + ''' Overrides the current thread's CurrentUICulture property for all + ''' resource lookups using this strongly typed resource class. + ''' + _ + Friend Property Culture() As Global.System.Globalization.CultureInfo + Get + Return resourceCulture + End Get + Set + resourceCulture = value + End Set + End Property + + ''' + ''' Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + ''' + Friend ReadOnly Property Icon32() As System.Drawing.Icon + Get + Dim obj As Object = ResourceManager.GetObject("Icon32", resourceCulture) + Return CType(obj,System.Drawing.Icon) + End Get + End Property + + ''' + ''' Looks up a localized resource of type System.Drawing.Bitmap. + ''' + Friend ReadOnly Property IconPic32() As System.Drawing.Bitmap + Get + Dim obj As Object = ResourceManager.GetObject("IconPic32", resourceCulture) + Return CType(obj,System.Drawing.Bitmap) + End Get + End Property + End Module +End Namespace diff --git a/SCrawler.Plugin.XVIDEOS/My Project/Resources.resx b/SCrawler.Plugin.XVIDEOS/My Project/Resources.resx new file mode 100644 index 0000000..e341d57 --- /dev/null +++ b/SCrawler.Plugin.XVIDEOS/My Project/Resources.resx @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + ..\Content\Icons\Icon32.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Content\Pictures\IconPic32.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.Plugin.XVIDEOS/My Project/Settings.Designer.vb b/SCrawler.Plugin.XVIDEOS/My Project/Settings.Designer.vb new file mode 100644 index 0000000..9129ea0 --- /dev/null +++ b/SCrawler.Plugin.XVIDEOS/My Project/Settings.Designer.vb @@ -0,0 +1,73 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My + + _ + Partial Friend NotInheritable Class MySettings + Inherits Global.System.Configuration.ApplicationSettingsBase + + Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings) + +#Region "My.Settings Auto-Save Functionality" +#If _MyType = "WindowsForms" Then + Private Shared addedHandler As Boolean + + Private Shared addedHandlerLockObject As New Object + + _ + Private Shared Sub AutoSaveSettings(sender As Global.System.Object, e As Global.System.EventArgs) + If My.Application.SaveMySettingsOnExit Then + My.Settings.Save() + End If + End Sub +#End If +#End Region + + Public Shared ReadOnly Property [Default]() As MySettings + Get + +#If _MyType = "WindowsForms" Then + If Not addedHandler Then + SyncLock addedHandlerLockObject + If Not addedHandler Then + AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings + addedHandler = True + End If + End SyncLock + End If +#End If + Return defaultInstance + End Get + End Property + End Class +End Namespace + +Namespace My + + _ + Friend Module MySettingsProperty + + _ + Friend ReadOnly Property Settings() As Global.XVIDEOS.My.MySettings + Get + Return Global.XVIDEOS.My.MySettings.Default + End Get + End Property + End Module +End Namespace diff --git a/SCrawler.Plugin.XVIDEOS/My Project/Settings.settings b/SCrawler.Plugin.XVIDEOS/My Project/Settings.settings new file mode 100644 index 0000000..85b890b --- /dev/null +++ b/SCrawler.Plugin.XVIDEOS/My Project/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/SCrawler.Plugin.XVIDEOS/SCrawler.Plugin.XVIDEOS.vbproj b/SCrawler.Plugin.XVIDEOS/SCrawler.Plugin.XVIDEOS.vbproj new file mode 100644 index 0000000..e3ec88a --- /dev/null +++ b/SCrawler.Plugin.XVIDEOS/SCrawler.Plugin.XVIDEOS.vbproj @@ -0,0 +1,175 @@ + + + + + Debug + AnyCPU + {CCCF47F4-C97C-4193-AC4B-C56DF2F9AA8A} + Library + XVIDEOS + SCrawler.Plugin.XVIDEOS + 512 + Windows + v4.6.1 + true + + + true + full + true + true + bin\Debug\ + + + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + pdbonly + false + true + true + bin\Release\ + + + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + On + + + Binary + + + Off + + + On + + + true + true + true + bin\x64\Debug\ + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + full + x64 + + + true + bin\x64\Release\ + true + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + pdbonly + x64 + + + true + true + true + bin\x86\Debug\ + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + full + x86 + + + true + bin\x86\Release\ + true + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + pdbonly + x86 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + Application.myapp + True + + + True + True + Resources.resx + + + True + Settings.settings + True + + + SettingsForm.vb + + + Form + + + + + + + VbMyResourcesResXFileCodeGenerator + Resources.Designer.vb + My.Resources + Designer + + + SettingsForm.vb + + + + + + MyApplicationCodeGenerator + Application.Designer.vb + + + SettingsSingleFileGenerator + My + Settings.Designer.vb + + + + + {8405896b-2685-4916-bc93-1fb514c323a9} + PersonalUtilities + + + {d4650f6b-5a54-44b6-999b-6c675b7116b1} + SCrawler.PluginProvider + + + + + + + + + + \ No newline at end of file diff --git a/SCrawler.Plugin.XVIDEOS/SettingsForm.Designer.vb b/SCrawler.Plugin.XVIDEOS/SettingsForm.Designer.vb new file mode 100644 index 0000000..cbbfb97 --- /dev/null +++ b/SCrawler.Plugin.XVIDEOS/SettingsForm.Designer.vb @@ -0,0 +1,129 @@ +' 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 Public Class SettingsForm : Inherits System.Windows.Forms.Form + + Protected Overrides Sub Dispose(ByVal disposing As Boolean) + Try + If disposing AndAlso components IsNot Nothing Then + components.Dispose() + End If + Finally + MyBase.Dispose(disposing) + End Try + End Sub + Private components As System.ComponentModel.IContainer + + Private Sub InitializeComponent() + Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer + Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(SettingsForm)) + Me.LIST_DOMAINS = New System.Windows.Forms.ListBox() + Me.ToolbarTOP = New System.Windows.Forms.ToolStrip() + Me.BTT_ADD = New System.Windows.Forms.ToolStripButton() + Me.BTT_DELETE = New System.Windows.Forms.ToolStripButton() + CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer() + CONTAINER_MAIN.ContentPanel.SuspendLayout() + CONTAINER_MAIN.TopToolStripPanel.SuspendLayout() + CONTAINER_MAIN.SuspendLayout() + Me.ToolbarTOP.SuspendLayout() + Me.SuspendLayout() + ' + 'CONTAINER_MAIN + ' + ' + 'CONTAINER_MAIN.ContentPanel + ' + CONTAINER_MAIN.ContentPanel.Controls.Add(Me.LIST_DOMAINS) + CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(384, 266) + CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill + CONTAINER_MAIN.LeftToolStripPanelVisible = False + CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0) + CONTAINER_MAIN.Name = "CONTAINER_MAIN" + CONTAINER_MAIN.RightToolStripPanelVisible = False + CONTAINER_MAIN.Size = New System.Drawing.Size(384, 291) + CONTAINER_MAIN.TabIndex = 0 + ' + 'CONTAINER_MAIN.TopToolStripPanel + ' + CONTAINER_MAIN.TopToolStripPanel.Controls.Add(Me.ToolbarTOP) + ' + 'LIST_DOMAINS + ' + Me.LIST_DOMAINS.Dock = System.Windows.Forms.DockStyle.Fill + Me.LIST_DOMAINS.FormattingEnabled = True + Me.LIST_DOMAINS.Location = New System.Drawing.Point(0, 0) + Me.LIST_DOMAINS.Name = "LIST_DOMAINS" + Me.LIST_DOMAINS.Size = New System.Drawing.Size(384, 266) + Me.LIST_DOMAINS.TabIndex = 0 + ' + 'ToolbarTOP + ' + Me.ToolbarTOP.Dock = System.Windows.Forms.DockStyle.None + Me.ToolbarTOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden + Me.ToolbarTOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_ADD, Me.BTT_DELETE}) + Me.ToolbarTOP.Location = New System.Drawing.Point(0, 0) + Me.ToolbarTOP.Name = "ToolbarTOP" + Me.ToolbarTOP.Size = New System.Drawing.Size(384, 25) + Me.ToolbarTOP.Stretch = True + Me.ToolbarTOP.TabIndex = 0 + ' + 'BTT_ADD + ' + Me.BTT_ADD.AutoToolTip = False + Me.BTT_ADD.BackColor = System.Drawing.Color.FromArgb(CType(CType(192, Byte), Integer), CType(CType(255, Byte), Integer), CType(CType(192, Byte), Integer)) + Me.BTT_ADD.ForeColor = System.Drawing.Color.DarkGreen + Me.BTT_ADD.Image = CType(resources.GetObject("BTT_ADD.Image"), System.Drawing.Image) + Me.BTT_ADD.ImageTransparentColor = System.Drawing.Color.Magenta + Me.BTT_ADD.Name = "BTT_ADD" + Me.BTT_ADD.Size = New System.Drawing.Size(49, 22) + Me.BTT_ADD.Text = "Add" + ' + 'BTT_DELETE + ' + Me.BTT_DELETE.AutoToolTip = False + Me.BTT_DELETE.BackColor = System.Drawing.Color.FromArgb(CType(CType(255, Byte), Integer), CType(CType(192, Byte), Integer), CType(CType(192, Byte), Integer)) + Me.BTT_DELETE.ForeColor = System.Drawing.Color.Maroon + Me.BTT_DELETE.Image = CType(resources.GetObject("BTT_DELETE.Image"), System.Drawing.Image) + Me.BTT_DELETE.ImageTransparentColor = System.Drawing.Color.Magenta + Me.BTT_DELETE.Name = "BTT_DELETE" + Me.BTT_DELETE.Size = New System.Drawing.Size(60, 22) + Me.BTT_DELETE.Text = "Delete" + ' + 'SettingsForm + ' + Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) + Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font + Me.ClientSize = New System.Drawing.Size(384, 291) + Me.Controls.Add(CONTAINER_MAIN) + Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle + Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon) + Me.MaximizeBox = False + Me.MaximumSize = New System.Drawing.Size(400, 330) + Me.MinimizeBox = False + Me.MinimumSize = New System.Drawing.Size(400, 330) + Me.Name = "SettingsForm" + Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide + Me.Text = "Settings" + CONTAINER_MAIN.ContentPanel.ResumeLayout(False) + CONTAINER_MAIN.TopToolStripPanel.ResumeLayout(False) + CONTAINER_MAIN.TopToolStripPanel.PerformLayout() + CONTAINER_MAIN.ResumeLayout(False) + CONTAINER_MAIN.PerformLayout() + Me.ToolbarTOP.ResumeLayout(False) + Me.ToolbarTOP.PerformLayout() + Me.ResumeLayout(False) + + End Sub + + Private WithEvents LIST_DOMAINS As Windows.Forms.ListBox + Private WithEvents ToolbarTOP As Windows.Forms.ToolStrip + Private WithEvents BTT_ADD As Windows.Forms.ToolStripButton + Private WithEvents BTT_DELETE As Windows.Forms.ToolStripButton +End Class \ No newline at end of file diff --git a/SCrawler.Plugin.XVIDEOS/SettingsForm.resx b/SCrawler.Plugin.XVIDEOS/SettingsForm.resx new file mode 100644 index 0000000..7083d71 --- /dev/null +++ b/SCrawler.Plugin.XVIDEOS/SettingsForm.resx @@ -0,0 +1,477 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + False + + + 17, 17 + + + + + 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 + FHW1qQAAAABJRU5ErkJggg== + + + + + AAABAAUAEBAAAAEAIABoBAAAVgAAABgYAAABACAAiAkAAL4EAAAgIAAAAQAIAKgIAABGDgAAMDAAAAEA + IACoJQAA7hYAACAgAAABAAgAqAgAAJY8AAAoAAAAEAAAACAAAAABACAAAAAAAAAEAAAAAAAAAAAAAAAA + AAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAIO/wADF/8AAxb/AAEJ/wAAAP8AAAD/AAAA/wAAAP8AAQb/AAMV/wAD + F/8AAhL/AAAC/wAAAP8AAAD/AAAA/wAHMv8AFoz/ABiW/wAQaf8AAQz/AAAA/wAAAP8AAAT/AAxU/wAY + lP8AGJP/AAtJ/wAAAv8AAAD/AAAA/wAAAP8AAQ3/ABOQ/wAh3v8AH9T/AAtb/wAAAf8AAAD/AAc7/wAc + x/8AIeD/ABis/wADHv8AAAD/AAAA/wAAAP8AAAD/AAAA/wAFK/8AG73/ACLk/wAbvf8ABSr/AAIV/wAW + o/8AIuP/AB7P/wAIRv8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAH/AAtZ/wAf1v8AIeH/ABSU/wAQ + e/8AINz/ACDe/wAPdv8AAAX/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wABC/8AE4z/ACHg/wAg + 2/8AINn/ACHi/wAXpf8AAhn/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAQm/wAa + t/8AIeH/ACHh/wAdyP8ABzr/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAB + C/8AFZj/ACHi/wAh4f8AG7r/AAQh/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AClH/AB7S/wAh4P8AIeD/ACHe/wAQfP8AAAb/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8ABCX/ABq2/wAi4/8AGrn/ABag/wAh4P8AHtD/AAlH/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAQr/ABKI/wAh4f8AH9X/AApQ/wAEKP8AG7v/ACLk/wAYrv8AAx7/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/Ag1W/wIi1/8CJOP/ABOL/wABCv8AAAD/AAxc/wIi2f8CJOL/AhN//wABB/8AAAD/AAAA/wAA + AP8AAAD/CQ0h/ylBsv8vTt7/Iz67/wMJKv8AAAD/AAAA/wACEP8aMJr/L07e/y1Iyv8RGD//AAAA/wAA + AP8AAAD/AAAA/wUHEP8RFzL/Ehg0/wwQI/8BAQL/AAAA/wAAAP8AAAD/CAsY/xIYM/8SGDT/CAsZ/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAoAAAAGAAAADAAAAABACAAAAAAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAEM/wADG/8AAxr/AAMa/wADFv8AAQT/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAB/wACEf8AAxv/AAMa/wADG/8AAhT/AAAC/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAQk/wAT + dv8AF4b/ABeF/wAVgP8ACT7/AAAC/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAQl/wATdP8AF4X/ABeF/wAW + gf8ACUD/AAAD/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAI/wAOav8AHcX/AB/K/wAfyv8AGaz/AAQv/wAA + AP8AAAD/AAAA/wAAAP8AART/ABKL/wAeyf8AH8r/AB/L/wAVkv8AAhr/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wADJP8AF6v/ACHi/wAh4P8AIeD/ABKR/wABE/8AAAD/AAAA/wAAA/8ADGH/AB/W/wAh + 4f8AIuL/ABzJ/wAISf8AAAH/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AB0b/AB3K/wAh + 4P8AIeD/AB7U/wALYP8AAAT/AAAA/wAFN/8AGr3/ACHi/wAh4P8AINr/AA5y/wAAB/8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAf/AA53/wAg2v8AIeD/ACHh/wAauv8ABTL/AAIT/wAT + k/8AId//ACHf/wAh4P8AFaD/AAIb/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAIg/wAVpP8AIeH/ACHg/wAh3v8AE5X/AA1z/wAf1P8AIeD/ACHh/wAbwf8ABjz/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAHQf8AHMX/ACHh/wAh + 3/8AINr/AB/W/wAh4P8AIeD/AB/W/wAMZ/8AAAb/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAACP8ADXD/ACDZ/wAh4P8AId//ACHg/wAh3/8AId//ABSU/wAB + Fv8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAhj/ABWe/wAh3/8AId//ACHf/wAh4P8AGrz/AAUx/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAT/AAxr/wAg3P8AId//ACHf/wAh + 4f8AFqP/AAIT/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAyX/ABiv/wAh4P8AId//ACHf/wAh4P8AH9L/AApb/wAAAv8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wABDf8AEYL/ACDd/wAh + 3/8AIeD/ACHg/wAh3/8AIeH/ABm3/wAFL/8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAC/wAKU/8AHs7/ACHh/wAh4P8AHMX/ABeo/wAg3P8AIeD/ACHf/wAS + jv8AARL/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAQq/wAY + sP8AIeH/ACHg/wAf1/8ADGj/AAQy/wAYtP8AIeH/ACHg/wAe0v8AC1v/AAAD/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAQv/ABGG/wAg3f8AIeD/ACHh/wAVnf8AAhr/AAAB/wAL + XP8AH9P/ACHg/wAh4P8AGrn/AAQu/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + Av8ACVX/AB3R/wAg4P8AIOH/ABvE/wAHPv8AAAD/AAAA/wABE/8AE5L/ACDf/wAg3/8AIN//ABGO/wAB + Ef8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wULLv8NKbj/DjHn/w4x5f8MLt//ARFz/wAA + CP8AAAD/AAAA/wAAAP8ABTT/ByXD/w4x5v8OMeb/Di7Y/wgWYf8BAQT/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/BAYN/yg5hf9BXuH/QF7i/0Ff4/8tRa7/Awgd/wAAAP8AAAD/AAAA/wAAAP8AAQX/GChx/z9b + 3f9BX+L/QV/k/zZOt/8MECj/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AgMJ/w8VMf8VHT//FRw9/xUc + Pv8KDiH/AAEB/wAAAP8AAAD/AAAA/wAAAP8AAAD/BQcP/xMZOP8VHD7/FRw+/xMbPP8FBxL/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + RS0uLiVGR0glLi40NTYAAAAAAAAAAAAAAAAAAAAAPT4lLi4lP0AAQUIuLi4uQwAAAAAAAAAAAAAAAAAA + ADE3JS4uLSw4AAA5OjQuLi07PAAAAAAAAAAAAAAAAAAAKywtLi4vMDEAAAAyMyUuLjQ1NgAAAAAAAAAA + AAAAACEiIyQkJSYnAAAAAAAoKSQkJCQqAAAAAAAAAAAAAAAVFhcYGBgZGgAAAAAAABscHRgYHh8gAAAA + AAAAAAAAAAkKCwwMDQ4PAAAAAAAAABAREgwMDRMUAAAAAAAAAAAAAQIDAwMDBAAAAAAAAAAAAAUGAwMD + BwgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAMAAAAGAA + AAABACAAAAAAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAC/wAAB/8AAAr/AAAJ/wAA + Cf8AAAn/AAAJ/wAACf8AAAj/AAAF/wAAAv8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAH/AAAH/wAACf8AAAn/AAAJ/wAACf8AAAn/AAAJ/wAA + Cf8AAAf/AAAB/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAH/AAAI/wAD + Gv8ABSr/AAYq/wAGKv8ABSr/AAUq/wAGK/8ABSn/AAQh/wACEP8AAAL/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wABB/8AAhT/AAUm/wAGK/8ABSr/AAUq/wAF + Kv8ABir/AAYr/wAEJf8AAhj/AAAF/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAP/AAEP/wAJPf8AEmj/ABRv/wAUb/8AE2//ABNv/wAUcP8AE27/ABFl/wAIOf8AAQ3/AAAC/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAEIf8AC03/ABJp/wAU + cP8AE2//ABNv/wATb/8AFG//ABRw/wANWP8ABTH/AAEK/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAH/AAAJ/wAHOP8AEXH/ABmV/wAbnv8AGpv/ABqc/wAanP8AGpz/ABmY/wAR + cv8ABzz/AAEM/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAX/AAEa/wAK + Uf8AFYf/ABmZ/wAbnf8AGpz/ABqc/wAbnf8AG5v/ABiO/wANWv8AAyD/AAAG/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wACHf8ACVT/ABed/wAduf8AHbv/AB27/wAd + u/8AHbv/AB68/wAaq/8AEHz/AAQo/wAABf8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AARL/AAdM/wATjP8AHLn/AB28/wAdu/8AHbv/AB27/wAevf8AHLH/ABOG/wAIP/8AAAT/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAABP8ABCr/ABKL/wAc + xP8AINv/ACDZ/wAg2P8AINj/ACHY/wAg1/8AGrn/AApm/wACJP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAACP8ABDH/ABOR/wAcxv8AINn/ACDZ/wAg2P8AINj/ACDZ/wAg1/8AGrf/AApf/wAC + IP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAhH/AAlV/wAVpP8AINz/ACHh/wAh4f8AIeH/ACHg/wAi5P8AH9b/ABSk/wAIUv8AAA3/AAAC/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAEJv8ADGv/ABu//wAg3/8AIeL/ACHh/wAh4P8AIeH/ACLj/wAc + yf8AEY7/AAQy/wAACf8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAX/AAEe/wANbv8AGr//ACDb/wAh4f8AId//ACHf/wAh4f8AId7/AB7R/wAR + hv8ABDL/AAEJ/wAAAP8AAAD/AAAA/wAAAP8AAAH/AAEL/wAKU/8AFqj/AB/X/wAh4/8AId//ACHf/wAh + 4P8AId//ACDZ/wAUnv8AB0//AAEP/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAF/wAFOv8AD4b/AB7M/wAi4v8AId//ACHf/wAh + 3/8AIeD/ACHf/wAZuP8ADXL/AAMZ/wAAAP8AAAD/AAAA/wAAAP8AAQv/AAQ4/wARi/8AHtH/ACHe/wAh + 4P8AId//ACHf/wAi4v8AINv/ABm6/wAMZf8AARX/AAAD/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wABE/8AB0j/ABem/wAf + 1f8AIeH/ACHg/wAh3/8AIeD/ACHh/wAf1v8AF6j/AAdJ/wABE/8AAAD/AAAA/wAAAf8AAyD/AA10/wAZ + uf8AIeD/ACHg/wAh3/8AId//ACHg/wAh4f8AHMj/AA9+/wAFM/8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAxj/AA1v/wAZtv8AIN//ACHg/wAh3/8AId//ACHf/wAi4v8AHs3/AA+H/wAFOv8AAAT/AAAA/wAB + E/8ACEr/ABes/wAf2P8AIeH/ACHf/wAh3/8AIeD/ACHh/wAe0v8AFaH/AAVA/wAAD/8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAn/AAMv/wAQg/8AHc//ACDe/wAh4f8AId//ACHf/wAh4f8AINv/ABq//wAN + bP8AARv/AAAE/wAGOf8AEYz/AB3N/wAh4f8AId//ACHf/wAh3/8AIeD/ACHf/wAXrv8ACWL/AAIZ/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAL/AAAM/wAITv8AE6D/AB7U/wAi4/8AId//ACHf/wAh + 4P8AIeD/ACDa/wAVnv8ACVf/AAQ0/wANbv8AG7//ACDc/wAh4v8AId//ACHf/wAh4f8AIN3/ABzG/wAP + ef8AAyj/AAAH/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wACIf8ACWL/ABq6/wAg + 3f8AIeD/ACHf/wAh3/8AIeD/ACLi/wAcxv8AE53/AA18/wAVpv8AIdv/ACHg/wAh4P8AId//ACHf/wAh + 4f8AHtD/ABOV/wAHQv8AAAL/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + A/8ABCj/ABGH/wAbxf8AIeL/ACHg/wAh3/8AId//ACHg/wAg2f8AHc//ABvF/wAe0f8AId//ACHf/wAh + 3/8AId//ACHh/wAf2f8AGLD/AAhQ/wABF/8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAQ7/AAdI/wAUmf8AH9f/ACHf/wAh4P8AId//ACHf/wAh3/8AIeD/ACHf/wAh + 3/8AIeD/ACHf/wAh3/8AIeD/ACHh/wAZvP8ADnj/AAMj/wAAA/8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAP/AAAV/wALY/8AGbf/AB/Z/wAh4f8AId//ACHf/wAh + 3/8AId//ACHg/wAh3/8AId//ACHf/wAh4P8AId7/AB7S/wARjf8ABDv/AAEL/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAD/wAEMf8ADXn/ABzH/wAh + 4f8AIeD/ACHf/wAh3/8AId//ACHf/wAh3/8AId//ACHf/wAh4v8AH9b/ABan/wAKU/8AAQz/AAAC/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + Dv8ABj3/ABWb/wAez/8AIeH/ACHg/wAh3/8AId//ACHf/wAh3/8AId//ACHg/wAg2/8AGrr/AAxn/wAE + Jf8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAhT/AAtl/wAYsP8AId//ACHg/wAh3/8AId//ACHf/wAh3/8AIeD/ACHh/wAd + zv8AE5X/AAQv/wAABf8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAr/AAM1/wASjf8AINj/ACHf/wAh4P8AId//ACHf/wAh + 3/8AIeD/ACLi/wAavv8ADnf/AAMa/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAQ3/AAZG/wAUmf8AINv/ACHf/wAh + 4P8AId//ACHf/wAh3/8AIeD/ACLh/wAdyf8AE4//AAQu/wAABv8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAv8AAyL/AA56/wAa + vP8AIeD/ACHg/wAh3/8AId//ACHf/wAh3/8AId//ACHg/wAh3f8AG7r/AApf/wACIP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAB + Gf8ACFT/ABix/wAf2f8AIeD/ACHf/wAh3/8AId//ACHf/wAh3/8AId//ACHf/wAi4v8AH9P/ABWi/wAI + TP8AAAX/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAG/wAHQv8AEpL/AB7Q/wAh4/8AId//ACHf/wAh3/8AIeD/ACHh/wAh4P8AId//ACHf/wAi + 4f8AId7/AB3N/wAQgv8ABC//AAEJ/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAb/AAMi/wAPdf8AHMb/ACDd/wAh4f8AId//ACHf/wAh3/8AId7/ACDb/wAg + 3f8AId//ACHf/wAh3/8AIeD/ACHg/wAYtP8ADGz/AAMc/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAhP/AAtg/wAXq/8AINz/ACHg/wAh3/8AId//ACHg/wAg + 3P8AHtH/ABvA/wAdzf8AId//ACHf/wAh3/8AId//ACHg/wAf1f8AF6b/AAZF/wAAEf8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAADf8ABjv/ABWa/wAez/8AIeL/ACHg/wAh + 3/8AIeD/ACHi/wAcy/8AFaL/AA51/wAVm/8AH9X/ACHf/wAh4P8AId//ACHf/wAi4f8AHcr/AA+C/wAF + NP8AAAH/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAC/wADLv8ADXX/ABzF/wAh + 4f8AIeD/ACHf/wAh3/8AIeD/ACDd/wAWqf8ACmH/AAIo/wALX/8AGbb/AB/Z/wAh4v8AId//ACHf/wAi + 4v8AINv/ABm7/wAMZf8AARX/AAAD/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAP/AAAR/wAL + Xv8AGLP/AB/Y/wAh4f8AId//ACHf/wAh4f8AIN3/ABzI/wAPdv8AAiL/AAAJ/wAEMf8ADXz/ABzK/wAh + 4v8AId//ACHf/wAh4P8AId//ACDZ/wAUnf8AB07/AAEP/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAQ3/AAZD/wATlP8AH9X/ACHf/wAh4P8AId//ACHf/wAi4v8AHtH/ABKW/wAHRf8AAAb/AAAA/wAA + D/8ABkL/ABak/wAf1P8AIuH/ACHg/wAh3/8AIeD/ACHh/wAcx/8AEYr/AAQu/wAAB/8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAv8ABCT/ABCB/wAbwv8AIeH/ACHg/wAh3/8AId//ACHg/wAg2/8AGbX/AAlZ/wAC + HP8AAAD/AAAA/wAAAP8AAxf/AA1u/wAZtv8AId//ACHg/wAh3/8AId//ACHg/wAh3v8AG7v/AApg/wAC + IP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wACHf8ACVr/ABm1/wAg2/8AIeD/ACHf/wAh3/8AIeD/ACHi/wAb + w/8AEIL/AAQk/wAAAv8AAAD/AAAA/wAAAP8AAQn/AAQw/wARhf8AHtH/ACHe/wAh4f8AId//ACHf/wAi + 4v8AH9T/ABWi/wAITP8AAAX/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAH/AAAI/wAHR/8AEZf/AB3R/wAg4v8AH9//AB/f/wAg + 4P8AIN//AB7X/wATl/8AB0b/AAEN/wAAAP8AAAD/AAAA/wAAAP8AAAL/AAAN/wAJU/8AFab/AB7W/wAg + 4v8AH97/AB/f/wAg4f8AH97/ABvM/wAOgf8AAy//AAAJ/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAQf/AgYp/wQUfP8EIcv/BCTf/wQl + 4/8EJeH/BCXh/wQm4/8DJNr/ARq4/wAMY/8AABX/AAAD/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAC + J/8AC2z/Ah3C/wMk4P8EJeH/BCXh/wQl4f8EJeL/BCXi/wQctv8EEG3/AQQc/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8DBhb/DR5s/xQx + uP8WO+b/Fjvp/xY76P8WO+j/Fjvo/xY86v8RM9H/BBaB/wAGNP8AAAP/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAABv8BBzH/CCGa/xAz1f8XPOv/Fjvp/xY76P8WO+n/Fjvp/xc63v8TLq7/CBJJ/wIE + Ev8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wYI + Ev8VH0r/L0ey/zpZ5/87Xvf/O131/ztd9P87XfX/O172/zRV5f8jPa//BxFG/wABEP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8CBRP/Chti/yM+tv85WvD/O130/zte9f87XfT/O131/zxe + 9v84Vt7/KDqS/xEZPv8AAQT/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/woPJf8gLmj/QFa8/0tk1/9KY9T/SmPU/0pj1P9KZNX/SmTW/z1Ttv8lNHX/BwsZ/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8BAwj/CQ8q/yc3ff9FXMj/SmPT/0pk + 1f9KY9T/SmPU/0tk1/9IYM//O0+s/xslVP8AAQf/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wUIF/8PFzn/HCZX/x8rYP8fKl3/Hipd/x4qXf8fKl7/Hype/xYe + Rv8KDiT/AgMH/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAH/AgMI/w0T + LP8aI1L/Hilc/x8qXv8eKl3/Hipd/x8qXv8eKV3/GyVV/w0TLP8BAQX/AAAB/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wIDCf8EBxT/BwoZ/wgLGv8HCxn/BwsZ/wcL + Gf8HCxn/BwsZ/wQGD/8AAAT/AAAB/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wIDCf8FBxT/BwoZ/wgLGv8HCxn/BwsZ/wcKGf8HCxr/Bwsa/wQGD/8AAAL/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA + AP8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAACAAAABAAAAAAQAIAAAAAAAABAAAAAAAAAAA + AAAAAQAAAAEAAAAAAAAIDigAFBxBABMbPwADBhQADRMxABQbQAASGj0AAQEGABsnWgBSbewAVXHyAFRx + 8QBVcvQANUqlAAABAwANFz8ATmjiAFVy8gA+U7UAAQIKAAAAAgAULJcAG0LsABtB6gAZP+QAAQ1bAAAA + CAALKawAHELtABtB6wAbPtgABg46AAABHgAAGb0AACDhAAAg3wAAIeEAABq/AAABIAAACGcAACDeAAAK + cAAABlEAACDYAAAh4AAAId8AACHiAAARjQAAAAEAAAIpAAAcxwAAIuIAABWoAAAACgAAEIsAAAZPAAAA + AwAAE5cAAB7OAAADNgAAARsAABq7AAAZugAAARkAAAZXAAAg2wAAC3AAAAVNAAAg1wAADoMAAAEiAAAa + vQAAEIcAAB/TAAAYtAAAARgAABm4AAAFSQAAH9YAAA6CAAAezAAAAzUAAAIzAAAQiAAAEIkAAAZSAAAg + 2gAAEpIAACDcAAAbwgAAASUAAAZbAAATmwAAB2EAABOZAAAABQAAAScAABvEAAACKgAAEY4AACHdAAAI + ZAAAAAQAAAhjAAABHwAAGr4AABzKAAACMQAACGIAACHcAAATnAAABlMAACDZAAAVpgAAAi0AABzIAAAL + cgAAAAYAABSgAAAe0AAAAzwAAAdOAAAcsQAAHLMAAB61AAARgQAABUcAABuvAAActAAAE4cAAAEVAAAU + dQAAGIEAABeAAAAXgQAAE3MAAAtTAAAHQwAAAAcAAAIaAAACGQAAAQ4AAAEUAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAi4yNjY2M + jgAAAAAAAAAAAAA5jY2NjYyPAAAAAAAAAACDhIWGhoeIgwAAAAAAAAAAMYmFhoaGhYoAAAAAAAAAAAB6 + e3x8fH1+ZwAAAAAAAAB/gIF8fH2CGwAAAAAAAAAAAHZ3Ly4uLlleAAAAAAAAaUglLi4teHkAAAAAAAAA + AAAAAHN0JS4uJTNjAAAAABVkLy4uLi51AAAAAAAAAAAAAAAAAG1uLi4uL29gAAAAcHEtLi40cjYAAAAA + AAAAAAAAAAAAZ18vLi4uZWgAAGlqJS4uJWtsAAAAAAAAAAAAAAAAAAAAYWIlLi4lM2MxZC8uLi5lZgAA + AAAAAAAAAAAAAAAAAAAAXEItLi40XV4sLS4uL19gAAAAAAAAAAAAAAAAAAAAAAAVWC8uLi5ZTy0uLiVa + WwAAAAAAAAAAAAAAAAAAAAAAAAAnJiUuLi4tLi4tV0EAAAAAAAAAAAAAAAAAAAAAAAAAAABWLC0uLi4u + LiUwFQAAAAAAAAAAAAAAAAAAAAAAAAAAADFVLS4uLi4lTT0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFNK + LS4uLjRUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxUC4uLi4uLVFSAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AE5PLS4uLi4uNDU2AAAAAAAAAAAAAAAAAAAAAAAAAABMTS8uLi0lLi4uLkMAAAAAAAAAAAAAAAAAAAAA + AAAAMUklLi4tSksuLi4tOzwAAAAAAAAAAAAAAAAAAAAAAABERS0uLiVGR0glLi40NTYAAAAAAAAAAAAA + AAAAAAAAPT4lLi4lP0AAQUIuLi4uQwAAAAAAAAAAAAAAAAAAADE3JS4uLSw4AAA5OjQuLi07PAAAAAAA + AAAAAAAAAAAAKywtLi4vMDEAAAAyMyUuLjQ1NgAAAAAAAAAAAAAAACEiIyQkJSYnAAAAAAAoKSQkJCQq + AAAAAAAAAAAAAAAVFhcYGBgZGgAAAAAAABscHRgYHh8gAAAAAAAAAAAAAAkKCwwMDQ4PAAAAAAAAABAR + EgwMDRMUAAAAAAAAAAAAAQIDAwMDBAAAAAAAAAAAAAUGAwMDBwgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + + + \ No newline at end of file diff --git a/SCrawler.Plugin.XVIDEOS/SettingsForm.vb b/SCrawler.Plugin.XVIDEOS/SettingsForm.vb new file mode 100644 index 0000000..987e17f --- /dev/null +++ b/SCrawler.Plugin.XVIDEOS/SettingsForm.vb @@ -0,0 +1,73 @@ +' 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.Forms.Toolbars +Imports PersonalUtilities.Forms +Public Class SettingsForm : Implements IOkCancelToolbar + Private ReadOnly MyDefs As DefaultFormProps + Private ReadOnly Property Settings As SiteSettings + Friend Sub New(ByRef s As SiteSettings) + InitializeComponent() + MyDefs = New DefaultFormProps + Settings = s + End Sub + Private Sub SettingsForm_Load(sender As Object, e As EventArgs) Handles Me.Load + Try + With MyDefs + .MyViewInitialize(Me, Settings.Design, True) + .AddOkCancelToolbar() + .DelegateClosingChecker() + If Settings.Domains.Count > 0 Then Settings.Domains.ForEach(Sub(d) LIST_DOMAINS.Items.Add(d)) + .EndLoaderOperations() + End With + Catch ex As Exception + MyDefs.InvokeLoaderError(ex) + End Try + End Sub + Private Sub ToolbarBttOK() Implements IOkCancelToolbar.ToolbarBttOK + Settings.Domains.Clear() + With LIST_DOMAINS + If .Items.Count > 0 Then + For Each i In .Items : Settings.Domains.Add(i.ToString) : Next + End If + End With + Settings.UpdateDomains() + MyDefs.CloseForm() + End Sub + Private Sub ToolbarBttCancel() Implements IOkCancelToolbar.ToolbarBttCancel + MyDefs.CloseForm(Windows.Forms.DialogResult.Cancel) + End Sub + Private Sub BTT_ADD_Click(sender As Object, e As EventArgs) Handles BTT_ADD.Click + Dim nd$ = InputBoxE("Enter a new domain using the pattern [xvideos.com]:", "New domain") + If Not nd.IsEmptyString Then + If Not LIST_DOMAINS.Items.Contains(nd) Then + LIST_DOMAINS.Items.Add(nd) + Else + MsgBoxE($"The domain [{nd}] already added") + End If + End If + End Sub + Private Sub BTT_DELETE_Click(sender As Object, e As EventArgs) Handles BTT_DELETE.Click + If _LatestSelected.ValueBetween(0, LIST_DOMAINS.Items.Count - 1) Then + Dim n$ = LIST_DOMAINS.Items(_LatestSelected) + If MsgBoxE({$"Are you sure you want to delete the [{n}] domain?", + "Removing domains"}, MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then + LIST_DOMAINS.Items.RemoveAt(_LatestSelected) + MsgBoxE($"Domain [{n}] removed") + Else + MsgBoxE("Operation canceled") + End If + Else + MsgBoxE("No domain selected", vbExclamation) + End If + End Sub + Private _LatestSelected As Integer = -1 + Private Sub LIST_DOMENS_SelectedIndexChanged(sender As Object, e As EventArgs) Handles LIST_DOMAINS.SelectedIndexChanged + _LatestSelected = LIST_DOMAINS.SelectedIndex + End Sub +End Class \ No newline at end of file diff --git a/SCrawler.Plugin.XVIDEOS/SiteSettings.vb b/SCrawler.Plugin.XVIDEOS/SiteSettings.vb new file mode 100644 index 0000000..f79f6c7 --- /dev/null +++ b/SCrawler.Plugin.XVIDEOS/SiteSettings.vb @@ -0,0 +1,185 @@ +' 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.Drawing +Imports PersonalUtilities.Functions.XML +Imports PersonalUtilities.Functions.RegularExpressions +Imports PersonalUtilities.Tools.WEB + +Public Class SiteSettings : Implements ISiteSettings + Public ReadOnly Property Icon As Icon Implements ISiteSettings.Icon + Get + Return My.Resources.Icon32 + End Get + End Property + Public ReadOnly Property Image As Image Implements ISiteSettings.Image + Get + Return My.Resources.IconPic32 + End Get + End Property + Public ReadOnly Property Site As String = "XVIDEOS" Implements ISiteSettings.Site + Public Property Logger As ILogProvider Implements ISiteSettings.Logger +#Region "M3U8" + Private ReadOnly OS64 As Boolean + Private ReadOnly FfmpegExists As Boolean + Friend ReadOnly FfmpegFile As SFile + Friend ReadOnly Property UseM3U8 As Boolean + Get + Return OS64 And FfmpegExists + End Get + End Property +#End Region + Private Property SiteDomains As PropertyValue + + Public Property DownloadUHD As PropertyValue + Friend ReadOnly Property Domains As List(Of String) + Public ReadOnly Property Responser As Response + Private Const DomainsDefault As String = "xvideos.com|xnxx.com" + Private _Initialized As Boolean = False + Friend Design As XmlFile + Public Sub New() + Responser = New Response($"Settings\Responser_{Site}.xml") + With Responser + If .File.Exists Then + .LoadSettings() + Else + .CookiesDomain = "www.xvideos.com" + .SaveSettings() + End If + End With + OS64 = Environment.Is64BitOperatingSystem + FfmpegFile = "ffmpeg.exe" + FfmpegExists = FfmpegFile.Exists + Domains = New List(Of String) + SiteDomains = New PropertyValue(DomainsDefault, GetType(String), Sub(s) UpdateDomains()) + DownloadUHD = New PropertyValue(False) + End Sub + Public Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider Implements ISiteSettings.GetInstance + Return New UserData + End Function + Public Sub BeginInit() Implements ISiteSettings.BeginInit + End Sub + Public Sub EndInit() Implements ISiteSettings.EndInit + _Initialized = True + UpdateDomains() + End Sub + Public Sub Load(ByVal XMLValues As IEnumerable(Of KeyValuePair(Of String, String))) Implements ISiteSettings.Load + End Sub + Private _DomainsUpdateInProgress As Boolean = False + Friend Sub UpdateDomains() + If Not _Initialized Then Exit Sub + If Not _DomainsUpdateInProgress Then + _DomainsUpdateInProgress = True + If Not ACheck(SiteDomains.Value) Then SiteDomains.Value = DomainsDefault + Domains.ListAddList(CStr(SiteDomains.Value).Split("|"), LAP.NotContainsOnly, LAP.ClearBeforeAdd) + Domains.ListAddList(DomainsDefault.Split("|"), LAP.NotContainsOnly) + SiteDomains.Value = Domains.ListToString(, "|") + _DomainsUpdateInProgress = False + End If + End Sub +#Region "Downloading" + Public Function Available(ByVal What As ISiteSettings.Download) As Boolean Implements ISiteSettings.Available + Return UseM3U8 + End Function + Public Function ReadyToDownload(ByVal What As ISiteSettings.Download) As Boolean Implements ISiteSettings.ReadyToDownload + Return UseM3U8 + End Function + Public Sub DownloadStarted(ByVal What As ISiteSettings.Download) Implements ISiteSettings.DownloadStarted + End Sub + Public Sub BeforeStartDownload(ByVal User As Object, ByVal What As ISiteSettings.Download) Implements ISiteSettings.BeforeStartDownload + End Sub + Public Sub AfterDownload(ByVal User As Object, ByVal What As ISiteSettings.Download) Implements ISiteSettings.AfterDownload + End Sub + Public Sub DownloadDone(ByVal What As ISiteSettings.Download) Implements ISiteSettings.DownloadDone + End Sub +#End Region + Public Sub BeginUpdate() Implements ISiteSettings.BeginUpdate + End Sub + Public Sub EndUpdate() Implements ISiteSettings.EndUpdate + End Sub + Public Sub Update() Implements ISiteSettings.Update + UpdateDomains() + Responser.SaveSettings() + End Sub + Public Sub Reset() Implements ISiteSettings.Reset + End Sub + Public Sub OpenSettingsForm() Implements ISiteSettings.OpenSettingsForm + Using f As New SettingsForm(Me) + Design = New XmlFile("Settings\Design_XVIDEOS.xml") + f.ShowDialog() + Design.Dispose() + End Using + End Sub + Public Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean) Implements ISiteSettings.UserOptions + Options = Nothing + End Sub + Public Function GetUserUrl(ByVal UserName As String, ByVal Channel As Boolean) As String Implements ISiteSettings.GetUserUrl + Dim user$ = UserName.Split("_").FirstOrDefault + user &= $"/{UserName.Replace($"{user}_", String.Empty)}" + Return user + End Function + Private Const UserRegexDefault As String = "/(profiles|[\w]*?[-]{0,1}channels)/([^/]+)(\Z|.*?)" + Private Const URD As String = ".*?{0}{1}" + Public Function IsMyUser(ByVal UserURL As String) As ExchangeOptions Implements ISiteSettings.IsMyUser + If Not UserURL.IsEmptyString Then + If Domains.Count > 0 Then + Dim uName$, uOpt$, fStr$ + For i% = 0 To Domains.Count - 1 + fStr = String.Format(URD, Domains(i), UserRegexDefault) + uName = RegexReplace(UserURL, RParams.DMS(fStr, 2)) + If Not uName.IsEmptyString Then + uOpt = RegexReplace(UserURL, RParams.DMS(fStr, 1)) + If Not uOpt.IsEmptyString Then Return New ExchangeOptions(Site, $"{uOpt}_{uName}") + End If + Next + End If + End If + Return Nothing + End Function + Public Function IsMyImageVideo(ByVal URL As String) As ExchangeOptions Implements ISiteSettings.IsMyImageVideo + If Not URL.IsEmptyString And Domains.Count > 0 Then + If Domains.Exists(Function(d) URL.Contains(d)) Then Return New ExchangeOptions With {.UserName = URL, .Exists = True} + End If + Return Nothing + End Function + Private Class TempThrower : Implements IThrower + Private Sub ThrowAny() Implements IThrower.ThrowAny + End Sub + End Class + Public Function GetSpecialData(ByVal URL As String, ByVal Path As String, ByVal AskForPath As Boolean) As IEnumerable(Of PluginUserMedia) Implements ISiteSettings.GetSpecialData + If Not URL.IsEmptyString And UseM3U8 Then + Dim f As SFile = Path.CSFileP + f.Name = "video" + f.Extension = "mp4" +#Disable Warning BC40000 + If AskForPath Then f = SFile.SaveAs(f,, True, "mp4") +#Enable Warning + If Not f.IsEmptyString Then + Using user As New UserData With { + .LogProvider = Logger, + .Thrower = New TempThrower, + .ESettings = Me, + .DataPath = f.Path + } + With user + .TempMediaList = New List(Of PluginUserMedia) From {UserData.GetVideoData(URL, Responser.Copy, DownloadUHD.Value, String.Empty, Logger)} + If Not .TempMediaList(0).URL.IsEmptyString Then + .Download() + If .TempMediaList(0).DownloadState = PluginUserMedia.States.Downloaded Then + Dim p As PluginUserMedia = .TempMediaList(0) + p.SpecialFolder = p.File + Return {p} + End If + End If + End With + End Using + End If + End If + Return Nothing + End Function +End Class \ No newline at end of file diff --git a/SCrawler.Plugin.XVIDEOS/UserData.vb b/SCrawler.Plugin.XVIDEOS/UserData.vb new file mode 100644 index 0000000..cab84b3 --- /dev/null +++ b/SCrawler.Plugin.XVIDEOS/UserData.vb @@ -0,0 +1,232 @@ +' 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.RegularExpressions +Imports PersonalUtilities.Functions.XML +Imports PersonalUtilities.Tools.WEB +Imports PersonalUtilities.Tools.WebDocuments.JSON +Public Class UserData : Implements IPluginContentProvider +#Region "Interface declarations" + Public Event ProgressChanged(Count As Integer) Implements IPluginContentProvider.ProgressChanged + Public Event TotalCountChanged(Count As Integer) Implements IPluginContentProvider.TotalCountChanged + Public Property Thrower As IThrower Implements IPluginContentProvider.Thrower + Public Property LogProvider As ILogProvider Implements IPluginContentProvider.LogProvider + Public Property ESettings As ISiteSettings Implements IPluginContentProvider.Settings + Private ReadOnly Property Settings As SiteSettings + Get + Return DirectCast(ESettings, SiteSettings) + End Get + End Property + Public Property Name As String Implements IPluginContentProvider.Name + Public Property ID As String Implements IPluginContentProvider.ID + Public Property ParseUserMediaOnly As Boolean Implements IPluginContentProvider.ParseUserMediaOnly + Public Property UserDescription As String Implements IPluginContentProvider.UserDescription + Public Property ExistingContentList As List(Of PluginUserMedia) Implements IPluginContentProvider.ExistingContentList + Public Property TempPostsList As List(Of String) Implements IPluginContentProvider.TempPostsList + Public Property TempMediaList As List(Of PluginUserMedia) Implements IPluginContentProvider.TempMediaList + Public Property UserExists As Boolean Implements IPluginContentProvider.UserExists + Public Property UserSuspended As Boolean Implements IPluginContentProvider.UserSuspended + Public Property IsSavedPosts As Boolean Implements IPluginContentProvider.IsSavedPosts + Public Property SeparateVideoFolder As Boolean Implements IPluginContentProvider.SeparateVideoFolder + Public Property DataPath As String Implements IPluginContentProvider.DataPath + Public Property PostsNumberLimit As Integer? Implements IPluginContentProvider.PostsNumberLimit + Public Property PostsDateLimit As Date? Implements IPluginContentProvider.PostsDateLimit +#End Region +#Region "Interface exchange options" + Public Sub ExchangeOptionsSet(ByVal Obj As Object) Implements IPluginContentProvider.ExchangeOptionsSet + End Sub + Public Function ExchangeOptionsGet() As Object Implements IPluginContentProvider.ExchangeOptionsGet + Return Nothing + End Function +#End Region +#Region "Interface XML" + Public Sub XmlFieldsSet(ByVal Fields As List(Of KeyValuePair(Of String, String))) Implements IPluginContentProvider.XmlFieldsSet + End Sub + Public Function XmlFieldsGet() As List(Of KeyValuePair(Of String, String)) Implements IPluginContentProvider.XmlFieldsGet + Return Nothing + End Function +#End Region + Private Property Responser As Response + Public Sub GetMedia() Implements IPluginContentProvider.GetMedia + Try + If Not Settings.UseM3U8 Then LogProvider.Add("File [ffmpeg.exe] not found") : Exit Sub + If Not Responser Is Nothing Then Responser.Dispose() + Responser = New Response + Responser.Copy(Settings.Responser) + + Dim NextPage% = 0 + Dim r$ + Dim j As EContainer, jj As EContainer + Dim e As ErrorsDescriber = EDP.ThrowException + Dim user$ = Settings.GetUserUrl(Name, False) + Dim p As PluginUserMedia + Dim EnvirSet As Boolean = False + + Do + Thrower.ThrowAny() + r = Responser.GetResponse($"https://www.xvideos.com/{user}/videos/new/{If(NextPage = 0, String.Empty, NextPage)}",, e) + If Not r.IsEmptyString Then + If Not EnvirSet Then UserExists = True : UserSuspended = False + j = JsonDocument.Parse(r).XmlIfNothing + With j + If .Contains("videos") Then + With .Item("videos") + If .Count > 0 Then + NextPage += 1 + For Each jj In .Self + p = New PluginUserMedia With { + .PostID = jj.Value("id"), + .URL = $"https://www.xvideos.com{jj.Value("u")}" + } + If Not p.PostID.IsEmptyString And Not jj.Value("u").IsEmptyString Then + If Not TempPostsList.Contains(p.PostID) Then TempPostsList.Add(p.PostID) : TempMediaList.Add(p) Else Exit Do + End If + Next + End If + End With + Else + Exit Do + End If + .Dispose() + End With + Else + Exit Do + End If + Loop + + If TempMediaList.Count > 0 Then + For i% = 0 To TempMediaList.Count - 1 + Thrower.ThrowAny() + With TempMediaList(i) + TempMediaList(i) = GetVideoData(.URL, Responser, Settings.DownloadUHD.Value, .PostID, LogProvider) + End With + Next + TempMediaList.RemoveAll(Function(m) m.URL.IsEmptyString) + End If + Catch oex As OperationCanceledException + Catch dex As ObjectDisposedException + Catch ex As Exception + If Responser.StatusCode = Net.HttpStatusCode.NotFound Then + UserExists = False + Else + LogProvider.Add(ex, "[XVIDEOS.UserData.GetMedia]") + End If + Finally + If TempMediaList.ListExists Then TempMediaList.RemoveAll(Function(m) m.URL.IsEmptyString) + End Try + End Sub + Private Structure VSize : Implements IRegExCreator, IComparable(Of VSize) + Friend Size As Integer + Friend Value As String + Private Function CreateFromArray(ByVal ParamsArray() As String) As Object Implements IRegExCreator.CreateFromArray + If ParamsArray.ListExists(2) Then + Size = AConvert(Of Integer)(ParamsArray(0), 0) + Value = ParamsArray(1) + End If + Return Me + End Function + Private Function CompareTo(ByVal Other As VSize) As Integer Implements IComparable(Of VSize).CompareTo + Return Size.CompareTo(Other.Size) * -1 + End Function + End Structure + Friend Shared Function GetVideoData(ByVal URL As String, ByVal resp As Response, ByVal DownloadUHD As Boolean, + ByVal ID As String, ByRef Logger As ILogProvider) As PluginUserMedia + Try + If Not URL.IsEmptyString Then + Dim r$ = resp.GetResponse(URL,, EDP.ThrowException) + If Not r.IsEmptyString Then + Dim m$ = RegexReplace(r, M3U8Regex) + If Not m.IsEmptyString Then + Dim appender$ = RegexReplace(m, M3U8Appender) + Dim t$ = RegexReplace(r, VideoTitleRegex) + r = resp.GetResponse(m,, EDP.ThrowException) + If Not r.IsEmptyString Then + Dim ls As List(Of VSize) = FNF.RegexFields(Of VSize)(r, {M3U8Reparse}, {1, 2}) + If ls.ListExists And DownloadUHD Then ls.RemoveAll(Function(v) v.Size > 1080) + If ls.ListExists Then + ls.Sort() + m = $"{appender}/{ls(0).Value}" + ls.Clear() + Dim pID$ = ID + If pID.IsEmptyString Then pID = RegexReplace(r, VideoID) + If pID.IsEmptyString Then pID = "0" + + If Not t.IsEmptyString Then t = t.StringRemoveWinForbiddenSymbols(" ") + If t.IsEmptyString Then + t = pID + Else + If t.Length > 100 Then t = Left(t, 100) + End If + If Not m.IsEmptyString Then + Return New PluginUserMedia With { + .ContentType = PluginUserMedia.Types.m3u8, + .PostID = pID, + .URL = m, + .File = $"{t}.mp4", + .SpecialFolder = appender + } + End If + End If + End If + End If + End If + End If + Return Nothing + Catch ex As Exception + Logger.Add(ex, $"[XVIDEOS.UserData.GetVideoData({URL})]") + Return Nothing + End Try + End Function + Public Sub Download() Implements IPluginContentProvider.Download + Try + If TempMediaList.Count > 0 Then + RaiseEvent TotalCountChanged(TempMediaList.Count - 1) + Dim m As PluginUserMedia + Dim f As SFile + Dim DefPath As String = DataPath.CSFilePSN + For i% = 0 To TempMediaList.Count - 1 + Thrower.ThrowAny() + m = TempMediaList(i) + f = m.File + f.Path = DefPath + f = M3U8.Download(m.URL, m.SpecialFolder, Settings.FfmpegFile, f, LogProvider) + m.File = f + If Not f.IsEmptyString Then m.DownloadState = PluginUserMedia.States.Downloaded + TempMediaList(i) = m + RaiseEvent ProgressChanged(1) + Next + End If + Catch oex As OperationCanceledException + Catch dex As ObjectDisposedException + Catch ex As Exception + LogProvider.Add(ex, $"[XVIDEOS.UserData.Download]") + End Try + End Sub +#Region "IDisposable Support" + Private disposedValue As Boolean = False + Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean) + If Not disposedValue Then + If disposing Then + If Not Responser Is Nothing Then Responser.Dispose() + If TempMediaList.ListExists Then TempMediaList.Clear() + If TempPostsList.ListExists Then TempPostsList.Clear() + If ExistingContentList.ListExists Then ExistingContentList.Clear() + End If + disposedValue = True + End If + End Sub + Protected Overrides Sub Finalize() + Dispose(False) + MyBase.Finalize() + End Sub + Public Overloads Sub Dispose() Implements IDisposable.Dispose + Dispose(True) + GC.SuppressFinalize(Me) + End Sub +#End Region +End Class diff --git a/SCrawler.PluginProvider/Interfaces/IPluginContentProvider.vb b/SCrawler.PluginProvider/Interfaces/IPluginContentProvider.vb index 3b7d16b..6d9bfdb 100644 --- a/SCrawler.PluginProvider/Interfaces/IPluginContentProvider.vb +++ b/SCrawler.PluginProvider/Interfaces/IPluginContentProvider.vb @@ -7,7 +7,7 @@ ' This program is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY Namespace Plugin - Public Interface IPluginContentProvider + Public Interface IPluginContentProvider : Inherits IDisposable Event ProgressChanged(ByVal Count As Integer) Event TotalCountChanged(ByVal Count As Integer) Property Thrower As IThrower @@ -19,7 +19,7 @@ Namespace Plugin Property UserDescription As String Property ExistingContentList As List(Of PluginUserMedia) Property TempPostsList As List(Of String) - Property TempMediaList As List(Of IPluginUserMedia) + Property TempMediaList As List(Of PluginUserMedia) Property UserExists As Boolean Property UserSuspended As Boolean Property IsSavedPosts As Boolean diff --git a/SCrawler.PluginProvider/Interfaces/ISiteSettings.vb b/SCrawler.PluginProvider/Interfaces/ISiteSettings.vb index a8c683d..13bd746 100644 --- a/SCrawler.PluginProvider/Interfaces/ISiteSettings.vb +++ b/SCrawler.PluginProvider/Interfaces/ISiteSettings.vb @@ -17,10 +17,11 @@ Namespace Plugin ReadOnly Property Icon As Icon ReadOnly Property Image As Image ReadOnly Property Site As String + Property Logger As ILogProvider Function GetUserUrl(ByVal UserName As String, ByVal Channel As Boolean) As String Function IsMyUser(ByVal UserURL As String) As ExchangeOptions Function IsMyImageVideo(ByVal URL As String) As ExchangeOptions - Function GetSpecialData(ByVal URL As String) As IEnumerable(Of IPluginUserMedia) + Function GetSpecialData(ByVal URL As String, ByVal Path As String, ByVal AskForPath As Boolean) As IEnumerable(Of PluginUserMedia) Function GetInstance(ByVal What As Download) As IPluginContentProvider #Region "XML Support" Sub Load(ByVal XMLValues As IEnumerable(Of KeyValuePair(Of String, String))) diff --git a/SCrawler.PluginProvider/My Project/AssemblyInfo.vb b/SCrawler.PluginProvider/My Project/AssemblyInfo.vb index 4691607..2006370 100644 --- a/SCrawler.PluginProvider/My Project/AssemblyInfo.vb +++ b/SCrawler.PluginProvider/My Project/AssemblyInfo.vb @@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices ' by using the '*' as shown below: ' - - + + diff --git a/SCrawler.PluginProvider/ObjectInterfaces/IPluginUserMedia.vb b/SCrawler.PluginProvider/ObjectInterfaces/IPluginUserMedia.vb deleted file mode 100644 index 23954db..0000000 --- a/SCrawler.PluginProvider/ObjectInterfaces/IPluginUserMedia.vb +++ /dev/null @@ -1,40 +0,0 @@ -' 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 Plugin - Public Structure PluginUserMedia : Implements IPluginUserMedia - Public Property ContentType As Integer Implements IPluginUserMedia.ContentType - Public Property URL As String Implements IPluginUserMedia.URL - Public Property MD5 As String Implements IPluginUserMedia.MD5 - Public Property File As String Implements IPluginUserMedia.File - Public Property DownloadState As Integer Implements IPluginUserMedia.DownloadState - Public Property PostID As String Implements IPluginUserMedia.PostID - Public Property PostDate As Date? Implements IPluginUserMedia.PostDate - Public Property SpecialFolder As String Implements IPluginUserMedia.SpecialFolder - End Structure - Public Interface IPluginUserMedia - Enum Types As Integer - Undefined = 0 - [Picture] = 1 - [Video] = 2 - [Text] = 3 - VideoPre = 10 - GIF = 50 - m3u8 = 100 - End Enum - Enum States As Integer : Unknown = 0 : Tried = 1 : Downloaded = 2 : Skipped = 3 : End Enum - Property ContentType As Integer - Property URL As String - Property MD5 As String - Property File As String - Property DownloadState As Integer - Property PostID As String - Property PostDate As Date? - Property SpecialFolder As String - End Interface -End Namespace \ No newline at end of file diff --git a/SCrawler.PluginProvider/Objects/PluginUserMedia.vb b/SCrawler.PluginProvider/Objects/PluginUserMedia.vb new file mode 100644 index 0000000..1180bdc --- /dev/null +++ b/SCrawler.PluginProvider/Objects/PluginUserMedia.vb @@ -0,0 +1,30 @@ +' 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 Plugin + Public Structure PluginUserMedia + Enum Types As Integer + Undefined = 0 + [Picture] = 1 + [Video] = 2 + [Text] = 3 + VideoPre = 10 + GIF = 50 + m3u8 = 100 + End Enum + Enum States As Integer : Unknown = 0 : Tried = 1 : Downloaded = 2 : Skipped = 3 : End Enum + Public ContentType As Integer + Public URL As String + Public MD5 As String + Public File As String + Public DownloadState As Integer + Public PostID As String + Public PostDate As Date? + Public SpecialFolder As String + End Structure +End Namespace \ No newline at end of file diff --git a/SCrawler.PluginProvider/SCrawler.PluginProvider.vbproj b/SCrawler.PluginProvider/SCrawler.PluginProvider.vbproj index c1cd504..3bd708f 100644 --- a/SCrawler.PluginProvider/SCrawler.PluginProvider.vbproj +++ b/SCrawler.PluginProvider/SCrawler.PluginProvider.vbproj @@ -105,7 +105,7 @@ - + diff --git a/SCrawler.sln b/SCrawler.sln index 4b07324..0123c75 100644 --- a/SCrawler.sln +++ b/SCrawler.sln @@ -17,6 +17,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "SCrawler.PluginProvider", "SCrawler.PluginProvider\SCrawler.PluginProvider.vbproj", "{D4650F6B-5A54-44B6-999B-6C675B7116B1}" EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "SCrawler.Plugin.LPSG", "SCrawler.Plugin.LPSG\SCrawler.Plugin.LPSG.vbproj", "{22A130B2-DDF4-4FB5-BA38-E5DB4CF1B8A2}" +EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "SCrawler.Plugin.XVIDEOS", "SCrawler.Plugin.XVIDEOS\SCrawler.Plugin.XVIDEOS.vbproj", "{CCCF47F4-C97C-4193-AC4B-C56DF2F9AA8A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -63,6 +67,30 @@ Global {D4650F6B-5A54-44B6-999B-6C675B7116B1}.Release|x64.Build.0 = Release|x64 {D4650F6B-5A54-44B6-999B-6C675B7116B1}.Release|x86.ActiveCfg = Release|x86 {D4650F6B-5A54-44B6-999B-6C675B7116B1}.Release|x86.Build.0 = Release|x86 + {22A130B2-DDF4-4FB5-BA38-E5DB4CF1B8A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22A130B2-DDF4-4FB5-BA38-E5DB4CF1B8A2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22A130B2-DDF4-4FB5-BA38-E5DB4CF1B8A2}.Debug|x64.ActiveCfg = Debug|x64 + {22A130B2-DDF4-4FB5-BA38-E5DB4CF1B8A2}.Debug|x64.Build.0 = Debug|x64 + {22A130B2-DDF4-4FB5-BA38-E5DB4CF1B8A2}.Debug|x86.ActiveCfg = Debug|x86 + {22A130B2-DDF4-4FB5-BA38-E5DB4CF1B8A2}.Debug|x86.Build.0 = Debug|x86 + {22A130B2-DDF4-4FB5-BA38-E5DB4CF1B8A2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {22A130B2-DDF4-4FB5-BA38-E5DB4CF1B8A2}.Release|Any CPU.Build.0 = Release|Any CPU + {22A130B2-DDF4-4FB5-BA38-E5DB4CF1B8A2}.Release|x64.ActiveCfg = Release|x64 + {22A130B2-DDF4-4FB5-BA38-E5DB4CF1B8A2}.Release|x64.Build.0 = Release|x64 + {22A130B2-DDF4-4FB5-BA38-E5DB4CF1B8A2}.Release|x86.ActiveCfg = Release|x86 + {22A130B2-DDF4-4FB5-BA38-E5DB4CF1B8A2}.Release|x86.Build.0 = Release|x86 + {CCCF47F4-C97C-4193-AC4B-C56DF2F9AA8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CCCF47F4-C97C-4193-AC4B-C56DF2F9AA8A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CCCF47F4-C97C-4193-AC4B-C56DF2F9AA8A}.Debug|x64.ActiveCfg = Debug|x64 + {CCCF47F4-C97C-4193-AC4B-C56DF2F9AA8A}.Debug|x64.Build.0 = Debug|x64 + {CCCF47F4-C97C-4193-AC4B-C56DF2F9AA8A}.Debug|x86.ActiveCfg = Debug|x86 + {CCCF47F4-C97C-4193-AC4B-C56DF2F9AA8A}.Debug|x86.Build.0 = Debug|x86 + {CCCF47F4-C97C-4193-AC4B-C56DF2F9AA8A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CCCF47F4-C97C-4193-AC4B-C56DF2F9AA8A}.Release|Any CPU.Build.0 = Release|Any CPU + {CCCF47F4-C97C-4193-AC4B-C56DF2F9AA8A}.Release|x64.ActiveCfg = Release|x64 + {CCCF47F4-C97C-4193-AC4B-C56DF2F9AA8A}.Release|x64.Build.0 = Release|x64 + {CCCF47F4-C97C-4193-AC4B-C56DF2F9AA8A}.Release|x86.ActiveCfg = Release|x86 + {CCCF47F4-C97C-4193-AC4B-C56DF2F9AA8A}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/SCrawler/API/Base/SiteSettingsBase.vb b/SCrawler/API/Base/SiteSettingsBase.vb index 3b91eb1..e114333 100644 --- a/SCrawler/API/Base/SiteSettingsBase.vb +++ b/SCrawler/API/Base/SiteSettingsBase.vb @@ -11,11 +11,12 @@ Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Tools.WEB Imports Download = SCrawler.Plugin.ISiteSettings.Download Namespace API.Base - Friend MustInherit Class SiteSettingsBase : Implements ISiteSettings, IResponserContainer + Friend MustInherit Class SiteSettingsBase : Implements ISiteSettings Friend ReadOnly Property Site As String Implements ISiteSettings.Site Friend Overridable ReadOnly Property Icon As Icon = Nothing Implements ISiteSettings.Icon Friend Overridable ReadOnly Property Image As Image = Nothing Implements ISiteSettings.Image - Friend Overridable ReadOnly Property Responser As Response Implements IResponserContainer.Responser + Private Property Logger As ILogProvider = LogConnector Implements ISiteSettings.Logger + Friend Overridable ReadOnly Property Responser As Response Friend MustOverride Function GetInstance(ByVal What As Download) As IPluginContentProvider Implements ISiteSettings.GetInstance Friend Sub New(ByVal SiteName As String) Site = SiteName @@ -82,7 +83,7 @@ Namespace API.Base Return Nothing End If End Function - Friend Overridable Function GetSpecialData(ByVal URL As String) As IEnumerable(Of IPluginUserMedia) Implements ISiteSettings.GetSpecialData + Friend Overridable Function GetSpecialData(ByVal URL As String, ByVal Path As String, ByVal AskForPath As Boolean) As IEnumerable(Of PluginUserMedia) Implements ISiteSettings.GetSpecialData Return Nothing End Function Friend Overridable Function GetSpecialDataF(ByVal URL As String) As IEnumerable(Of UserMedia) diff --git a/SCrawler/API/Base/Structures.vb b/SCrawler/API/Base/Structures.vb index eaba86a..eb1d131 100644 --- a/SCrawler/API/Base/Structures.vb +++ b/SCrawler/API/Base/Structures.vb @@ -42,7 +42,7 @@ Namespace API.Base Me.New(_URL) [Type] = _Type End Sub - Friend Sub New(ByVal m As Plugin.IPluginUserMedia) + Friend Sub New(ByVal m As Plugin.PluginUserMedia) If Not IsNothing(m) Then [Type] = m.ContentType URL = m.URL diff --git a/SCrawler/API/Base/UserDataBase.vb b/SCrawler/API/Base/UserDataBase.vb index 1f3efae..8c02fb6 100644 --- a/SCrawler/API/Base/UserDataBase.vb +++ b/SCrawler/API/Base/UserDataBase.vb @@ -9,6 +9,7 @@ Imports PersonalUtilities.Functions.XML Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Forms.Toolbars +Imports PersonalUtilities.Tools.WEB Imports System.IO Imports System.Net Imports System.Threading @@ -421,7 +422,7 @@ BlockNullPicture: Friend Property ExternalPlugin As IPluginContentProvider Private Property IPluginContentProvider_ExistingContentList As List(Of PluginUserMedia) Implements IPluginContentProvider.ExistingContentList Private Property IPluginContentProvider_TempPostsList As List(Of String) Implements IPluginContentProvider.TempPostsList - Private Property IPluginContentProvider_TempMediaList As List(Of IPluginUserMedia) Implements IPluginContentProvider.TempMediaList + Private Property IPluginContentProvider_TempMediaList As List(Of PluginUserMedia) Implements IPluginContentProvider.TempMediaList Private Property IPluginContentProvider_SeparateVideoFolder As Boolean Implements IPluginContentProvider.SeparateVideoFolder Private Property IPluginContentProvider_DataPath As String Implements IPluginContentProvider.DataPath Private Sub IPluginContentProvider_XmlFieldsSet(ByVal Fields As List(Of KeyValuePair(Of String, String))) Implements IPluginContentProvider.XmlFieldsSet @@ -712,7 +713,7 @@ BlockNullPicture: #Region "Download functions and options" Friend Overridable Property DownloadTopCount As Integer? = Nothing Implements IUserData.DownloadTopCount, IPluginContentProvider.PostsNumberLimit Friend Overridable Property DownloadToDate As Date? = Nothing Implements IUserData.DownloadToDate, IPluginContentProvider.PostsDateLimit - Protected Responser As PersonalUtilities.Tools.WEB.Response + Protected Responser As Response Friend Overridable Sub DownloadData(ByVal Token As CancellationToken) Implements IContentProvider.DownloadData Dim Canceled As Boolean = False _ExternalCompatibilityToken = Token @@ -720,12 +721,8 @@ BlockNullPicture: UpdateDataFiles() UserDescriptionReset() If Not Responser Is Nothing Then Responser.Dispose() - Responser = New PersonalUtilities.Tools.WEB.Response - If TypeOf HOST.Source Is IResponserContainer Then - With DirectCast(HOST.Source, IResponserContainer) - If Not .Responser Is Nothing Then Responser.Copy(.Responser) - End With - End If + Responser = New Response + If Not HOST.Responser Is Nothing Then Responser.Copy(HOST.Responser) Dim UpPic As Boolean = Settings.ViewModeIsPicture AndAlso GetPicture(False) Is Nothing Dim sEnvir() As Boolean = {UserExists, UserSuspended} diff --git a/SCrawler/API/Instagram/UserData.vb b/SCrawler/API/Instagram/UserData.vb index 75f1ce6..d9e0fad 100644 --- a/SCrawler/API/Instagram/UserData.vb +++ b/SCrawler/API/Instagram/UserData.vb @@ -260,7 +260,7 @@ Namespace API.Instagram If Not TaggedChecked Then TaggedCount = j.Value("total_count").FromXML(Of Integer)(0) TaggedChecked = True - If TaggedChecked > 200 Then + If TaggedCount > 200 Then Dim a% = MsgBoxE({$"The number of tagged posts is {TaggedCount.NumToString(New ANumbers With { .FormatOptions = ANumbers.Options.GroupIntegral})}" & vbCr & "The tagged data download operation can take a long time.", "Too much tagged data"}, vbExclamation,,, diff --git a/SCrawler/Editors/SiteEditorForm.vb b/SCrawler/Editors/SiteEditorForm.vb index 87c205f..721b1d2 100644 --- a/SCrawler/Editors/SiteEditorForm.vb +++ b/SCrawler/Editors/SiteEditorForm.vb @@ -19,7 +19,7 @@ Namespace Editors Private ReadOnly LBL_AUTH As Label Private ReadOnly LBL_OTHER As Label Private ReadOnly MyDefs As DefaultFormProps(Of FieldsChecker) - Private SpecialButton As Button + Private WithEvents SpecialButton As Button #Region "Providers" Private Class SavedPostsChecker : Implements ICustomProvider Private Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider, @@ -70,24 +70,27 @@ Namespace Editors .AddControl(Of String)(TXT_PATH_SAVED_POSTS, TXT_PATH_SAVED_POSTS.CaptionText, True, New SavedPostsChecker) End With + Dim offset% = PropertyValueHost.LeftOffsetDefault + Dim h% = 0, c% = 0 + Dim AddTpControl As Action(Of Control, Integer) = Sub(ByVal cnt As Control, ByVal _height As Integer) + TP_SITE_PROPS.RowStyles.Add(New RowStyle(SizeType.Absolute, _height)) + TP_SITE_PROPS.RowCount += 1 + TP_SITE_PROPS.Controls.Add(cnt, 0, TP_SITE_PROPS.RowStyles.Count - 1) + h += _height + c += 1 + End Sub + + If Host.Responser Is Nothing Then + h -= 28 + TXT_COOKIES.Enabled = False + TXT_COOKIES.Visible = False + TP_MAIN.RowStyles(2).Height = 0 + End If + + If .PropList.Count > 0 Then - Dim offset% = PropertyValueHost.LeftOffsetDefault - Dim h% = 0, c% = 0 Dim laAdded As Boolean = False Dim loAdded As Boolean = False - If Not Host.IsMyClass Then - h -= 28 - TXT_COOKIES.Enabled = False - TXT_COOKIES.Visible = False - TP_MAIN.RowStyles(2).Height = 0 - End If - Dim AddTpControl As Action(Of Control, Integer) = Sub(ByVal cnt As Control, ByVal _height As Integer) - TP_SITE_PROPS.RowStyles.Add(New RowStyle(SizeType.Absolute, _height)) - TP_SITE_PROPS.RowCount += 1 - TP_SITE_PROPS.Controls.Add(cnt, 0, TP_SITE_PROPS.RowStyles.Count - 1) - h += _height - c += 1 - End Sub Dim pArr() As Boolean If .PropList.Exists(Function(p) If(p.Options?.IsAuth, False)) Then pArr = {True, False} Else pArr = {False} .PropList.Sort() @@ -117,20 +120,21 @@ Namespace Editors End If Next Next - SpecialButton = .GetSettingsButtonInternal - If Not SpecialButton Is Nothing Then AddTpControl(SpecialButton, 28) - TP_SITE_PROPS.BaseControlsPadding = New Padding(offset, 0, 0, 0) - offset += PaddingE.GetOf({TP_SITE_PROPS}).Left - TXT_PATH.CaptionWidth = offset - TXT_PATH_SAVED_POSTS.CaptionWidth = offset - TXT_COOKIES.CaptionWidth = offset - CH_GET_USER_MEDIA_ONLY.Padding = New PaddingE(CH_GET_USER_MEDIA_ONLY.Padding) With {.Left = offset} - If c > 0 Or Not Host.IsMyClass Then - Dim ss As New Size(Size.Width, Size.Height + h + c) - MinimumSize = ss - Size = ss - MaximumSize = ss - End If + End If + + SpecialButton = .GetSettingsButtonInternal + If Not SpecialButton Is Nothing Then AddTpControl(SpecialButton, 28) + TP_SITE_PROPS.BaseControlsPadding = New Padding(offset, 0, 0, 0) + offset += PaddingE.GetOf({TP_SITE_PROPS}).Left + TXT_PATH.CaptionWidth = offset + TXT_PATH_SAVED_POSTS.CaptionWidth = offset + TXT_COOKIES.CaptionWidth = offset + CH_GET_USER_MEDIA_ONLY.Padding = New PaddingE(CH_GET_USER_MEDIA_ONLY.Padding) With {.Left = offset} + If c > 0 Or Not Host.IsMyClass Then + Dim ss As New Size(Size.Width, Size.Height + h + c) + MinimumSize = ss + Size = ss + MaximumSize = ss End If End With @@ -208,8 +212,8 @@ Namespace Editors End Sub Private Sub TXT_COOKIES_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_COOKIES.ActionOnButtonClick If Sender.DefaultButton = ActionButton.DefaultButtons.Edit Then - If TypeOf Host.Source Is IResponserContainer Then - Using f As New CookieListForm(DirectCast(Host.Source, IResponserContainer).Responser) With { + If Not Host.Responser Is Nothing Then + Using f As New CookieListForm(Host.Responser) With { .MyDesignXML = Settings.Design, .DisableControls = CookieControl.AddFromInternal + CookieControl.AuthorizeProgram + CookieControl.OpenBrowser } @@ -220,8 +224,8 @@ Namespace Editors End If End Sub Private Sub TXT_COOKIES_ActionOnButtonClearClick() Handles TXT_COOKIES.ActionOnButtonClearClick - If TypeOf Host.Source Is IResponserContainer Then - With DirectCast(Host.Source, IResponserContainer).Responser + If Not Host.Responser Is Nothing Then + With Host.Responser If Not .Cookies Is Nothing Then .Cookies.Dispose() .Cookies = New CookieKeeper(.CookiesDomain) End With @@ -229,8 +233,10 @@ Namespace Editors End If End Sub Private Sub SetCookieText() - If TypeOf Host.Source Is IResponserContainer Then _ - TXT_COOKIES.Text = $"{If(DirectCast(Host.Source, IResponserContainer).Responser.Cookies?.Count, 0)} cookies" + If Not Host.Responser Is Nothing Then TXT_COOKIES.Text = $"{If(Host.Responser.Cookies?.Count, 0)} cookies" + End Sub + Private Sub SpecialButton_Click(sender As Object, e As EventArgs) Handles SpecialButton.Click + MyDefs.Detector() End Sub End Class End Namespace \ No newline at end of file diff --git a/SCrawler/MainMod.vb b/SCrawler/MainMod.vb index f79c2b9..4328942 100644 --- a/SCrawler/MainMod.vb +++ b/SCrawler/MainMod.vb @@ -292,8 +292,13 @@ Friend Module MainMod For Each p As PluginHost In Settings.Plugins d = p.Settings.IsMyImageVideo(URL) If d.Exists Then - um = Settings(d.HostKey).GetSpecialData(URL) + um = Settings(d.HostKey).GetSpecialData(URL, Settings.LatestSavingPath.Value, AskForPath) found = True + If um.ListExists Then + If AskForPath And Not um(0).SpecialFolder.IsEmptyString And Not p.Settings.IsMyClass Then _ + Settings.LatestSavingPath.Value = um(0).SpecialFolder + If um(0).State = UserMedia.States.Downloaded Then Return True + End If Exit For End If Next diff --git a/SCrawler/My Project/AssemblyInfo.vb b/SCrawler/My Project/AssemblyInfo.vb index 9ad03e5..7b865be 100644 --- a/SCrawler/My Project/AssemblyInfo.vb +++ b/SCrawler/My Project/AssemblyInfo.vb @@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices ' by using the '*' as shown below: ' - - + + diff --git a/SCrawler/PluginsEnvironment/Hosts/IResponserContainer.vb b/SCrawler/PluginsEnvironment/Hosts/IResponserContainer.vb deleted file mode 100644 index 7ee1feb..0000000 --- a/SCrawler/PluginsEnvironment/Hosts/IResponserContainer.vb +++ /dev/null @@ -1,13 +0,0 @@ -' 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 Plugin - Friend Interface IResponserContainer - ReadOnly Property Responser As PersonalUtilities.Tools.WEB.Response - End Interface -End Namespace \ No newline at end of file diff --git a/SCrawler/PluginsEnvironment/Hosts/SettingsHost.vb b/SCrawler/PluginsEnvironment/Hosts/SettingsHost.vb index 84dc48a..022ad31 100644 --- a/SCrawler/PluginsEnvironment/Hosts/SettingsHost.vb +++ b/SCrawler/PluginsEnvironment/Hosts/SettingsHost.vb @@ -11,6 +11,7 @@ Imports SCrawler.API.Base Imports SCrawler.Plugin.Attributes Imports PersonalUtilities.Functions.XML Imports PersonalUtilities.Functions.XML.Base +Imports PersonalUtilities.Tools.WEB Imports Download = SCrawler.Plugin.ISiteSettings.Download Namespace Plugin.Hosts Friend Class SettingsHost @@ -25,7 +26,7 @@ Namespace Plugin.Hosts End Function Friend Function GetSettingsButtonInternal() As Button If Not SpecialFormAttribute Is Nothing AndAlso SpecialFormAttribute.SettingsForm Then - BTT_SETTINGS_INTERNAL = New Button With {.Text = "Other settings", .Dock = DockStyle.Right} + BTT_SETTINGS_INTERNAL = New Button With {.Text = "Other settings", .Dock = DockStyle.Right, .Width = 150} Return BTT_SETTINGS_INTERNAL Else Return Nothing @@ -77,6 +78,16 @@ Namespace Plugin.Hosts End Get End Property Friend ReadOnly Property HasSpecialOptions As Boolean = False + Private ReadOnly _ResponserGetMethod As MethodInfo + Friend ReadOnly Property Responser As Response + Get + If Not _ResponserGetMethod Is Nothing Then + Return _ResponserGetMethod.Invoke(Source, Nothing) + Else + Return Nothing + End If + End Get + End Property #End Region #Region "Base properties compatibility" Friend ReadOnly Property Temporary As XMLValue(Of Boolean) @@ -128,6 +139,7 @@ Namespace Plugin.Hosts Friend Sub New(ByVal Plugin As ISiteSettings, ByRef _XML As XmlFile, ByVal GlobalPath As SFile, ByRef _Temp As XMLValue(Of Boolean), ByRef _Imgs As XMLValue(Of Boolean), ByRef _Vids As XMLValue(Of Boolean)) Source = Plugin + Source.Logger = LogConnector PropList = New List(Of PropertyValueHost) @@ -162,7 +174,7 @@ Namespace Plugin.Hosts Source.BeginInit() Dim n() As String = {SettingsCLS.Name_Node_Sites, Name} - If If(_XML(n)?.Count, 0) > 0 Then Source.Load(_XML(n).ToKeyValuePair) + If If(_XML(n)?.Count, 0) > 0 Then Source.Load(ToKeyValuePair(Of String, EContainer)(_XML(n))) Dim Members As IEnumerable(Of MemberInfo) = Plugin.GetType.GetTypeInfo.DeclaredMembers If Members.ListExists Then Dim Updaters As New List(Of MemberInfo) @@ -170,7 +182,12 @@ Namespace Plugin.Hosts Dim PropCheckers As New List(Of MemberInfo) Dim m As MemberInfo For Each m In Members - If m.MemberType = MemberTypes.Property Then PropList.Add(New PropertyValueHost(Source, m)) + If m.MemberType = MemberTypes.Property Then + PropList.Add(New PropertyValueHost(Source, m)) + With DirectCast(m, PropertyInfo) + If .PropertyType Is GetType(Response) Then _ResponserGetMethod = .GetMethod + End With + End If With m.GetCustomAttributes() If .ListExists Then If m.MemberType = MemberTypes.Method Then @@ -265,14 +282,14 @@ Namespace Plugin.Hosts If s.Exists Then s.SiteName = Name : s.HostKey = Key Return s End Function - Friend Function GetSpecialData(ByVal URL As String) As IEnumerable(Of UserMedia) + Friend Function GetSpecialData(ByVal URL As String, ByVal Path As SFile, ByVal AskForPath As Boolean) As IEnumerable(Of UserMedia) If IsMyClass Then Return DirectCast(Source, SiteSettingsBase).GetSpecialDataF(URL) Else - Dim um As IEnumerable(Of IPluginUserMedia) = Source.GetSpecialData(URL) + Dim um As IEnumerable(Of PluginUserMedia) = Source.GetSpecialData(URL, Path, AskForPath) If um.ListExists Then Dim u As New List(Of UserMedia) - For Each d As IPluginUserMedia In um : u.Add(New UserMedia(d)) : Next + For Each d As PluginUserMedia In um : u.Add(New UserMedia(d)) : Next Return u End If Return Nothing diff --git a/SCrawler/PluginsEnvironment/Hosts/UserDataHost.vb b/SCrawler/PluginsEnvironment/Hosts/UserDataHost.vb index d17a1e4..7e14812 100644 --- a/SCrawler/PluginsEnvironment/Hosts/UserDataHost.vb +++ b/SCrawler/PluginsEnvironment/Hosts/UserDataHost.vb @@ -27,7 +27,7 @@ Namespace Plugin.Hosts End Sub Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean) If Loading Then - ExternalPlugin.XmlFieldsSet(Container.ToKeyValuePair) + ExternalPlugin.XmlFieldsSet(ToKeyValuePair(Of String, EContainer)(Container)) Else Dim fl As List(Of KeyValuePair(Of String, String)) = ExternalPlugin.XmlFieldsGet If fl.ListExists Then @@ -53,11 +53,16 @@ Namespace Plugin.Hosts .PostsNumberLimit = DownloadTopCount .PostsDateLimit = DownloadToDate + .ExistingContentList = New List(Of PluginUserMedia) + .TempMediaList = New List(Of PluginUserMedia) + .TempPostsList = New List(Of String) + If _ContentList.Count > 0 Then ExternalPlugin.ExistingContentList = _ContentList.Select(Function(u) u.PluginUserMedia).ToList ExternalPlugin.TempPostsList = ListAddList(Nothing, _TempPostsList) .GetMedia() + _TempPostsList.ListAddList(.TempPostsList, LNC) If .TempMediaList.ListExists Then _TempMediaList.ListAddList(.TempMediaList.Select(Function(tm) New UserMedia(tm)), LNC) If Not .Name = Name Then Name = .Name @@ -70,7 +75,18 @@ Namespace Plugin.Hosts Protected Overrides Sub ReparseVideo(ByVal Token As CancellationToken) End Sub Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken) - If UseInternalDownloader Then DownloadContentDefault(Token) Else ExternalPlugin.Download() + If UseInternalDownloader Then + DownloadContentDefault(Token) + Else + With ExternalPlugin + If .TempMediaList.ListExists Then .TempMediaList.Clear() + .TempMediaList = New List(Of PluginUserMedia) + .TempMediaList.ListAddList(_ContentNew.Select(Function(c) c.PluginUserMedia())) + .Download() + _ContentNew.Clear() + If .TempMediaList.ListExists Then _ContentNew.ListAddList(.TempMediaList.Select(Function(c) New UserMedia(c))) + End With + End If End Sub Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False) As Integer LogError(ex, Message) @@ -83,5 +99,16 @@ Namespace Plugin.Hosts Private Sub ExternalPlugin_TotalCountChanged(ByVal Count As Integer) Progress.TotalCount += Count End Sub + Protected Overrides Sub Dispose(ByVal disposing As Boolean) + If disposing And Not disposedValue Then + With ExternalPlugin + If .ExistingContentList.ListExists Then .ExistingContentList.Clear() + If .TempMediaList.ListExists Then .TempMediaList.Clear() + If .TempPostsList.ListExists Then .TempPostsList.Clear() + .Dispose() + End With + End If + MyBase.Dispose(disposing) + End Sub End Class End Namespace \ No newline at end of file diff --git a/SCrawler/SCrawler.vbproj b/SCrawler/SCrawler.vbproj index cf7e04a..c79aff9 100644 --- a/SCrawler/SCrawler.vbproj +++ b/SCrawler/SCrawler.vbproj @@ -271,7 +271,6 @@ True -