Initial commit

This commit is contained in:
Andy
2021-12-07 09:52:01 +03:00
commit 1791b24f37
82 changed files with 14931 additions and 0 deletions

2
.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

392
.gitignore vendored Normal file
View File

@@ -0,0 +1,392 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
ffmpeg.exe
ToDo.txt
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
ffmpeg/
Info/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Nuget personal access tokens and Credentials
nuget.config
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
.idea/
*.sln.iml

57
README.md Normal file
View File

@@ -0,0 +1,57 @@
# Social networks crawler
Program for downloading photo and video from Reddit and Twitter
Enjoying the tool? Considering adding to my coffee fund :)
[![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/andyprogram)
# What can program do:
- Download pictures and videos from users' profiles:
- Reddit images;
- Reddit galleries of images;
- Redgifs hosted videos (https://www.redgifs.com/);
- Reddit hosted videos (downloading Reddit hosted video is going through ffmpeg);
- Twitter images;
- Twitter videos.
- Parse channel and view data.
- Add users from parsed channel.
- Labeling users.
- Filter exists users by label or group.
# How does it works:
## Reddit
The program parsing all user's posts, gathering pictures' MD5 hash and compare with existing for remove duplicates. Then media will be downloaded.
## Twitter
The program parsing all user's posts and compare file names with existing for remove duplicates. Then media will be downloaded.
# Requirements:
- Windows 7, 8, 9, 10, 11 with NET Framework 4.6.1 or higher
- Authorization cookies and tokens for Twitter (if you want to download data from Twitter)
- Don't put program in the ```Program Files``` system folder (this is portable program and program settings are stored in the program folder)
- Just unpack program archive in any folder you want, copy ```ffmpeg.exe``` into and enjoy. :-)
# Settings and usage
The program has an intuitive interface.
Just add user profile and press ```Start downloading``` button.
Users can be added by patterns:
- https://twitter.com/SomeUserName
- https://reddit.com/user/SomeUserName
- u/SomeUserName
- SomeUserName (in this case you must to choose user site)
More about users adding here
## Using program as just video downloader
Create a shortcut for the program. Open shortcut properties. On the ```Shortcut``` tab in ```Target``` field just add ```v``` at the end through the space.
Example: ```D:\Programs\SCrawler\SCrawler.exe v```

60
SCrawler.sln Normal file
View File

@@ -0,0 +1,60 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31515.178
MinimumVisualStudioVersion = 10.0.40219.1
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "SCrawler", "SCrawler\SCrawler.vbproj", "{4A016FAD-9F07-4957-8BB2-AE86C88BA342}"
EndProject
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "PersonalUtilities", "..\..\MyUtilities\PersonalUtilities\PersonalUtilities.vbproj", "{8405896B-2685-4916-BC93-1FB514C323A9}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{FE5CE5B9-DDBE-4399-A17C-880893635307}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
README.md = README.md
Info\RedditUrlsInfo.txt = Info\RedditUrlsInfo.txt
Info\TwitterNewAlgo.txt = Info\TwitterNewAlgo.txt
Info\TwitterUrlsInfo.txt = Info\TwitterUrlsInfo.txt
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4A016FAD-9F07-4957-8BB2-AE86C88BA342}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A016FAD-9F07-4957-8BB2-AE86C88BA342}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A016FAD-9F07-4957-8BB2-AE86C88BA342}.Debug|x64.ActiveCfg = Debug|x64
{4A016FAD-9F07-4957-8BB2-AE86C88BA342}.Debug|x64.Build.0 = Debug|x64
{4A016FAD-9F07-4957-8BB2-AE86C88BA342}.Debug|x86.ActiveCfg = Debug|x86
{4A016FAD-9F07-4957-8BB2-AE86C88BA342}.Debug|x86.Build.0 = Debug|x86
{4A016FAD-9F07-4957-8BB2-AE86C88BA342}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4A016FAD-9F07-4957-8BB2-AE86C88BA342}.Release|Any CPU.Build.0 = Release|Any CPU
{4A016FAD-9F07-4957-8BB2-AE86C88BA342}.Release|x64.ActiveCfg = Release|x64
{4A016FAD-9F07-4957-8BB2-AE86C88BA342}.Release|x64.Build.0 = Release|x64
{4A016FAD-9F07-4957-8BB2-AE86C88BA342}.Release|x86.ActiveCfg = Release|x86
{4A016FAD-9F07-4957-8BB2-AE86C88BA342}.Release|x86.Build.0 = Release|x86
{8405896B-2685-4916-BC93-1FB514C323A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8405896B-2685-4916-BC93-1FB514C323A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8405896B-2685-4916-BC93-1FB514C323A9}.Debug|x64.ActiveCfg = Debug|x64
{8405896B-2685-4916-BC93-1FB514C323A9}.Debug|x64.Build.0 = Debug|x64
{8405896B-2685-4916-BC93-1FB514C323A9}.Debug|x86.ActiveCfg = Debug|x86
{8405896B-2685-4916-BC93-1FB514C323A9}.Debug|x86.Build.0 = Debug|x86
{8405896B-2685-4916-BC93-1FB514C323A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8405896B-2685-4916-BC93-1FB514C323A9}.Release|Any CPU.Build.0 = Release|Any CPU
{8405896B-2685-4916-BC93-1FB514C323A9}.Release|x64.ActiveCfg = Release|x64
{8405896B-2685-4916-BC93-1FB514C323A9}.Release|x64.Build.0 = Release|x64
{8405896B-2685-4916-BC93-1FB514C323A9}.Release|x86.ActiveCfg = Release|x86
{8405896B-2685-4916-BC93-1FB514C323A9}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4037B243-B6D7-4DF1-A4CC-4E86F4AD31BB}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,78 @@
Imports PersonalUtilities.Tools
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.XML.Base
Namespace API.Base
Friend Class SiteSettings : Implements IDisposable
Friend Const Header_Twitter_Authorization As String = "authorization"
Friend Const Header_Twitter_Token As String = "x-csrf-token"
Friend ReadOnly Site As Sites
Friend ReadOnly Responser As WEB.Response
Private ReadOnly _Path As XMLValue(Of SFile)
Friend Property Path As SFile
Get
If _Path.IsEmptyString Then _Path.Value = SFile.GetPath($"{Settings.GlobalPath.Value.PathWithSeparator}{Site}")
Return _Path.Value
End Get
Set(ByVal NewFile As SFile)
_Path.Value = NewFile
End Set
End Property
Private ReadOnly SettingsFile As SFile
Friend Sub New(ByVal s As Sites, ByRef _XML As XmlFile, ByVal GlobalPath As SFile)
Site = s
SettingsFile = $"{SettingsFolderName}\Responser_{s}.xml"
Responser = New WEB.Response(SettingsFile)
If SettingsFile.Exists Then
Responser.LoadSettings()
Else
If Site = Sites.Twitter Then
With Responser
.ContentType = "application/json"
.Accept = "*/*"
.CookiesDomain = "twitter.com"
.Decoders.Add(SymbolsConverter.Converters.Unicode)
With .Headers
.Add("sec-ch-ua", " Not;A Brand" & Chr(34) & ";v=" & Chr(34) & "99" & Chr(34) & ", " & Chr(34) &
"Google Chrome" & Chr(34) & ";v=" & Chr(34) & "91" & Chr(34) & ", " & Chr(34) & "Chromium" &
Chr(34) & ";v=" & Chr(34) & "91" & Chr(34))
.Add("sec-ch-ua-mobile", "?0")
.Add("sec-fetch-dest", "empty")
.Add("sec-fetch-mode", "cors")
.Add("sec-fetch-site", "same-origin")
.Add(Header_Twitter_Token, String.Empty)
.Add("x-twitter-active-user", "yes")
.Add("x-twitter-auth-type", "OAuth2Session")
.Add(Header_Twitter_Authorization, String.Empty)
End With
End With
ElseIf Site = Sites.Reddit Then
Responser.CookiesDomain = "reddit.com"
Responser.Decoders.Add(SymbolsConverter.Converters.Unicode)
End If
Responser.SaveSettings()
End If
_Path = New XMLValue(Of SFile)("Path", SFile.GetPath($"{GlobalPath.PathWithSeparator}{Site}"), _XML, {Site.ToString}, XMLValue(Of SFile).ToFilePath)
End Sub
Friend Sub Update()
Responser.SaveSettings()
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 Responser.Dispose()
disposedValue = True
End If
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub
Friend Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
End Namespace

View File

@@ -0,0 +1,81 @@
Namespace API.Base
Friend Module Structures
Friend Structure UserMedia : Implements IEquatable(Of UserMedia)
Friend Enum Types As Integer
Undefined = 0
[Picture] = 1
[Video] = 2
[Text] = 3
VideoPre = 10
GIF = 50
m3u8 = 100
End Enum
Friend Enum States : Unknown : Tried : Downloaded : Skipped : End Enum
Friend Type As Types
Friend URL_BASE As String
Friend URL As String
Friend MD5 As String
Friend [File] As SFile
Friend Post As UserPost
Friend PictureOption As String
Friend State As States
Friend Sub New(ByVal _URL As String)
URL = _URL
URL_BASE = _URL
File = URL
Type = Types.Undefined
End Sub
Friend Sub New(ByVal _URL As String, ByVal _Type As Types)
Me.New(_URL)
Type = _Type
End Sub
Public Shared Widening Operator CType(ByVal _URL As String) As UserMedia
Return New UserMedia(_URL)
End Operator
Public Shared Widening Operator CType(ByVal m As UserMedia) As String
Return m.URL
End Operator
Public Overrides Function ToString() As String
Return URL
End Function
Friend Overloads Function Equals(ByVal Other As UserMedia) As Boolean Implements IEquatable(Of UserMedia).Equals
Return URL = Other.URL
End Function
Public Overrides Function Equals(ByVal Obj As Object) As Boolean
Return Equals(CType(Obj, UserMedia))
End Function
End Structure
Friend Structure UserPost : Implements IEquatable(Of UserPost), IComparable(Of UserPost)
''' <summary>Post ID</summary>
Friend ID As String
Friend [Date] As Date?
#Region "Channel compatible fields"
Friend UserID As String
Friend CachedFile As SFile
#End Region
Friend Function GetImage(ByVal s As Size, ByVal e As ErrorsDescriber, ByVal NullArg As Image) As Image
If Not CachedFile.IsEmptyString Then
Return If(PersonalUtilities.Tools.ImageRenderer.GetImage(SFile.GetBytes(CachedFile), s, e), NullArg.Clone)
Else
Return NullArg.Clone
End If
End Function
#Region "IEquatable, IComparable Support"
Friend Overloads Function Equals(ByVal Other As UserPost) As Boolean Implements IEquatable(Of UserPost).Equals
Return ID = Other.ID
End Function
Public Overloads Overrides Function Equals(ByVal Obj As Object) As Boolean
Return Equals(DirectCast(Obj, UserPost))
End Function
Friend Function CompareTo(ByVal Other As UserPost) As Integer Implements IComparable(Of UserPost).CompareTo
Return GetCompareValue(Me).CompareTo(GetCompareValue(Other))
End Function
#End Region
Private Function GetCompareValue(ByVal Post As UserPost) As Long
Dim v& = 0
If Post.Date.HasValue Then v = Post.Date.Value.Ticks * -1
Return v
End Function
End Structure
End Module
End Namespace

View File

@@ -0,0 +1,961 @@
Imports PersonalUtilities.Functions.XML
Imports System.IO
Imports System.Threading
Imports UState = SCrawler.API.Base.UserMedia.States
Namespace API.Base
Friend MustInherit Class UserDataBase : Implements IUserData
Friend Const UserFileAppender As String = "User"
Friend Event OnPictureUpdated As IUserData.OnPictureUpdatedEventHandler Implements IUserData.OnPictureUpdated
Protected Sub Raise_OnPictureUpdated()
RaiseEvent OnPictureUpdated(Me)
End Sub
#Region "Collection buttons"
Friend WithEvents BTT_CONTEXT_DOWN As ToolStripMenuItem
Friend WithEvents BTT_CONTEXT_EDIT As ToolStripMenuItem
Friend WithEvents BTT_CONTEXT_DELETE As ToolStripMenuItem
Friend WithEvents BTT_CONTEXT_OPEN_PATH As ToolStripMenuItem
Friend WithEvents BTT_CONTEXT_OPEN_SITE As ToolStripMenuItem
Friend Sub CreateButtons(ByVal CollectionIndex As Integer)
Dim tn$ = $"[{Site}] - {Name}"
Dim _tn$ = $"{Site}{Name}"
Dim tnn As Func(Of String, String) = Function(Input) $"{Input}{_tn}"
Dim i As Image = Nothing
Select Case Site
Case Sites.Reddit : i = My.Resources.RedditIcon.ToBitmap
Case Sites.Twitter : i = My.Resources.TwitterIcon.ToBitmap
End Select
BTT_CONTEXT_DOWN = New ToolStripMenuItem(tn, i) With {.Name = tnn("DOWN"), .Tag = CollectionIndex}
BTT_CONTEXT_EDIT = New ToolStripMenuItem(tn, i) With {.Name = tnn("EDIT"), .Tag = CollectionIndex}
BTT_CONTEXT_DELETE = New ToolStripMenuItem(tn, i) With {.Name = tnn("DELETE"), .Tag = CollectionIndex}
BTT_CONTEXT_OPEN_PATH = New ToolStripMenuItem(tn, i) With {.Name = tnn("PATH"), .Tag = CollectionIndex}
BTT_CONTEXT_OPEN_SITE = New ToolStripMenuItem(tn, i) With {.Name = tnn("SITE"), .Tag = CollectionIndex}
End Sub
#End Region
#Region "XML Declarations"
Private Const Name_Site As String = "Site"
Private Const Name_UserName As String = "UserName"
Private Const Name_FriendlyName As String = "FriendlyName"
Private Const Name_UserID As String = "UserID"
Private Const Name_Description As String = "Description"
Private Const Name_ParseUserMediaOnly As String = "ParseUserMediaOnly"
Private Const Name_Temporary As String = "Temporary"
Private Const Name_Favorite As String = "Favorite"
Private Const Name_SeparateVideoFolder As String = "SeparateVideoFolder"
Private Const Name_CollectionName As String = "Collection"
Private Const Name_LabelsName As String = "Labels"
Private Const Name_ReadyForDownload As String = "ReadyForDownload"
Private Const Name_VideoCount As String = "VideoCount"
Private Const Name_PicturesCount As String = "PicturesCount"
Private Const Name_LastUpdated As String = "LastUpdated"
Private Const Name_DataMerging As String = "DataMerging"
#Region "Downloaded data"
Private Const Name_MediaType As String = "Type"
Private Const Name_MediaURL As String = "URL"
Private Const Name_MediaHash As String = "Hash"
Private Const Name_MediaFile As String = "File"
Private Const Name_MediaPostID As String = "ID"
Private Const Name_MediaPostDate As String = "Date"
#End Region
#End Region
#Region "Declarations"
Friend MustOverride Property Site As Sites Implements IContentProvider.Site
Friend User As UserInfo
Friend Overridable Property Name As String Implements IContentProvider.Name
Get
Return User.Name
End Get
Set(ByVal NewName As String)
User.Name = NewName
User.UpdateUserFile()
Settings.UpdateUsersList(User)
End Set
End Property
Friend Overridable Property ID As String = String.Empty Implements IContentProvider.ID
Friend Overridable Property FriendlyName As String = String.Empty Implements IContentProvider.FriendlyName
Friend Property UserDescription As String = String.Empty Implements IContentProvider.Description
Friend Property ParseUserMediaOnly As Boolean = False Implements IUserData.ParseUserMediaOnly
Protected _Favorite As Boolean = False
Friend Overridable Property Favorite As Boolean Implements IContentProvider.Favorite
Get
Return _Favorite
End Get
Set(ByVal Fav As Boolean)
_Favorite = Fav
If _Favorite Then _Temporary = False
End Set
End Property
Protected _Temporary As Boolean = False
Friend Overridable Property Temporary As Boolean Implements IContentProvider.Temporary
Get
Return _Temporary
End Get
Set(ByVal Temp As Boolean)
_Temporary = Temp
If _Temporary Then _Favorite = False
End Set
End Property
Friend Overridable ReadOnly Property IsChannel As Boolean Implements IUserData.IsChannel
Get
Return User.IsChannel
End Get
End Property
Friend ReadOnly Property Self As IUserData Implements IUserData.Self
Get
Return Me
End Get
End Property
#Region "Images"
Friend Overridable Function GetUserPicture() As Image Implements IUserData.GetPicture
If Settings.ViewModeIsPicture Then
Return GetPicture()
Else
Return Nothing
End If
End Function
Friend Overridable Sub SetPicture(ByVal f As SFile) Implements IUserData.SetPicture
Try
If Not f.IsEmptyString AndAlso f.Exists Then
Using p As New UserImage(f, User.File) : p.Save() : End Using
End If
Catch ex As Exception
End Try
End Sub
Protected Function GetNullPicture(ByVal MaxHeigh As XML.Base.XMLValue(Of Integer)) As Bitmap
Return New Bitmap(CInt(DivideWithZeroChecking(MaxHeigh.Value, 100) * 75), MaxHeigh.Value)
End Function
Private Function GetPicture(Optional ByVal ReturnNullImageOnNothing As Boolean = True) As Image
Dim f As SFile = Nothing
Dim p As UserImage = Nothing
Dim DelPath As Boolean = True
BlockPictureFolder:
On Error GoTo BlockPictureScan
f = SFile.GetPath($"{MyFile.PathWithSeparator}Pictures")
If f.Exists(SFO.Path, False) Then
Dim PicList As List(Of SFile) = SFile.GetFiles(f, $"{UserImage.ImagePrefix}*.jpg")
If PicList.ListExists Then
PicList.Sort()
Dim l As SFile, s As SFile
l = PicList.Find(Function(ff) ff.Name.Contains(UserImage.ImagePostfix_Large))
If Not l.IsEmptyString Then PicList.Remove(l)
s = PicList.Find(Function(ff) ff.Name.Contains(UserImage.ImagePostfix_Small))
If Not s.IsEmptyString Then PicList.Remove(s)
If PicList.Count > 0 Then
p = New UserImage(PicList.First, l, s, MyFile)
GoTo BlockReturn
Else
f.Delete(SFO.Path, False, False, EDP.None)
DelPath = False
End If
End If
End If
BlockPictureScan:
On Error GoTo BlockDeletePictureFolder
Dim NewPicFile As SFile = SFile.GetFiles(MyFile.CutPath, "*.jpg|*.png",,
New ErrorsDescriber(EDP.ReturnValue) With {
.ReturnValue = New List(Of SFile),
.ReturnValueExists = True}).FirstOrDefault
If Not NewPicFile.IsEmptyString AndAlso NewPicFile.Exists Then
p = New UserImage(NewPicFile, MyFile)
p.Save()
GoTo BlockReturn
End If
BlockDeletePictureFolder:
On Error GoTo BlockReturn
If DelPath Then
f = SFile.GetPath($"{MyFile.PathWithSeparator}Pictures")
If f.Exists(SFO.Path, False) Then f.Delete(SFO.Path, False, False)
End If
BlockReturn:
On Error GoTo BlockNullPicture
If Not p Is Nothing Then
Dim i As Image = Nothing
Select Case Settings.ViewMode.Value
Case View.LargeIcon : i = p.Large.OriginalImage.Clone
Case View.SmallIcon : i = p.Small.OriginalImage.Clone
End Select
p.Dispose()
Return i
End If
BlockNullPicture:
If ReturnNullImageOnNothing Then
Select Case Settings.ViewMode.Value
Case View.LargeIcon : Return GetNullPicture(Settings.MaxLargeImageHeigh)
Case View.SmallIcon : Return GetNullPicture(Settings.MaxSmallImageHeigh)
End Select
End If
Return Nothing
End Function
#End Region
#Region "Separate folder"
Friend Property SeparateVideoFolder As Boolean?
Protected ReadOnly Property SeparateVideoFolderF As Boolean
Get
Return (SeparateVideoFolder.HasValue AndAlso SeparateVideoFolder.Value) OrElse Settings.SeparateVideoFolder.Value
End Get
End Property
#End Region
#Region "Collections support"
Protected _IsCollection As Boolean = False
Protected Friend ReadOnly Property IsCollection As Boolean Implements IUserData.IsCollection
Get
Return _IsCollection
End Get
End Property
Friend Overridable Property CollectionName As String Implements IUserData.CollectionName
Get
Return User.CollectionName
End Get
Set(ByVal NewCollection As String)
ChangeCollectionName(NewCollection, True)
End Set
End Property
Friend ReadOnly Property IncludedInCollection As Boolean Implements IUserData.IncludedInCollection
Get
Return User.IncludedInCollection
End Get
End Property
Friend Overridable Sub ChangeCollectionName(ByVal NewName As String, ByVal UpdateSettings As Boolean)
Dim u As UserInfo = User
u.CollectionName = NewName
u.IncludedInCollection = Not NewName.IsEmptyString
User = u
If UpdateSettings Then Settings.UpdateUsersList(User)
End Sub
Friend Overridable ReadOnly Property Labels As List(Of String) Implements IUserData.Labels
#End Region
#Region "Downloading params"
Protected _DataLoaded As Boolean = False
Protected _DataParsed As Boolean = False
Friend Property ReadyForDownload As Boolean = True Implements IUserData.ReadyForDownload
#End Region
#Region "Content"
Protected ReadOnly _ContentList As List(Of UserMedia)
Protected ReadOnly _ContentNew As List(Of UserMedia)
Protected ReadOnly _ContentForReparse As List(Of UserMedia)
Protected ReadOnly _TempMediaList As List(Of UserMedia)
Protected ReadOnly _TempPostsList As List(Of String)
#End Region
#Region "Files"
Friend Overridable Property MyFile As SFile Implements IUserData.File
Get
Return User.File
End Get
Set(ByVal f As SFile)
User.File = f
Settings.UpdateUsersList(User)
End Set
End Property
Protected MyFileData As SFile
Protected MyFileDataR As SFile
Protected MyFileDataRV As SFile
Protected MyFilePosts As SFile
Friend Overridable Property FileExists As Boolean = False Implements IUserData.FileExists
Friend Overridable Property DataMerging As Boolean
Get
Return User.Merged
End Get
Set(ByVal IsMerged As Boolean)
If Not User.Merged = IsMerged Then
User.Merged = IsMerged
User.UpdateUserFile()
Settings.UpdateUsersList(User)
End If
End Set
End Property
#End Region
#Region "Information"
Protected _CountVideo As Integer = 0
Protected _CountPictures As Integer = 0
Friend Overridable Property LastUpdated As Date?
Friend ReadOnly Property TotalContentCount As Integer
Get
Return _CountVideo + _CountPictures
End Get
End Property
Friend Overridable Property HasError As Boolean = False Implements IUserData.HasError
Private _DownloadedPicturesTotal As Integer = 0
Private _DownloadedPicturesSession As Integer = 0
Friend Property DownloadedPictures As Integer Implements IUserData.DownloadedPictures
Get
Return _DownloadedPicturesSession
End Get
Set(ByVal NewValue As Integer)
_DownloadedPicturesSession = NewValue
End Set
End Property
Private _DownloadedVideosTotal As Integer = 0
Private _DownloadedVideosSession As Integer = 0
Friend Property DownloadedVideos As Integer Implements IUserData.DownloadedVideos
Get
Return _DownloadedVideosSession
End Get
Set(ByVal NewValue As Integer)
_DownloadedVideosSession = NewValue
End Set
End Property
Friend Overridable ReadOnly Property DownloadedTotal(Optional ByVal Total As Boolean = True) As Integer Implements IUserData.DownloadedTotal
Get
If Total Then
Return _DownloadedPicturesTotal + _DownloadedVideosTotal
Else
Return _DownloadedPicturesSession + _DownloadedVideosSession
End If
End Get
End Property
Friend ReadOnly Property DownloadedInformation As String Implements IUserData.DownloadedInformation
Get
Dim luv$ = String.Empty
If LastUpdated.HasValue Then luv = $"{LastUpdated.Value.ToStringDate(ADateTime.Formats.BaseDateTime)}: "
Return $"{luv}{Name} [{Site}]{IIf(HasError, " (with errors)", String.Empty)}: P - {_DownloadedPicturesTotal}; V - {_DownloadedVideosTotal}" &
$" (P - {_CountPictures}; V - {_CountVideo})"
End Get
End Property
#End Region
Protected ReadOnly LNC As New ListAddParams(LAP.NotContainsOnly)
#End Region
#Region "LVI"
Friend ReadOnly Property LVIKey As String Implements IUserData.LVIKey
Get
If Not _IsCollection Then
Return $"{IIf(Site = Sites.Reddit, "R", "T")}_{Name}"
Else
Return $"CCCC_{CollectionName}"
End If
End Get
End Property
Private _LVIIndex As Integer = -1
Private ReadOnly Property LVIIndex As Integer Implements IUserData.LVIIndex
Get
Return _LVIIndex
End Get
End Property
Friend Function GetLVI(ByVal Destination As ListView) As ListViewItem Implements IUserData.GetLVI
_LVIIndex = Destination.Items.Count
If Settings.ViewModeIsPicture Then
Return New ListViewItem(ToString(), LVIKey, GetLVIGroup(Destination)) With {.Name = LVIKey, .Tag = LVIKey}
Else
Return New ListViewItem(ToString(), GetLVIGroup(Destination)) With {.Name = LVIKey, .Tag = LVIKey}
End If
End Function
Friend Overridable ReadOnly Property FitToAddParams As Boolean Implements IUserData.FitToAddParams
Get
Select Case Settings.ShowingMode.Value
Case ShowingModes.Regular : Return Not Temporary And Not Favorite
Case ShowingModes.Temporary : Return Temporary
Case ShowingModes.Favorite : Return Favorite
Case ShowingModes.Labels : Return Settings.Labels.CurrentSelection.ListContains(Labels)
Case ShowingModes.NoLabels : Return Labels.Count = 0
Case Else : Return True
End Select
End Get
End Property
Friend Function GetLVIGroup(ByVal Destination As ListView) As ListViewGroup Implements IUserData.GetLVIGroup
Try
If Settings.ShowingMode.Value = ShowingModes.Labels Then
If Labels.Count > 0 And Settings.Labels.CurrentSelection.Count > 0 Then
For i% = 0 To Labels.Count - 1
If Settings.Labels.CurrentSelection.Contains(Labels(i)) Then Return Destination.Groups.Item(Labels(i))
Next
Return Destination.Groups.Item(LabelsKeeper.NoLabeledName)
Else
Return Destination.Groups.Item(LabelsKeeper.NoLabeledName)
End If
Else
Return Destination.Groups.Item(GetLviGroupName(Site, Temporary, Favorite, IsCollection))
End If
Catch ex As Exception
Return Destination.Groups.Item(LabelsKeeper.NoLabeledName)
End Try
End Function
Friend Overridable Function GetUserInformation() As String
Dim OutStr$ = $"User: {Name}"
OutStr.StringAppendLine($"Path: {MyFile.CutPath.Path}")
OutStr.StringAppendLine($"Total downloaded ({TotalContentCount.NumToString(ANumbers.Formats.Number, 3)}):")
OutStr.StringAppendLine($"Pictures: {_CountPictures.NumToString(ANumbers.Formats.Number, 3)}")
OutStr.StringAppendLine($"Videos: {_CountVideo.NumToString(ANumbers.Formats.Number, 3)}")
If Not UserDescription.IsEmptyString Then
OutStr.StringAppendLine(String.Empty)
OutStr.StringAppendLine(UserDescription)
End If
OutStr.StringAppendLine(String.Empty)
OutStr.StringAppendLine($"Last updated at: {AConvert(Of String)(LastUpdated, ADateTime.Formats.BaseDateTime, "not yet")}")
If _DataParsed Then
OutStr.StringAppendLine("Downloaded now:")
OutStr.StringAppendLine($"Pictures: {_CountPictures.NumToString(ANumbers.Formats.Number, 3)}")
OutStr.StringAppendLine($"Videos: {_CountVideo.NumToString(ANumbers.Formats.Number, 3)}")
End If
Return OutStr
End Function
#End Region
#Region "Initializer"
Private ReadOnly _InvokeImageHandler As Boolean
''' <summary>By using this constructor you must set UserName and MyFile manually</summary>
Friend Sub New(Optional ByVal InvokeImageHandler As Boolean = True)
_InvokeImageHandler = InvokeImageHandler
_ContentList = New List(Of UserMedia)
_ContentNew = New List(Of UserMedia)
_ContentForReparse = New List(Of UserMedia)
_TempMediaList = New List(Of UserMedia)
_TempPostsList = New List(Of String)
Labels = New List(Of String)
If InvokeImageHandler Then ImageHandler(Me)
End Sub
''' <exception cref="ArgumentOutOfRangeException"></exception>
Friend Overloads Shared Function GetInstance(ByVal u As UserInfo, Optional ByVal _LoadUserInformation As Boolean = True) As IUserData
Select Case u.Site
Case Sites.Reddit : Return New Reddit.UserData(u, _LoadUserInformation)
Case Sites.Twitter : Return New Twitter.UserData(u, _LoadUserInformation)
Case Else : Throw New ArgumentOutOfRangeException("Site", $"Site [{u.Site}] information does not recognized by loader")
End Select
End Function
#End Region
#Region "Information & Content data files loader and saver"
#Region "User information"
Friend Overridable Sub LoadUserInformation() Implements IUserData.LoadUserInformation
Try
If MyFile.Exists Then
FileExists = True
Using x As New XmlFile(MyFile) With {.XmlReadOnly = True}
x.DefaultsLoading(False)
User.Site = Site
Site = x.Value(Name_Site).FromXML(Of Integer)(0)
User.Name = x.Value(Name_UserName)
ID = x.Value(Name_UserID)
FriendlyName = x.Value(Name_FriendlyName)
UserDescription = x.Value(Name_Description)
ParseUserMediaOnly = x.Value(Name_ParseUserMediaOnly).FromXML(Of Boolean)(False)
Temporary = x.Value(Name_Temporary).FromXML(Of Boolean)(False)
Favorite = x.Value(Name_Favorite).FromXML(Of Boolean)(False)
SeparateVideoFolder = AConvert(Of Boolean)(x.Value(Name_SeparateVideoFolder), Nothing)
ReadyForDownload = x.Value(Name_ReadyForDownload).FromXML(Of Boolean)(True)
_CountVideo = x.Value(Name_VideoCount).FromXML(Of Integer)(0)
_CountPictures = x.Value(Name_PicturesCount).FromXML(Of Integer)(0)
LastUpdated = AConvert(Of Date)(x.Value(Name_LastUpdated), ADateTime.Formats.BaseDateTime, Nothing)
DataMerging = x.Value(Name_DataMerging).FromXML(Of Boolean)(False)
ChangeCollectionName(x.Value(Name_CollectionName), False)
Labels.ListAddList(x.Value(Name_LabelsName).StringToList(Of String, List(Of String))("|", EDP.ReturnValue), LAP.NotContainsOnly, LAP.ClearBeforeAdd)
End Using
UpdateDataFiles()
_DataForReparseExists = MyFileDataR.Exists
End If
Catch ex As Exception
LogError(ex, "user information loading error")
End Try
End Sub
Friend Overridable Sub UpdateUserInformation() Implements IUserData.UpdateUserInformation
Try
MyFile.Exists(SFO.Path)
Using x As New XmlFile With {.Name = "User"}
x.Add(Name_Site, CInt(Site))
x.Add(Name_UserName, User.Name)
x.Add(Name_UserID, ID)
x.Add(Name_FriendlyName, FriendlyName)
x.Add(Name_Description, UserDescription)
x.Add(Name_ParseUserMediaOnly, ParseUserMediaOnly.BoolToInteger)
x.Add(Name_Temporary, Temporary.BoolToInteger)
x.Add(Name_Favorite, Favorite.BoolToInteger)
If SeparateVideoFolder.HasValue Then
x.Add(Name_SeparateVideoFolder, SeparateVideoFolder.Value.BoolToInteger)
Else
x.Add(Name_SeparateVideoFolder, String.Empty)
End If
x.Add(Name_ReadyForDownload, ReadyForDownload.BoolToInteger)
x.Add(Name_VideoCount, _CountVideo)
x.Add(Name_PicturesCount, _CountPictures)
x.Add(Name_LastUpdated, AConvert(Of String)(LastUpdated, ADateTime.Formats.BaseDateTime, String.Empty))
x.Add(Name_CollectionName, CollectionName)
x.Add(Name_LabelsName, Labels.ListToString(, "|", EDP.ReturnValue))
x.Add(Name_DataMerging, DataMerging.BoolToInteger)
x.Save(MyFile)
End Using
Settings.UpdateUsersList(User)
Catch ex As Exception
LogError(ex, "user information saving error")
End Try
End Sub
#End Region
#Region "User data"
Friend Overridable Overloads Sub LoadContentInformation()
UpdateDataFiles()
LoadContentInformation(_ContentList, MyFileData)
LoadContentInformation(_ContentForReparse, MyFileDataR)
LoadContentInformation(_TempMediaList, MyFileDataRV)
_DataForReparseExists = False
End Sub
Private Overloads Sub LoadContentInformation(ByRef _CLIST As List(Of UserMedia), ByVal f As SFile)
Try
If Not f.Exists Then Exit Sub
Using x As New XmlFile(f, ProtectionLevels.All, False) With {.XmlReadOnly = True, .AllowSameNames = True}
x.LoadData()
x.DefaultsLoading(False)
If x.Count > 0 Then
Dim fs$ = MyFile.CutPath.PathWithSeparator
Dim gfn As Func(Of String, String) = Function(ByVal Input As String) As String
If Input.IsEmptyString Then
Return String.Empty
Else
If Input.Contains("\") Then
Return New SFile(Input).File
Else
Return Input
End If
End If
End Function
For Each v As EContainer In x
_CLIST.Add(New UserMedia With {
.Type = AConvert(Of Integer)(v.Attribute(Name_MediaType).Value, 0),
.URL = v.Attribute(Name_MediaURL).Value,
.URL_BASE = v.Value,
.MD5 = v.Attribute(Name_MediaHash).Value,
.File = fs & gfn.Invoke(v.Attribute(Name_MediaFile).Value),
.Post = New UserPost With {
.ID = v.Attribute(Name_MediaPostID).Value,
.[Date] = AConvert(Of Date)(v.Attribute(Name_MediaPostDate).Value, ParsersDataDateProvider, Nothing)}
})
Next
End If
_DataLoaded = True
End Using
Catch ex As Exception
LogError(ex, "history loading error")
End Try
End Sub
Friend Sub UpdateContentInformation(ByRef _CLIST As List(Of UserMedia), ByVal f As SFile)
Try
UpdateDataFiles()
If f.IsEmptyString Then Exit Sub
f.Exists(SFO.Path)
Using x As New XmlFile With {.AllowSameNames = True, .Name = "Data"}
If _CLIST.Count > 0 Then
For Each i As UserMedia In _CLIST
x.Add(New EContainer("MediaData", i.URL_BASE,
{New EAttribute(Name_MediaType, CInt(i.Type)),
New EAttribute(Name_MediaURL, i.URL),
New EAttribute(Name_MediaHash, i.MD5),
New EAttribute(Name_MediaFile, i.File.File),
New EAttribute(Name_MediaPostID, i.Post.ID),
New EAttribute(Name_MediaPostDate, AConvert(Of String)(i.Post.Date, ParsersDataDateProvider, String.Empty))
}))
Next
End If
x.Save(MyFileData)
End Using
Catch ex As Exception
LogError(ex, "history saving error")
End Try
End Sub
#End Region
#End Region
#Region "Open site, folder"
Friend Overridable Sub OpenSite() Implements IContentProvider.OpenSite
Try
Dim URL$ = String.Empty
Select Case Site
Case Sites.Reddit : URL = $"https://www.reddit.com/user/{Name}/"
Case Sites.Twitter : URL = $"https://twitter.com/{Name}"
Case Else : MsgBoxE($"Site [{Site}] opening does not implemented", MsgBoxStyle.Exclamation)
End Select
If Not URL.IsEmptyString Then Process.Start(URL)
Catch ex As Exception
MsgBoxE($"Error on trying to open [{Site}] page of user [{Name}]", MsgBoxStyle.Critical)
End Try
End Sub
Friend Overridable Sub OpenFolder() Implements IUserData.OpenFolder
MyFile.CutPath.Open(SFO.Path, EDP.None)
End Sub
#End Region
#Region "Download functions and options"
Friend Overridable Property DownloadReparseOnly As Boolean = False Implements IUserData.DownloadReparseOnly
Private _DataForReparseExists As Boolean = False
Friend Overridable ReadOnly Property DataForReparseExists As Boolean Implements IUserData.DataForReparseExists
Get
Return _ContentForReparse.Count > 0 Or _DataForReparseExists
End Get
End Property
Friend Overridable Sub DownloadData(ByVal Token As CancellationToken) Implements IContentProvider.DownloadData
Dim Canceled As Boolean = False
Try
UpdateDataFiles()
Dim UpPic As Boolean = Settings.ViewModeIsPicture AndAlso GetPicture(False) Is Nothing
_DownloadedPicturesSession = 0
_DownloadedVideosSession = 0
_TempMediaList.Clear()
_TempPostsList.Clear()
If Not _DataLoaded Then LoadContentInformation()
If Not DownloadReparseOnly Then
If MyFilePosts.Exists Then _TempPostsList.ListAddList(File.ReadAllLines(MyFilePosts))
If _ContentList.Count > 0 Then _TempPostsList.ListAddList(_ContentList.Select(Function(u) u.Post.ID), LNC)
Token.ThrowIfCancellationRequested()
DownloadDataF(Token)
Token.ThrowIfCancellationRequested()
End If
ReparseVideo(Token)
If Token.IsCancellationRequested Then
If Not DownloadReparseOnly Then
If _TempMediaList.Count > 0 AndAlso _TempMediaList.Exists(Function(c) c.Type = UserMedia.Types.VideoPre) Then
TextSaver.SaveTextToFile((From c As UserMedia In _TempMediaList
Where c.Type = UserMedia.Types.VideoPre
Select c.URL).ListToString(, Environment.NewLine), MyFileDataRV, True,, EDP.SendInLog)
Else
If MyFileDataRV.Exists Then MyFileDataRV.Delete(,,, EDP.SendInLog)
End If
End If
Else
If Not DownloadReparseOnly And _TempPostsList.Count > 0 Then TextSaver.SaveTextToFile(_TempPostsList.ListToString(, Environment.NewLine), MyFilePosts, True,, EDP.None)
_ContentNew.ListAddList(_TempMediaList, LAP.ClearBeforeAdd)
End If
Dim r% = 0
Do While r <= 2 And (_ContentNew.Count > 0 Or _ContentForReparse.Count > 0) And Not Token.IsCancellationRequested
DownloadContent(Token)
If _ContentNew.Count > 0 Then
_ContentForReparse.ListAddList(_ContentNew.Where(Function(c) c.State = UState.Tried Or c.State = UState.Unknown), LNC)
_ContentList.ListAddList(_ContentNew.Where(Function(c) c.State = UState.Downloaded), LNC)
End If
If _ContentForReparse.Count > 0 Then _ContentForReparse.RemoveAll(Function(c) _ContentList.Contains(c))
_ContentNew.Clear()
If _ContentForReparse.Count > 0 Then _ContentNew.ListAddList(_ContentForReparse, LNC)
r += 1
Loop
_CountPictures = _ContentList.LongCount(Function(c) c.Type = UserMedia.Types.Picture)
_CountVideo = _ContentList.LongCount(Function(c) c.Type = UserMedia.Types.Video)
If DownloadedPictures + DownloadedVideos > 0 Then
LastUpdated = Now
If Labels.Contains(LabelsKeeper.NoParsedUser) Then Labels.Remove(LabelsKeeper.NoParsedUser)
UpdateContentInformation(_ContentList, MyFileData)
UpdateUserInformation()
End If
If _ContentForReparse.Count > 0 Then UpdateContentInformation(_ContentForReparse, MyFileDataR)
_DownloadedPicturesTotal += _DownloadedPicturesSession
_DownloadedVideosTotal += _DownloadedVideosSession
If UpPic Then Raise_OnPictureUpdated()
Catch oex As OperationCanceledException When Token.IsCancellationRequested
MyMainLOG = $"{Site} - {Name}: downloading canceled"
Canceled = True
Catch ex As Exception
LogError(ex, "downloading data error")
HasError = True
Finally
If Not Canceled Then _DataParsed = True ': LastUpdated = Now
_ContentNew.Clear()
DownloadReparseOnly = False
If _ContentForReparse.Count = 0 And MyFileDataR.Exists Then MyFileDataR.Delete(,,, EDP.SendInLog)
End Try
End Sub
Private Sub UpdateDataFiles()
If Not User.File.IsEmptyString Then
MyFileData = User.File
MyFileData.Name &= "_Data"
MyFileDataR = MyFileData
MyFileDataR.Name &= "_REPARSE"
MyFileDataRV = MyFileData
MyFileDataRV.Name &= "_RVideo"
MyFilePosts = User.File
MyFilePosts.Name &= "_Posts"
MyFilePosts.Extension = "txt"
Else
Throw New ArgumentNullException("User.File", "User file does not detected")
End If
End Sub
Protected MustOverride Sub DownloadDataF(ByVal Token As CancellationToken)
Protected MustOverride Sub ReparseVideo(ByVal Token As CancellationToken)
Protected MustOverride Sub DownloadContent(ByVal Token As CancellationToken)
#End Region
#Region "Delete, Move, Merge"
Friend Overridable Function Delete() As Integer Implements IUserData.Delete
Dim f As SFile = SFile.GetPath(MyFile.CutPath.Path)
If f.Exists(SFO.Path, False) AndAlso f.Delete(SFO.Path, False, False) Then
ImageHandler(Me, False)
Settings.UsersList.Remove(User)
Settings.UpdateUsersList()
Settings.Users.Remove(Me)
Downloader.UserRemove(Me)
Dispose(True)
Return 1
Else
Return 0
End If
End Function
Friend Overridable Function MoveFiles(ByVal __CollectionName As String, ByVal _MergeData As Boolean) As Boolean Implements IUserData.MoveFiles
Dim UserBefore As UserInfo = User
Try
Dim f As SFile
Dim Removed As Boolean
If IncludedInCollection Then
Settings.Users.Add(Me)
Removed = False
User.CollectionName = String.Empty
User.IncludedInCollection = False
Else
Settings.Users.Remove(Me)
Removed = True
User.CollectionName = __CollectionName
User.IncludedInCollection = True
End If
User.UpdateUserFile()
f = User.File.CutPath(, EDP.ThrowException)
If f.Exists(SFO.Path, False) Then
If If(SFile.GetFiles(f,, SearchOption.AllDirectories), New List(Of SFile)).Count > 0 AndAlso
MsgBoxE({$"Destination directory [{f.Path}] already exists and contains files!" & vbCr &
"By continuing, this directory and all files will be deleted",
"Destination directory is not empty!"}, MsgBoxStyle.Exclamation,,, {"Delete", "Cancel"}) = 1 Then
MsgBoxE("Operation canceled", MsgBoxStyle.Exclamation)
User = UserBefore
If Removed Then Settings.Users.Add(Me) Else Settings.Users.Remove(Me)
Return False
End If
f.Delete(SFO.Path, False, False, EDP.ThrowException)
End If
f.CutPath.Exists(SFO.Path)
Directory.Move(UserBefore.File.CutPath(, EDP.ThrowException).Path, f.Path)
Settings.UsersList.Remove(UserBefore)
Settings.UpdateUsersList(User)
UpdateUserInformation()
Return True
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Files moving error")
User = UserBefore
Return False
End Try
End Function
Friend Overloads Sub MergeData()
Dim UserBefore As UserInfo = User
Try
If DataMerging Then
Throw New InvalidOperationException($"{Site} - {Name}: data already merged") With {.HelpLink = 1}
Else
Dim files As List(Of SFile) = Nothing
Dim allFiles As List(Of SFile) = Nothing
Dim fSource As SFile, fDest As SFile
Dim ReplacingPath$ = UserBefore.File.CutPath.Path
Dim dirs As List(Of SFile) = SFile.GetDirectories(UserBefore.File.CutPath,, SearchOption.AllDirectories)
Dim FilesMover As Action = Sub()
If files.ListExists Then
For Each fSource In files
fDest = fSource
fDest.Path = User.File.CutPath.PathWithSeparator & fSource.Path.Replace(ReplacingPath, String.Empty)
fDest.Exists(SFO.Path,, EDP.ThrowException)
fDest = CheckFile(fDest, allFiles)
File.Move(fSource, fDest)
Next
files.Clear()
End If
End Sub
DataMerging = True
If dirs.ListExists Then
For Each dir As SFile In dirs
allFiles = SFile.GetFiles(SFile.GetPath(User.File.CutPath.PathWithSeparator &
dir.Path.Replace(ReplacingPath, String.Empty)),,, EDP.ReturnValue)
files = SFile.GetFiles(dir,,, EDP.ReturnValue)
FilesMover.Invoke
Next
End If
allFiles = SFile.GetFiles(User.File.CutPath,,, EDP.ReturnValue)
files = SFile.GetFiles(UserBefore.File.CutPath,,, EDP.ReturnValue)
FilesMover.Invoke
If SFile.GetFiles(UserBefore.File.CutPath,, SearchOption.AllDirectories,
New ErrorsDescriber(False, False, False, New List(Of SFile))).Count = 0 Then
UserBefore.File.CutPath.Delete(SFO.Path, False, False, EDP.SendInLog)
End If
UpdateUserInformation()
End If
Catch ex As Exception
LogError(ex, "[UserDataBase.MergeData]")
End Try
End Sub
Private Function CheckFile(ByVal f As SFile, ByRef List As IEnumerable(Of SFile)) As SFile
If List.ListExists Then
Dim p As New RegexStructure(".+?\s{0,1}\((\d+)\)|.+",,,,,,, String.Empty, EDP.ReturnValue)
Dim i% = List.Where(Function(ff) CStr(RegexReplace(ff.Name, p)).Trim.ToLower = f.Name.Trim.ToLower).Count
If i > 0 Then f.Name &= $" ({i + 1})"
End If
Return f
End Function
#End Region
#Region "Errors functions"
Protected Sub LogError(ByVal ex As Exception, ByVal Message As String)
ErrorsDescriber.Execute(EDP.SendInLog, ex, $"{IIf(IncludedInCollection, $"{CollectionName}-", String.Empty)}{Site} - {Name}: {Message}")
End Sub
Protected Sub ErrorDownloading(ByVal f As SFile, ByVal URL As String)
If Not f.Exists Then MyMainLOG = $"Error downloading from [{URL}] to [{f}]"
End Sub
#End Region
Public Overrides Function ToString() As String
If Settings.ViewModeIsPicture Then
If IsCollection Then
Return CollectionName
Else
Return IIf(FriendlyName.IsEmptyString, Name, FriendlyName)
End If
Else
Dim t$ = String.Empty
If Temporary Then
t = " (T)"
ElseIf Favorite Then
t = " (F)"
End If
If IsCollection Then
Return $"Collection [{CollectionName}]{t}"
Else
Return $"[{Site}]{t} {IIf(FriendlyName.IsEmptyString, Name, FriendlyName)}"
End If
End If
End Function
#Region "Buttons actions"
Private Sub BTT_CONTEXT_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_DOWN.Click
Downloader.Add(Me)
End Sub
Private Sub BTT_CONTEXT_EDIT_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_EDIT.Click
Using f As New Editors.UserCreatorForm(Me)
f.ShowDialog()
If f.DialogResult = DialogResult.OK Then UpdateUserInformation()
End Using
End Sub
Private Sub BTT_CONTEXT_DELETE_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_DELETE.Click
End Sub
Private Sub BTT_CONTEXT_OPEN_PATH_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_OPEN_PATH.Click
OpenFolder()
End Sub
Private Sub BTT_CONTEXT_OPEN_SITE_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_OPEN_SITE.Click
OpenSite()
End Sub
#End Region
#Region "IComparable Support"
Friend Overridable Function CompareTo(ByVal Other As UserDataBase) As Integer Implements IComparable(Of UserDataBase).CompareTo
Dim x% = CompareValue(Me)
Dim y% = CompareValue(Other)
If x.CompareTo(y) = 0 Then
Return Name.CompareTo(Other.Name)
Else
Return x.CompareTo(y)
End If
End Function
Protected Function CompareValue(ByVal x As UserDataBase) As Integer
Dim OutValue% = CInt(x.Site) * 10000
If x.IsCollection Then OutValue -= 1000
If x.Temporary Then OutValue += 2000
If x.Favorite Then OutValue -= 500
Return OutValue
End Function
Friend Overridable Function CompareTo(ByVal Obj As Object) As Integer Implements IComparable.CompareTo
Return CompareTo(DirectCast(Obj, UserDataBase))
End Function
#End Region
#Region "IEquatable Support"
Friend Overridable Overloads Function Equals(ByVal Other As UserDataBase) As Boolean Implements IEquatable(Of UserDataBase).Equals
Return Site = Other.Site And Name = Other.Name
End Function
Public Overrides Function Equals(ByVal Obj As Object) As Boolean
Return Equals(DirectCast(Obj, UserDataBase))
End Function
#End Region
#Region "IDisposable Support"
Protected disposedValue As Boolean = False
Friend ReadOnly Property Disposed As Boolean
Get
Return disposedValue
End Get
End Property
Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
If Not disposedValue Then
If disposing Then
_ContentList.Clear()
_ContentNew.Clear()
_TempMediaList.Clear()
_TempPostsList.Clear()
If Not BTT_CONTEXT_DOWN Is Nothing Then BTT_CONTEXT_DOWN.Dispose()
If Not BTT_CONTEXT_EDIT Is Nothing Then BTT_CONTEXT_EDIT.Dispose()
If Not BTT_CONTEXT_DELETE Is Nothing Then BTT_CONTEXT_DELETE.Dispose()
If Not BTT_CONTEXT_OPEN_PATH Is Nothing Then BTT_CONTEXT_OPEN_PATH.Dispose()
If Not BTT_CONTEXT_OPEN_SITE Is Nothing Then BTT_CONTEXT_OPEN_SITE.Dispose()
If _InvokeImageHandler Then ImageHandler(Me, False)
End If
disposedValue = True
End If
End Sub
Protected Overloads Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub
Friend Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
Friend Interface IContentProvider
Property Site As Sites
Property Name As String
Property ID As String
Property FriendlyName As String
Property Description As String
Property Favorite As Boolean
Property Temporary As Boolean
Sub OpenSite()
Sub DownloadData(ByVal Token As CancellationToken)
End Interface
Friend Interface IUserData : Inherits IContentProvider, IComparable(Of UserDataBase), IComparable, IEquatable(Of UserDataBase), IDisposable
Event OnPictureUpdated(ByVal User As IUserData)
Property ParseUserMediaOnly As Boolean
#Region "Images"
Function GetPicture() As Image
Sub SetPicture(ByVal f As SFile)
#End Region
#Region "Collection support"
ReadOnly Property IsCollection As Boolean
Property CollectionName As String
ReadOnly Property IncludedInCollection As Boolean
ReadOnly Property Labels As List(Of String)
#End Region
ReadOnly Property IsChannel As Boolean
Property ReadyForDownload As Boolean
Property [File] As SFile
Property FileExists As Boolean
Property DownloadedPictures As Integer
Property DownloadedVideos As Integer
ReadOnly Property DownloadedTotal(Optional ByVal Total As Boolean = True) As Integer
ReadOnly Property DownloadedInformation As String
Property HasError As Boolean
ReadOnly Property FitToAddParams As Boolean
ReadOnly Property LVIKey As String
ReadOnly Property LVIIndex As Integer
Function GetLVI(ByVal Destination As ListView) As ListViewItem
Function GetLVIGroup(ByVal Destination As ListView) As ListViewGroup
Sub LoadUserInformation()
Sub UpdateUserInformation()
''' <summary>
''' 0 - Nothing removed<br/>
''' 1 - User removed<br/>
''' 2 - Collection removed<br/>
''' 3 - Collection splitted
''' </summary>
Function Delete() As Integer
Function MoveFiles(ByVal CollectionName As String, ByVal MergeData As Boolean) As Boolean
Sub OpenFolder()
Property DownloadReparseOnly As Boolean
ReadOnly Property DataForReparseExists As Boolean
ReadOnly Property Self As IUserData
End Interface
Friend Interface IChannelLimits
Property AutoGetLimits As Boolean
Property DownloadLimitCount As Integer?
Property DownloadLimitPost As String
Property DownloadLimitDate As Date?
Overloads Sub SetLimit(Optional ByVal Post As String = "", Optional ByVal Count As Integer? = Nothing, Optional ByVal [Date] As Date? = Nothing)
Overloads Sub SetLimit(ByVal Source As IChannelLimits)
End Interface
Friend Interface IChannelData : Inherits IContentProvider, IChannelLimits
Property SkipExistsUsers As Boolean
Property SaveToCache As Boolean
End Interface
End Namespace

View File

@@ -0,0 +1,304 @@
Imports PersonalUtilities.Tools
Imports PersonalUtilities.Forms.Toolbars
Imports PersonalUtilities.Functions.XML
Imports SCrawler.API.Base
Namespace API.Reddit
Friend Class Channel : Implements ICollection(Of UserPost), IEquatable(Of Channel), IComparable(Of Channel),
IRangeSwitcherContainer(Of UserPost), ILoaderSaver, IMyEnumerator(Of UserPost), IChannelLimits, IDisposable
#Region "XML Nodes' Names"
Private Const Name_Name As String = "Name"
Private Const Name_ID As String = "ID"
Private Const Name_Date As String = "Date"
Private Const Name_PostsNode As String = "Posts"
#End Region
Friend Const DefaultDownloadLimitCount As Integer = 1000
Friend Property Name As String = String.Empty
Friend Property ID As String = String.Empty
Friend ReadOnly Property CUser As UserInfo
Get
Return New UserInfo(Me)
End Get
End Property
Friend ReadOnly Property PostsLatest As List(Of UserPost)
Friend ReadOnly Property Posts As List(Of UserPost)
Friend ReadOnly Property PostsAll As List(Of UserPost)
Get
Return ListAddList(Nothing, Posts).ListAddList(PostsLatest).ListSort
End Get
End Property
Private ReadOnly Property Source As IEnumerable(Of UserPost) Implements IRangeSwitcherContainer(Of UserPost).Source
Get
Return Posts
End Get
End Property
Friend Property LatestParsedDate As Date? = Nothing
Private _Downloading As Boolean = False
Friend ReadOnly Property Downloading As Boolean
Get
Return _Downloading
End Get
End Property
Friend ReadOnly Property File As SFile
Get
Return $"{ChannelsCollection.ChannelsPath.PathWithSeparator}{ID}.xml"
End Get
End Property
Friend ReadOnly Property CachePath As SFile
Get
Return $"{ChannelsCollection.ChannelsPathCache.PathWithSeparator}{ID}\"
End Get
End Property
Friend ReadOnly Property Count As Integer Implements ICollection(Of UserPost).Count, IMyEnumerator(Of UserPost).MyEnumeratorCount
Get
Return Posts.Count
End Get
End Property
Default Friend ReadOnly Property Item(ByVal Index As Integer) As UserPost Implements IMyEnumerator(Of UserPost).MyEnumeratorObject
Get
Return Posts(Index)
End Get
End Property
Private ReadOnly Property Range As RangeSwitcher(Of UserPost)
#Region "Limits Support"
Private _DownloadLimitCount As Integer? = Nothing
Friend Property DownloadLimitCount As Integer? Implements IChannelLimits.DownloadLimitCount
Get
If AutoGetLimits Then
If LatestParsedDate.HasValue OrElse Not DownloadLimitPost.IsEmptyString Then
Return Nothing
ElseIf _DownloadLimitCount.HasValue Then
Return _DownloadLimitCount
Else
Return DefaultDownloadLimitCount
End If
Else
Return _DownloadLimitCount
End If
End Get
Set(ByVal NewLimit As Integer?)
_DownloadLimitCount = NewLimit
End Set
End Property
Private _DownloadLimitPost As String = String.Empty
Friend Property DownloadLimitPost As String Implements IChannelLimits.DownloadLimitPost
Get
Dim PID$ = ListAddList(Nothing, Posts, LAP.NotContainsOnly).ListAddList(PostsLatest, LAP.NotContainsOnly).ListSort.FirstOrDefault.ID
If AutoGetLimits And Not PID.IsEmptyString Then
Return PID
Else
Return _DownloadLimitPost
End If
End Get
Set(ByVal NewLimit As String)
_DownloadLimitPost = NewLimit
End Set
End Property
Private _DownloadLimitDate As Date? = Nothing
Friend Property DownloadLimitDate As Date? Implements IChannelLimits.DownloadLimitDate
Get
If AutoGetLimits And LatestParsedDate.HasValue Then
Return LatestParsedDate
Else
Return _DownloadLimitDate
End If
End Get
Set(ByVal NewLimit As Date?)
_DownloadLimitDate = NewLimit
End Set
End Property
Friend Overloads Sub SetLimit(Optional ByVal MaxPost As String = "", Optional ByVal MaxCount As Integer? = Nothing,
Optional ByVal MinDate As Date? = Nothing) Implements IChannelLimits.SetLimit
DownloadLimitPost = MaxPost
DownloadLimitCount = MaxCount
DownloadLimitDate = MinDate
End Sub
Friend Overloads Sub SetLimit(ByVal Source As IChannelLimits) Implements IChannelLimits.SetLimit
With Source
DownloadLimitCount = .DownloadLimitCount
DownloadLimitPost = .DownloadLimitPost
DownloadLimitDate = .DownloadLimitDate
AutoGetLimits = .AutoGetLimits
End With
End Sub
Friend Property AutoGetLimits As Boolean = True Implements IChannelLimits.AutoGetLimits
#End Region
Friend Sub New()
Posts = New List(Of UserPost)
PostsLatest = New List(Of UserPost)
Range = New RangeSwitcher(Of UserPost)(Me)
End Sub
Friend Sub New(ByVal f As SFile)
Me.New
LoadData(f, False)
End Sub
Public Shared Widening Operator CType(ByVal f As SFile) As Channel
Return New Channel(f)
End Operator
Public Overrides Function ToString() As String
If Not Name.IsEmptyString Then
Return Name
Else
Return ID
End If
End Function
Friend Sub Delete()
If File.Exists Then File.Delete()
End Sub
Friend Sub DownloadData(ByVal Token As Threading.CancellationToken, Optional ByVal SkipExists As Boolean = True,
Optional ByVal p As MyProgress = Nothing)
Try
_Downloading = True
Using d As New UserData(CUser, False, False) With {
.Progress = p,
.SaveToCache = True,
.SkipExistsUsers = SkipExists,
.ChannelInfo = Me
}
d.SetLimit(Me)
d.DownloadData(Token)
Posts.ListAddList(d.GetNewChannelPosts(), LAP.NotContainsOnly)
Posts.Sort()
LatestParsedDate = If(Posts.FirstOrDefault(Function(pp) pp.Date.HasValue).Date, LatestParsedDate)
Token.ThrowIfCancellationRequested()
End Using
Catch oex As OperationCanceledException When Token.IsCancellationRequested
Finally
_Downloading = False
End Try
End Sub
#Region "ICollection Support"
Private ReadOnly Property IsReadOnly As Boolean = False Implements ICollection(Of UserPost).IsReadOnly
Friend Sub Add(ByVal _Item As UserPost) Implements ICollection(Of UserPost).Add
If Not Contains(_Item) Then Posts.Add(_Item)
End Sub
Friend Sub AddRange(ByVal _Items As IEnumerable(Of UserPost))
If _Items.ListExists Then
For Each i As UserPost In _Items : Add(i) : Next
End If
End Sub
Friend Sub Clear() Implements ICollection(Of UserPost).Clear
Posts.Clear()
End Sub
Friend Function Contains(ByVal _Item As UserPost) As Boolean Implements ICollection(Of UserPost).Contains
Return Count > 0 AndAlso Posts.Contains(_Item)
End Function
Private Sub CopyTo(ByVal _Array() As UserPost, ByVal ArrayIndex As Integer) Implements ICollection(Of UserPost).CopyTo
Throw New NotImplementedException()
End Sub
Friend Function Remove(ByVal _Item As UserPost) As Boolean Implements ICollection(Of UserPost).Remove
Return Posts.Remove(_Item)
End Function
#End Region
#Region "IEnumerable Support"
Friend Function GetEnumerator() As IEnumerator(Of UserPost) Implements IEnumerable(Of UserPost).GetEnumerator
Return New MyEnumerator(Of UserPost)(Me)
End Function
Friend Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Return GetEnumerator()
End Function
#End Region
#Region "IEquatable Support"
Friend Overloads Function Equals(ByVal Other As Channel) As Boolean Implements IEquatable(Of Channel).Equals
Return ID = Other.ID
End Function
Public Overloads Overrides Function Equals(ByVal Obj As Object) As Boolean
If Not Obj Is Nothing Then
If TypeOf Obj Is String Then
Return ID = CStr(Obj)
Else
Return Equals(DirectCast(Obj, Channel))
End If
Else
Return False
End If
End Function
#End Region
#Region "IComparable Support"
Friend Function CompareTo(ByVal Other As Channel) As Integer Implements IComparable(Of Channel).CompareTo
If Not Name.IsEmptyString And Not Other.Name.IsEmptyString Then
Return Name.CompareTo(Other.Name)
Else
Return ID.CompareTo(Other.ID)
End If
End Function
#End Region
#Region "IXMLContainer Support"
Friend Overloads Function LoadData(Optional ByVal f As SFile = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Boolean Implements ILoaderSaver.Load
Return LoadData(File, False, e)
End Function
Friend Overloads Function LoadData(ByVal f As SFile, ByVal PartialLoad As Boolean, Optional ByVal e As ErrorsDescriber = Nothing) As Boolean
If f.Exists Then
Using x As New XmlFile(f, ProtectionLevels.All, False) With {.XmlReadOnly = True, .AllowSameNames = True}
x.LoadData()
x.DefaultsLoading(False)
If x.Count > 0 Then
Dim XMLDateProvider As New ADateTime(ADateTime.Formats.BaseDateTime)
Name = x.Value(Name_Name)
ID = x.Value(Name_ID)
LatestParsedDate = AConvert(Of Date)(x.Value(Name_Date), XMLDateProvider, Nothing)
If Not PartialLoad Then
With x(Name_PostsNode).XmlIfNothing
If .Count > 0 Then .ForEach(Sub(ee) PostsLatest.Add(New UserPost With {
.ID = ee.Attribute(Name_ID),
.[Date] = AConvert(Of Date)(ee.Attribute(Name_Date).Value, XMLDateProvider, Nothing)}))
End With
End If
End If
End Using
End If
Return True
End Function
Friend Overloads Function Save(Optional ByVal f As SFile = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Boolean Implements ILoaderSaver.Save
Dim XMLDateProvider As New ADateTime(ADateTime.Formats.BaseDateTime)
Using x As New XmlFile With {.AllowSameNames = True, .Name = "Channel"}
x.DefaultsLoading(False)
x.Add(Name_Name, Name)
x.Add(Name_ID, ID)
If Posts.Count > 0 Or PostsLatest.Count > 0 Then
Dim tmpPostList As List(Of UserPost) = Nothing
tmpPostList.ListAddList(Posts).ListAddList(PostsLatest)
tmpPostList.Sort()
LatestParsedDate = tmpPostList.FirstOrDefault(Function(pd) pd.Date.HasValue).Date
x.Add(Name_Date, AConvert(Of String)(LatestParsedDate, XMLDateProvider, String.Empty))
x.Add(Name_PostsNode, String.Empty)
With x(Name_PostsNode)
tmpPostList.Take(200).ToList.ForEach(Sub(p) .Add(New EContainer("Post",
String.Empty,
{
New EAttribute(Name_ID, p.ID),
New EAttribute(Name_Date, AConvert(Of String)(p.Date, XMLDateProvider, String.Empty))
})
)
)
End With
tmpPostList.Clear()
End If
x.Save(File)
End Using
Return True
End Function
#End Region
#Region "IDisposable Support"
Private disposedValue As Boolean = False
Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
If Not disposedValue Then
If disposing Then
Posts.Clear()
PostsLatest.Clear()
Range.Dispose()
If CachePath.Exists(SFO.Path, False) Then CachePath.Delete(SFO.Path, False, False, EDP.SendInLog)
End If
disposedValue = True
End If
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub
Friend Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
End Namespace

View File

@@ -0,0 +1,141 @@
Imports PersonalUtilities.Tools
Imports PersonalUtilities.Forms.Toolbars
Imports SCrawler.API.Base
Imports System.Threading
Namespace API.Reddit
Friend Class ChannelsCollection : Implements ICollection(Of Channel), IMyEnumerator(Of Channel), IChannelLimits, IDisposable
Friend Shared ReadOnly Property ChannelsPath As SFile = $"{SettingsFolderName}\Channels\"
Friend Shared ReadOnly Property ChannelsPathCache As SFile = $"{Settings.GlobalPath.Value.PathWithSeparator}_CachedData\"
Private ReadOnly Channels As List(Of Channel)
Friend ReadOnly Property Downloading As Boolean
Get
If Count > 0 Then
Return Channels.Exists(Function(c) c.Downloading)
Else
Return False
End If
End Get
End Property
#Region "Limits Support"
Friend Property DownloadLimitCount As Integer? Implements IChannelLimits.DownloadLimitCount
<Obsolete("This property cannot be used in collections", True)> Private Property DownloadLimitPost As String Implements IChannelLimits.DownloadLimitPost
Friend Property DownloadLimitDate As Date? Implements IChannelLimits.DownloadLimitDate
Friend Overloads Sub SetLimit(Optional ByVal MaxPost As String = "", Optional ByVal MaxCount As Integer? = Nothing,
Optional ByVal MinDate As Date? = Nothing) Implements IChannelLimits.SetLimit
'DownloadLimitPost = MaxPost
DownloadLimitCount = MaxCount
DownloadLimitDate = MinDate
End Sub
Friend Overloads Sub SetLimit(ByVal Source As IChannelLimits) Implements IChannelLimits.SetLimit
With Source
DownloadLimitCount = .DownloadLimitCount
DownloadLimitDate = .DownloadLimitDate
AutoGetLimits = .AutoGetLimits
End With
End Sub
Friend Property AutoGetLimits As Boolean = True Implements IChannelLimits.AutoGetLimits
#End Region
Friend Sub New()
Channels = New List(Of Channel)
End Sub
Friend Sub Load()
If ChannelsPath.Exists(SFO.Path, False) Then
Dim files As List(Of SFile) = SFile.GetFiles(ChannelsPath, "*.xml")
If files.ListExists Then files.ForEach(Sub(f) Add(f))
End If
End Sub
Friend Sub Update()
If Count > 0 Then Channels.ForEach(Sub(c) c.Save())
End Sub
Friend ReadOnly Property Count As Integer Implements ICollection(Of Channel).Count, IMyEnumerator(Of Channel).MyEnumeratorCount
Get
Return Channels.Count
End Get
End Property
Default Friend ReadOnly Property Item(ByVal Index As Integer) As Channel Implements IMyEnumerator(Of Channel).MyEnumeratorObject
Get
Return Channels(Index)
End Get
End Property
''' <exception cref="ArgumentException"></exception>
Friend ReadOnly Property Find(ByVal ChannelID As String) As Channel
Get
If Count > 0 Then
For i% = 0 To Count - 1
If Item(i).ID = ChannelID Then Return Item(i)
Next
End If
Throw New ArgumentException($"Channel ID [{ChannelID}] does not found in channels collection", "ChannelID") With {.HelpLink = 1}
'Return Nothing
End Get
End Property
Friend Sub DownloadData(ByVal Token As CancellationToken, Optional ByVal SkipExists As Boolean = True,
Optional ByVal p As MyProgress = Nothing)
Try
If Count > 0 Then
Dim t As New List(Of Task)
For Each c As Channel In Channels
If Not c.Downloading Then t.Add(Task.Run(Sub()
c.SetLimit(Me)
c.DownloadData(Token, SkipExists, p)
End Sub))
Next
If t.Count > 0 Then Task.WaitAll(t.ToArray)
Token.ThrowIfCancellationRequested()
End If
Catch oex As OperationCanceledException When Token.IsCancellationRequested
End Try
End Sub
#Region "ICollection Support"
Private ReadOnly Property IsReadOnly As Boolean = False Implements ICollection(Of Channel).IsReadOnly
Friend Sub Add(ByVal _Item As Channel) Implements ICollection(Of Channel).Add
If Not Contains(_Item) Then Channels.Add(_Item)
End Sub
Friend Sub Clear() Implements ICollection(Of Channel).Clear
Channels.ListClearDispose
End Sub
Private Sub CopyTo(ByVal _Array() As Channel, ByVal ArrayIndex As Integer) Implements ICollection(Of Channel).CopyTo
Throw New NotImplementedException()
End Sub
Friend Function Contains(ByVal _Item As Channel) As Boolean Implements ICollection(Of Channel).Contains
Return Count > 0 AndAlso Channels.Contains(_Item)
End Function
Friend Function Remove(ByVal _Item As Channel) As Boolean Implements ICollection(Of Channel).Remove
If Count > 0 Then
Dim i% = Channels.IndexOf(_Item)
If i >= 0 Then
With Channels(i) : .Delete() : .Dispose() : End With
Channels.RemoveAt(i)
Return True
End If
End If
Return False
End Function
#End Region
#Region "IEnumerable Support"
Friend Function GetEnumerator() As IEnumerator(Of Channel) Implements IEnumerable(Of Channel).GetEnumerator
Return New MyEnumerator(Of Channel)(Me)
End Function
Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Return GetEnumerator()
End Function
#End Region
#Region "IDisposable Support"
Private disposedValue As Boolean = False
Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
If Not disposedValue Then
If disposing Then Update() : Clear()
disposedValue = True
End If
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub
Friend Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
End Namespace

View File

@@ -0,0 +1,33 @@
Imports PersonalUtilities.Functions.XML.Base
Namespace API.Reddit
Friend Module Declarations
Friend ReadOnly JsonNodesJson() As NodeParams = {New NodeParams("posts", True, True, True, True, 3)}
Friend ReadOnly ChannelJsonNodes() As NodeParams = {New NodeParams("data", True, True, True, True, 1),
New NodeParams("children", True, True, True)}
Friend ReadOnly UrlBasePattern As New RegexStructure("(?<=/)([^/]+?\.[\w]{3,4})(?=(\?|\Z))", True, False)
Friend ReadOnly VideoRegEx As New RegexStructure("http.{0,1}://[^" & Chr(34) & "]+?mp4", True, False)
Friend ReadOnly DateProvider As New JsonDate
Friend ReadOnly DateProviderChannel As New JsonDateChannel
Private ReadOnly EUR_PROVIDER As New ANumbers(ANumbers.Modes.EUR)
Friend Class JsonDate : Implements ICustomProvider
''' <inheritdoc cref="ADateTime.ParseUnicodeJS(Object, Object, ErrorsDescriber)"/>
Friend Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider,
Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert
Return ADateTime.ParseUnicodeJS(Value, NothingArg, e)
End Function
Private Function GetFormat(ByVal FormatType As Type) As Object Implements IFormatProvider.GetFormat
Throw New NotImplementedException("GetFormat does not available in this context")
End Function
End Class
Friend Class JsonDateChannel : Implements ICustomProvider
''' <inheritdoc cref="ADateTime.ParseUnicodeJS(Object, Object, ErrorsDescriber)"/>
Friend Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider,
Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert
Return ADateTime.ParseUnicode(AConvert(Of Integer)(Value, EUR_PROVIDER, Value), NothingArg, e)
End Function
Private Function GetFormat(ByVal FormatType As Type) As Object Implements IFormatProvider.GetFormat
Throw New NotImplementedException("GetFormat does not available in this context")
End Function
End Class
End Module
End Namespace

100
SCrawler/API/Reddit/M3U8.vb Normal file
View File

@@ -0,0 +1,100 @@
Imports System.Net
Imports SCrawler.API.Reddit.M3U8_Declarations
Imports PersonalUtilities.Tools.WEB
Namespace API.Reddit.M3U8_Declarations
Friend Module M3U8_Declarations
Friend ReadOnly BaseUrlPattern As New RegexStructure("([htps:/]{7,8}.+?/.+?)(?=/)", True, False,,,,,, EDP.ReturnValue)
Friend ReadOnly PlayListRegEx_1 As New RegexStructure("(#EXT-X-STREAM-INF)(.+)(RESOLUTION=)(\d+)(.+?[\r\n]{1,2})(.+?)([\r\n]{1,2})", True, False,,,
RegexReturn.List,, New List(Of String),
New ErrorsDescriber(False, False, True, New List(Of String)))
Friend ReadOnly PlayListRegEx_2 As New RegexStructure("(?<=#EXT-X-BYTERANGE.+?[\r\n]{1,2})(.+)(?=[\r\n]{0,2})", True, False,,, RegexReturn.List,,
New List(Of String),
New ErrorsDescriber(False, False, True, New List(Of String)))
Friend ReadOnly DPED As New ErrorsDescriber(EDP.SendInLog + EDP.ReturnValue)
End Module
End Namespace
Namespace API.Reddit
Friend NotInheritable Class M3U8
Private Sub New()
End Sub
Private Structure Resolution : Implements IRegExCreator, IComparable(Of Resolution)
Friend File As String
Friend Resolution As Integer
Friend Function CreateFromArray(ByVal ParamsArray() As String) As IRegExCreator Implements IRegExCreator.CreateFromArray
If ParamsArray.ArrayExists Then
File = ParamsArray(0)
If ParamsArray.Length > 1 Then Resolution = AConvert(Of Integer)(ParamsArray(1), 0)
End If
Return Me
End Function
Friend Function CompareTo(ByVal Other As Resolution) As Integer Implements IComparable(Of Resolution).CompareTo
Return Resolution.CompareTo(Other.Resolution) * -1
End Function
End Structure
Private Shared Function GetPlaylistUrls(ByVal PlayListURL As String, ByVal BaseUrl As String) As List(Of String)
Try
If Not BaseUrl.IsEmptyString Then
Using w As New WebClient
Dim r$ = w.DownloadString(PlayListURL)
If Not r.IsEmptyString Then
Dim l As List(Of Resolution) = RegexFields(Of Resolution)(r, {PlayListRegEx_1}, {6, 4})
If l.ListExists Then
l.Sort()
Dim pls$ = $"{BaseUrl}/{l.First.File}"
r = w.DownloadString(pls)
If Not r.IsEmptyString Then
Dim lp As New ListAddParams(LAP.NotContainsOnly) With {
.Converter = Function(input) $"{BaseUrl}/{input}",
.e = New ErrorsDescriber(False, False, True, New List(Of String))}
Return ListAddList(Of String, List(Of String))(Nothing, DirectCast(RegexReplace(r, PlayListRegEx_2), List(Of String)), lp).ListIfNothing
End If
End If
End If
End Using
End If
Return New List(Of String)
Catch ex As Exception
Return ErrorsDescriber.Execute(DPED, ex, "[M3U8.GetPlaylistUrls]", New List(Of String))
End Try
End Function
Private Shared Function Save(ByVal URLs As List(Of String), ByVal f As SFile) As SFile
Dim CachePath As SFile = Nothing
Try
If URLs.ListExists Then
Dim ConcatFile As SFile = f
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(ANumbers.Modes.USA) With {.GroupSeparator = String.Empty, .FormatMode = 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 = New SFile(URLs(0)).Extension
If dFile.Extension.IsEmptyString Then 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, "ffmpeg.exe", ConcatFile, p, DPED)
eFiles.Clear()
Return f
End If
End If
Return Nothing
Catch ex As Exception
Return ErrorsDescriber.Execute(DPED, ex, "[M3U8.Save]", New SFile)
Finally
If Not CachePath.IsEmptyString AndAlso CachePath.Exists(SFO.Path, False) Then CachePath.Delete(SFO.Path, False, False, DPED)
End Try
End Function
Friend Shared Function Download(ByVal URL As String, ByVal f As SFile) As SFile
Dim BaseUrl$ = RegexReplace(URL, BaseUrlPattern)
Return Save(GetPlaylistUrls(URL, BaseUrl), f)
End Function
End Class
End Namespace

View File

@@ -0,0 +1,468 @@
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Forms.Toolbars
Imports PersonalUtilities.Tools.ImageRenderer
Imports PersonalUtilities.Tools.WebDocuments.JSON
Imports System.Net
Imports System.Threading
Imports SCrawler.API.Base
Imports UStates = SCrawler.API.Base.UserMedia.States
Imports UTypes = SCrawler.API.Base.UserMedia.Types
Namespace API.Reddit
Friend Class UserData : Inherits UserDataBase : Implements IChannelData
Friend Overrides Property Site As Sites = Sites.Reddit
#Region "Channels Support"
#Region "IChannelLimits Support"
Friend Property DownloadLimitCount As Integer? Implements IChannelLimits.DownloadLimitCount
Friend Property DownloadLimitPost As String Implements IChannelLimits.DownloadLimitPost
Friend Property DownloadLimitDate As Date? Implements IChannelLimits.DownloadLimitDate
Friend Overloads Sub SetLimit(Optional ByVal MaxPost As String = "", Optional ByVal MaxCount As Integer? = Nothing,
Optional ByVal MinDate As Date? = Nothing) Implements IChannelLimits.SetLimit
DownloadLimitPost = MaxPost
DownloadLimitCount = MaxCount
DownloadLimitDate = MinDate
End Sub
Friend Overloads Sub SetLimit(ByVal Source As IChannelLimits) Implements IChannelLimits.SetLimit
With Source
DownloadLimitCount = .DownloadLimitCount
DownloadLimitPost = .DownloadLimitPost
DownloadLimitDate = .DownloadLimitDate
AutoGetLimits = .AutoGetLimits
End With
End Sub
Friend Property AutoGetLimits As Boolean = True Implements IChannelLimits.AutoGetLimits
#End Region
Friend Property ChannelInfo As Channel
Private ReadOnly ChannelPostsNames As New List(Of String)
Friend Property SkipExistsUsers As Boolean = True Implements IChannelData.SkipExistsUsers
Private ReadOnly _ExistsUsersNames As List(Of String)
Friend Property SaveToCache As Boolean = False Implements IChannelData.SaveToCache
Friend Function GetNewChannelPosts() As IEnumerable(Of UserPost)
If _ContentNew.Count > 0 Then Return (From c As UserMedia In _ContentNew
Where Not c.Post.CachedFile.IsEmptyString And c.State = UStates.Downloaded
Select c.Post) Else Return Nothing
End Function
#End Region
Private _Progress As MyProgress
Friend Property Progress As MyProgress
Get
If _Progress Is Nothing Then Return MainProgress Else Return _Progress
End Get
Set(ByVal p As MyProgress)
_Progress = p
End Set
End Property
#Region "Initializers"
''' <summary>Video downloader initializer</summary>
Private Sub New()
End Sub
''' <summary>Default initializer</summary>
Friend Sub New(ByVal u As UserInfo, Optional ByVal _LoadUserInformation As Boolean = True, Optional ByVal InvokeImageHandler As Boolean = True)
MyBase.New(InvokeImageHandler)
ChannelPostsNames = New List(Of String)
_ExistsUsersNames = New List(Of String)
User = u
If _LoadUserInformation Then LoadUserInformation()
End Sub
#End Region
#Region "Download Overrides"
Friend Overrides Sub DownloadData(ByVal Token As CancellationToken)
If IsChannel Then
ChannelPostsNames.ListAddList(ChannelInfo.PostsAll.Select(Function(p) p.ID), LNC)
If SkipExistsUsers Then _ExistsUsersNames.ListAddList(Settings.UsersList.Select(Function(p) p.Name), LNC)
DownloadDataF(Token)
ReparseVideo(Token)
_ContentNew.ListAddList(_TempMediaList, LAP.ClearBeforeAdd)
DownloadContent(Token)
Else
MyBase.DownloadData(Token)
End If
End Sub
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
If IsChannel Then
_DownloadedChannelPosts = 0
DownloadDataChannel(String.Empty, Token)
Else
DownloadDataUser(String.Empty, Token)
End If
End Sub
#End Region
#Region "Download Functions (User, Channel)"
Private Sub DownloadDataUser(ByVal POST As String, ByVal Token As CancellationToken)
Dim URL$ = String.Empty
Try
Dim PostID$ = String.Empty
Dim PostDate$
Dim n As EContainer, nn As EContainer, s As EContainer
Dim NewPostDetected As Boolean = False
Dim ExistsDetected As Boolean = False
Dim _ItemsBefore%
Dim added As Boolean
Dim __ItemType$
Dim tmpType As UTypes
Dim CheckNode As Predicate(Of EContainer) = Function(e) e("author").XmlIfNothingValue("/").ToLower.Equals(Name.ToLower)
Dim UPicType As Func(Of String, UTypes) = Function(input) IIf(input = "image", UTypes.Picture, UTypes.GIF)
URL = $"https://gateway.reddit.com/desktopapi/v1/user/{Name}/posts?rtj=only&allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort=new&t=all&layout=classic"
Token.ThrowIfCancellationRequested()
Dim r$ = GetSiteResponse(URL)
If Not r.IsEmptyString Then
Using w As EContainer = JsonDocument.Parse(r)
If w.Count > 0 Then
n = w.GetNode(JsonNodesJson)
If Not n Is Nothing AndAlso n.Count > 0 Then
For Each nn In n
Token.ThrowIfCancellationRequested()
If nn.Count > 0 Then
PostID = nn.Name
If PostID.IsEmptyString AndAlso nn.Contains("id") Then PostID = nn("id").Value
If nn.Contains("created") Then PostDate = nn("created").Value Else PostDate = String.Empty
If Not _TempPostsList.Contains(PostID) Then
NewPostDetected = True
_TempPostsList.Add(PostID)
Else
ExistsDetected = True
Continue For
End If
If CheckNode(nn) Then
_ItemsBefore = _TempMediaList.Count
added = True
s = nn.ItemF({"source", "url"})
If s.XmlIfNothingValue("/").Contains("redgifs.com") Then
_TempMediaList.ListAddValue(MediaFromData(UTypes.VideoPre, s.Value, PostID, PostDate,, IsChannel), LNC)
Else
s = nn.ItemF({"media"}).XmlIfNothing
__ItemType = s("type").XmlIfNothingValue
Select Case __ItemType
Case "gallery" : DownloadGallery(s, PostID, PostDate)
Case "image", "gifvideo"
If s.Contains("content") Then _
_TempMediaList.ListAddValue(MediaFromData(UPicType(__ItemType), s.Value("content"),
PostID, PostDate,, IsChannel), LNC)
Case "video"
If s("hlsUrl").XmlIfNothingValue("/").ToLower.Contains("m3u8") Then _
_TempMediaList.ListAddValue(MediaFromData(UTypes.m3u8, s.Value("hlsUrl"),
PostID, PostDate,, IsChannel), LNC)
Case Else : added = False
End Select
End If
If Not added Then
s = nn.ItemF({"source", "url"}).XmlIfNothing
If Not s.IsEmptyString AndAlso TryFile(s.Value) Then
With s.Value.ToLower
Select Case True
Case .Contains("redgifs") : tmpType = UTypes.VideoPre
Case .Contains("m3u8") : tmpType = UTypes.m3u8
Case .Contains(".gif") And TryFile(s.Value) : tmpType = UTypes.GIF
Case TryFile(s.Value) : tmpType = UTypes.Picture
Case Else : tmpType = UTypes.Undefined
End Select
End With
If Not tmpType = UTypes.Undefined Then _
_TempMediaList.ListAddValue(MediaFromData(tmpType, s.Value, PostID, PostDate,, IsChannel), LNC)
End If
End If
End If
End If
Next
End If
End If
End Using
If POST.IsEmptyString And ExistsDetected Then Exit Sub
If Not PostID.IsEmptyString And NewPostDetected Then DownloadDataUser(PostID, Token)
End If
Catch oex As OperationCanceledException When Token.IsCancellationRequested
Catch ex As Exception
LogError(ex, $"data downloading error [{URL}]")
HasError = True
End Try
End Sub
Private _DownloadedChannelPosts As Integer = 0
Private Sub DownloadDataChannel(ByVal POST As String, ByVal Token As CancellationToken)
Dim URL$ = String.Empty
Try
Dim PostID$ = String.Empty
Dim PostDate$, _UserID$, tmpUrl$
Dim n As EContainer, nn As EContainer, s As EContainer, ss As EContainer
Dim NewPostDetected As Boolean = False
Dim ExistsDetected As Boolean = False
Dim eCount As Predicate(Of EContainer) = Function(e) e.Count > 0
Dim lDate As Date?
URL = $"https://reddit.com/r/{Name}/new.json?allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort=new&t=all&layout=classic"
Token.ThrowIfCancellationRequested()
Dim r$ = GetSiteResponse(URL)
If Not r.IsEmptyString Then
Using w As EContainer = JsonDocument.Parse(r).XmlIfNothing
If w.Count > 0 Then
n = w.GetNode(ChannelJsonNodes)
If Not n Is Nothing AndAlso n.Count > 0 Then
For Each nn In n
Token.ThrowIfCancellationRequested()
s = nn.ItemF({eCount})
If Not s Is Nothing AndAlso s.Count > 0 Then
PostID = s.Value("name")
If PostID.IsEmptyString AndAlso s.Contains("id") Then PostID = s("id").Value
If ChannelPostsNames.Contains(PostID) Then ExistsDetected = True : Continue For 'Exit Sub
If DownloadLimitCount.HasValue AndAlso _DownloadedChannelPosts >= DownloadLimitCount.Value Then Exit Sub
If Not DownloadLimitPost.IsEmptyString AndAlso DownloadLimitPost = PostID Then Exit Sub
If DownloadLimitDate.HasValue AndAlso _TempMediaList.Count > 0 Then
With (From __u In _TempMediaList Where __u.Post.Date.HasValue Select __u.Post.Date.Value)
If .Count > 0 Then lDate = .Min Else lDate = Nothing
End With
If lDate.HasValue AndAlso lDate.Value <= DownloadLimitDate.Value Then Exit Sub
End If
NewPostDetected = True
If s.Contains("created") Then PostDate = s("created").Value Else PostDate = String.Empty
_UserID = s.Value("author")
If SkipExistsUsers AndAlso _ExistsUsersNames.Count > 0 AndAlso
Not _UserID.IsEmptyString AndAlso _ExistsUsersNames.Contains(_UserID) Then Continue For
tmpUrl = s.Value("url")
If Not tmpUrl.IsEmptyString AndAlso tmpUrl.Contains("redgifs.com") Then
If SaveToCache Then
tmpUrl = s.Value({"media", "oembed"}, "thumbnail_url")
If Not tmpUrl.IsEmptyString Then
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, tmpUrl, PostID, PostDate, _UserID, IsChannel), LNC)
_DownloadedChannelPosts += 1
End If
Else
_TempMediaList.ListAddValue(MediaFromData(UTypes.VideoPre, tmpUrl, PostID, PostDate, _UserID, IsChannel), LNC)
_DownloadedChannelPosts += 1
End If
ElseIf s.Item("media_metadata").XmlIfNothing.Count > 0 Then
DownloadGallery(s, PostID, PostDate, _UserID, SaveToCache)
_DownloadedChannelPosts += 1
ElseIf s.Contains("preview") Then
ss = s.ItemF({"preview", "images", eCount, "source", "url"}).XmlIfNothing
If Not ss.Value.IsEmptyString Then
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, ss.Value, PostID, PostDate, _UserID, IsChannel), LNC)
_DownloadedChannelPosts += 1
End If
End If
End If
Next
End If
End If
End Using
If POST.IsEmptyString And ExistsDetected Then Exit Sub
If Not PostID.IsEmptyString And NewPostDetected Then DownloadDataChannel(PostID, Token)
End If
Catch oex As OperationCanceledException When Token.IsCancellationRequested
Catch ex As Exception
LogError(ex, $"channel data downloading error [{URL}]")
HasError = True
End Try
End Sub
#End Region
#Region "Download Base Functions"
Private Sub DownloadGallery(ByVal w As EContainer, ByVal PostID As String, ByVal PostDate As String,
Optional ByVal _UserID As String = Nothing, Optional ByVal FirstOnly As Boolean = False)
Try
Dim cn$ = IIf(IsChannel, "media_metadata", "mediaMetadata")
If Not w Is Nothing AndAlso w(cn).XmlIfNothing.Count > 0 Then
Dim t As EContainer
For Each n As EContainer In w(cn)
t = n.ItemF({"s", "u"})
If Not t Is Nothing AndAlso Not t.Value.IsEmptyString Then
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, t.Value, PostID, PostDate, _UserID, IsChannel), LNC)
If FirstOnly Then Exit For
End If
Next
End If
Catch ex As Exception
LogError(ex, "gallery parsing error")
HasError = True
End Try
End Sub
Protected Overrides Sub ReparseVideo(ByVal Token As CancellationToken)
Try
Token.ThrowIfCancellationRequested()
If _TempMediaList.Count > 0 AndAlso _TempMediaList.Exists(Function(p) p.Type = UTypes.VideoPre) Then
Dim r$, v$
Dim m As UserMedia
For i% = _TempMediaList.Count - 1 To 0 Step -1
Token.ThrowIfCancellationRequested()
If _TempMediaList(i).Type = UTypes.VideoPre Then
m = _TempMediaList(i)
r = GetSiteResponse(m.URL)
_TempMediaList(i) = New UserMedia
If Not r.IsEmptyString Then
v = RegexReplace(r, VideoRegEx)
If Not v.IsEmptyString Then
_TempMediaList(i) = New UserMedia With {.Type = UTypes.Video, .URL = v, .File = v, .Post = m.Post}
Else
_TempMediaList.RemoveAt(i)
End If
End If
End If
Next
End If
Catch oex As OperationCanceledException When Token.IsCancellationRequested
Catch ex As Exception
LogError(ex, "video reparsing error")
End Try
End Sub
Friend Shared Function GetVideoInfo(ByVal URL As String) As UserMedia
Try
If Not URL.IsEmptyString AndAlso URL.Contains("redgifs") Then
Using r As New UserData
r._TempMediaList.Add(MediaFromData(UTypes.VideoPre, URL, String.Empty, String.Empty,, False))
r.ReparseVideo(Nothing)
If r._TempMediaList.ListExists Then Return r._TempMediaList(0)
End Using
End If
Return Nothing
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.ShowMainMsg + EDP.SendInLog, ex, "Video searching error")
End Try
End Function
#End Region
#Region "Structure creator"
Protected Shared Function MediaFromData(ByVal t As UTypes, ByVal _URL As String, ByVal PostID As String, ByVal PostDate As String,
Optional ByVal _UserID As String = "", Optional ByVal IsChannel As Boolean = False) As UserMedia
If _URL.IsEmptyString And t = UTypes.Picture Then Return Nothing
_URL = LinkFormatterSecure(RegexReplace(_URL.Replace("\", String.Empty), LinkPattern))
Dim m As New UserMedia(_URL, t) With {.Post = New UserPost With {.ID = PostID, .UserID = _UserID}}
If t = UTypes.Picture Or t = UTypes.GIF Then m.File = CStr(RegexReplace(m.URL, FilesPattern)) Else m.File = Nothing
If m.URL.Contains("preview") Then m.URL = $"https://i.redd.it/{m.File.File}"
If Not PostDate.IsEmptyString Then m.Post.Date = AConvert(Of Date)(PostDate, If(IsChannel, DateProviderChannel, DateProvider), Nothing) Else m.Post.Date = Nothing
Return m
End Function
Private Function TryFile(ByVal URL As String) As Boolean
Try
If Not URL.IsEmptyString AndAlso URL.Contains(".jpg") Then
Dim f As SFile = CStr(RegexReplace(URL, FilesPattern))
Return Not f.IsEmptyString And Not f.File.IsEmptyString
End If
Return False
Catch ex As Exception
Return False
End Try
End Function
#End Region
Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
Try
Dim i%
Token.ThrowIfCancellationRequested()
If _ContentNew.Count > 0 Then
_ContentNew.RemoveAll(Function(c) c.URL.IsEmptyString)
If _ContentNew.Count > 0 Then
MyFile.Exists(SFO.Path)
Dim MyDir$
If IsChannel And SaveToCache Then
MyDir = ChannelInfo.CachePath.PathNoSeparator
Else
MyDir = MyFile.CutPath.PathNoSeparator
End If
Dim HashList As New List(Of String)
If _ContentList.Count > 0 Then HashList.ListAddList((From h In _ContentList Where Not h.MD5.IsEmptyString Select h.MD5), LNC)
Dim f As SFile
Dim v As UserMedia
Dim cached As Boolean = IsChannel And SaveToCache
Dim vsf As Boolean = SeparateVideoFolderF
Dim ImgFormat As Imaging.ImageFormat
Dim bDP As New ErrorsDescriber(EDP.None)
Dim MD5BS As Func(Of String, UTypes,
SFile, Boolean, String) = Function(ByVal __URL As String, ByVal __MT As UTypes,
ByVal __File As SFile, ByVal __IsBase As Boolean) As String
Try
If __MT = UTypes.GIF Then
ImgFormat = Imaging.ImageFormat.Gif
ElseIf __IsBase Then
ImgFormat = GetImageFormat(CStr(RegexReplace(__URL, UrlBasePattern)))
Else
ImgFormat = GetImageFormat(__File)
End If
Return ByteArrayToString(GetMD5(SFile.GetBytesFromNet(__URL, bDP), ImgFormat))
Catch hash_ex As Exception
Return String.Empty
End Try
End Function
Dim m$
Using w As New WebClient
If vsf Then SFileShares.SFileExists($"{MyDir}\Video\", SFO.Path)
Progress.TotalCount += _ContentNew.Count
For i = 0 To _ContentNew.Count - 1
Token.ThrowIfCancellationRequested()
v = _ContentNew(i)
v.State = UStates.Tried
If v.Type = UTypes.Picture Then v.File = v.URL
If v.File.IsEmptyString Then
f = v.URL
Else
f = v.File
End If
f.Separator = "\"
m = String.Empty
If (v.Type = UTypes.Picture Or v.Type = UTypes.GIF) And Not cached Then
m = MD5BS(v.URL, v.Type, f, False)
If m.IsEmptyString AndAlso Not v.URL_BASE.IsEmptyString AndAlso Not v.URL_BASE = v.URL Then
m = MD5BS(v.URL_BASE, v.Type, f, True)
If Not m.IsEmptyString Then v.URL = v.URL_BASE
End If
End If
If (Not m.IsEmptyString AndAlso Not HashList.Contains(m)) Or Not (v.Type = UTypes.Picture Or
v.Type = UTypes.GIF) Or cached Then
If Not cached Then HashList.Add(m)
v.MD5 = m
f.Path = MyDir
Try
If (v.Type = UTypes.Video Or v.Type = UTypes.m3u8) And vsf Then f.Path = $"{f.PathWithSeparator}Video"
If v.Type = UTypes.m3u8 Then
f = M3U8.Download(v.URL, f)
Else
w.DownloadFile(v.URL, f.ToString)
End If
If Not v.Type = UTypes.m3u8 Or Not f.IsEmptyString Then
Select Case v.Type
Case UTypes.Picture : DownloadedPictures += 1 : _CountPictures += 1
Case UTypes.Video, UTypes.m3u8 : DownloadedVideos += 1 : _CountVideo += 1
End Select
v.File = f
v.Post.CachedFile = f
v.State = UStates.Downloaded
End If
Catch wex As Exception
If Not IsChannel Then ErrorDownloading(f, v.URL)
End Try
Else
v.State = UStates.Skipped
End If
_ContentNew(i) = v
Progress.Perform()
Next
End Using
End If
End If
Catch oex As OperationCanceledException When Token.IsCancellationRequested
Catch ex As Exception
LogError(ex, "content downloading error")
HasError = True
End Try
End Sub
Protected Function GetSiteResponse(ByVal URL As String) As String
Try
Return Settings.Site(Sites.Reddit).Responser.GetResponse(URL,, EDP.ThrowException)
Catch ex As Exception
HasError = True
Dim e As EDP = EDP.SendInLog
Dim OptText$ = String.Empty
If Settings.Site(Sites.Reddit).Responser.StatusCode = HttpStatusCode.NotFound Then
e += EDP.ThrowException
OptText = ": USER NOT FOUND"
Else
e += EDP.ReturnValue
End If
Return ErrorsDescriber.Execute(e, ex, $"[{Site} - {Name}: GetSiteResponse([{URL}])]{OptText}", String.Empty)
End Try
End Function
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If Not disposedValue And disposing Then ChannelPostsNames.Clear() : _ExistsUsersNames.Clear()
MyBase.Dispose(disposing)
End Sub
End Class
End Namespace

View File

@@ -0,0 +1,9 @@
Imports PersonalUtilities.Functions.XML.Base
Namespace API.Twitter
Friend Module Declarations
Friend DateProvider As New ADateTime(ADateTime.Formats.BaseDateTime)
Friend ReadOnly VideoNode As NodeParams() = {New NodeParams("video_info", True, True, True, True, 10)}
Friend ReadOnly VideoSizeRegEx As New RegexStructure("\d+x(\d+)",,,, 1,,, String.Empty, EDP.ReturnValue)
Friend ReadOnly UserIdRegEx As New RegexStructure("user_id.:.(\d+)",,,, 1,,, String.Empty, EDP.ReturnValue)
End Module
End Namespace

View File

@@ -0,0 +1,264 @@
Imports PersonalUtilities.Tools.WebDocuments.JSON
Imports PersonalUtilities.Functions.XML
Imports System.Net
Imports System.Threading
Imports SCrawler.API.Base
Imports UStates = SCrawler.API.Base.UserMedia.States
Namespace API.Twitter
Friend Class UserData : Inherits UserDataBase
#Region "Declarations"
Friend Overrides Property Site As Sites = Sites.Twitter
Private Structure Sizes : Implements IComparable(Of Sizes)
Friend Value As Integer
Friend Name As String
Friend ReadOnly HasError As Boolean
Friend Sub New(ByVal _Value As String, ByVal _Name As String)
Try
Value = _Value
Name = _Name
Catch ex As Exception
HasError = True
End Try
End Sub
Friend Function CompareTo(ByVal Other As Sizes) As Integer Implements IComparable(Of Sizes).CompareTo
Return Value.CompareTo(Other.Value) * -1
End Function
Friend Shared Function Reparse(ByRef Current As Sizes, ByVal Other As Sizes, ByVal LargeContained As Boolean) As Sizes
If LargeContained And Current.Name.IsEmptyString And Current.Value > Other.Value Then Current.Name = "large"
Return Current
End Function
Friend Shared Function ApplyLarge(ByRef s As Sizes) As Sizes
s.Name = "large"
Return s
End Function
End Structure
#End Region
#Region "Initializer"
Friend Sub New(ByVal u As UserInfo, Optional ByVal _LoadUserInformation As Boolean = True)
User = u
If _LoadUserInformation Then LoadUserInformation()
End Sub
#End Region
#Region "Download functions"
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
DownloadData(String.Empty, Token)
End Sub
Private Overloads Sub DownloadData(ByVal POST As String, ByVal Token As CancellationToken)
Dim URL$ = String.Empty
Try
Dim PostID$ = String.Empty
Dim PostDate$
Dim m As EContainer, nn As EContainer, s As EContainer
Dim NewPostDetected As Boolean = False
Dim ExistsDetected As Boolean = False
Dim PicNode As Predicate(Of EContainer) = Function(e) e.Count > 0 AndAlso e.Contains("media_url")
Dim UID As Func(Of EContainer, String) = Function(e) e.XmlIfNothing.Item({"user", "id"}).XmlIfNothingValue
URL = $"https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name={Name}&count=200&exclude_replies=false&include_rts=1&tweet_mode=extended"
If Not POST.IsEmptyString Then URL &= $"&max_id={POST}"
Token.ThrowIfCancellationRequested()
Dim r$ = Settings.Site(Sites.Twitter).Responser.GetResponse(URL,, EDP.ThrowException)
If Not r.IsEmptyString Then
Using w As EContainer = JsonDocument.Parse(r)
If Not w Is Nothing AndAlso w.Count > 0 Then
For Each nn In w
Token.ThrowIfCancellationRequested()
If nn.Count > 0 Then
PostID = nn.Value("id")
If ID.IsEmptyString Then
ID = UID(nn)
If Not ID.IsEmptyString Then UpdateUserInformation()
End If
'Date Pattern:
'Sat Jan 01 01:10:15 +0000 2000
If nn.Contains("created_at") Then PostDate = nn("created_at").Value Else PostDate = String.Empty
If Not _TempPostsList.Contains(PostID) Then
NewPostDetected = True
_TempPostsList.Add(PostID)
Else
ExistsDetected = True
Continue For
End If
If Not ParseUserMediaOnly OrElse (Not nn.Contains("retweeted_status") OrElse
(Not ID.IsEmptyString AndAlso UID(nn("retweeted_status")) = ID)) Then
If Not CheckVideoNode(nn, PostID, PostDate) Then
s = nn.ItemF({"extended_entities", "media"})
If s Is Nothing OrElse s.Count = 0 Then s = nn.ItemF({"retweeted_status", "extended_entities", "media"})
If Not s Is Nothing AndAlso s.Count > 0 Then
For Each m In s
If m.Count > 0 AndAlso m.Contains("media_url") Then
_TempMediaList.ListAddValue(MediaFromData(m("media_url").Value,
PostID, PostDate, GetPictureOption(m)), LNC)
End If
Next
End If
End If
End If
End If
Next
End If
End Using
If POST.IsEmptyString And ExistsDetected Then Exit Sub
If Not PostID.IsEmptyString And NewPostDetected Then DownloadData(PostID, Token)
End If
Catch oex As OperationCanceledException When Token.IsCancellationRequested
Catch ex As Exception
LogError(ex, $"data downloading error [{URL}]")
HasError = True
End Try
End Sub
Friend Shared Function GetVideoInfo(ByVal URL As String) As UserMedia
Try
If URL.Contains("twitter") Then
Dim PostID$ = RegexReplace(URL, New RegexStructure("(?<=/)\d+", True, False,,,,, String.Empty))
If Not PostID.IsEmptyString Then
Dim r$ = Settings.Site(Sites.Twitter).Responser.GetResponse($"https://api.twitter.com/1.1/statuses/show.json?id={PostID}",,
EDP.ReturnValue)
If Not r.IsEmptyString Then
Using j As EContainer = JsonDocument.Parse(r)
If j.ListExists Then
Dim u$ = GetVideoNodeURL(j)
If Not u.IsEmptyString Then Return MediaFromData(u, PostID, String.Empty)
End If
End Using
End If
End If
End If
Return Nothing
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.ShowMainMsg + EDP.SendInLog, ex, "Video searching error")
End Try
End Function
#Region "Picture options"
Private Function GetPictureOption(ByVal w As EContainer) As String
Try
Dim ww As EContainer = w("sizes")
If Not ww Is Nothing AndAlso ww.Count > 0 Then
Dim l As New List(Of Sizes)
Dim LargeContained As Boolean = ww.Contains("large")
For Each v As EContainer In ww
If v.Count > 0 AndAlso v.Contains("h") Then l.Add(New Sizes(v.Value("h"), v.Name))
Next
If l.Count > 0 Then
l.Sort()
If l(0).Name.IsEmptyString And LargeContained Then Return "large" Else Return l(0).Name
End If
End If
Return String.Empty
Catch ex As Exception
LogError(ex, "[GetPictureOption]")
Return String.Empty
End Try
End Function
#End Region
#Region "Video options"
Private Function CheckVideoNode(ByVal w As EContainer, ByVal PostID As String, ByVal PostDate As String) As Boolean
Try
Dim URL$ = GetVideoNodeURL(w)
If Not URL.IsEmptyString Then _TempMediaList.ListAddValue(MediaFromData(URL, PostID, PostDate), LNC) : Return True
Return False
Catch ex As Exception
LogError(ex, "[CheckVideoNode]")
Return False
End Try
End Function
Private Shared Function GetVideoNodeURL(ByVal w As EContainer) As String
Dim v As EContainer = w.GetNode(VideoNode)
If Not v Is Nothing AndAlso v.Count > 0 Then
Dim l As New List(Of Sizes)
Dim u$
Dim nn As EContainer
For Each n As EContainer In v
If n.Count > 0 Then
For Each nn In n
If nn("content_type").XmlIfNothingValue("none").Contains("mp4") AndAlso nn.Contains("url") Then
u = nn.Value("url")
l.Add(New Sizes(RegexReplace(u, VideoSizeRegEx), u))
End If
Next
End If
Next
If l.Count > 0 Then l.RemoveAll(Function(s) s.HasError)
If l.Count > 0 Then l.Sort() : Return l(0).Name
End If
Return String.Empty
End Function
Protected Overrides Sub ReparseVideo(ByVal Token As CancellationToken)
End Sub
#End Region
Private Shared Function MediaFromData(ByVal _URL As String, ByVal PostID As String, ByVal PostDate As String,
Optional ByVal _PictureOption As String = "") As UserMedia
_URL = LinkFormatterSecure(RegexReplace(_URL.Replace("\", String.Empty), LinkPattern))
Dim m As New UserMedia(_URL) With {.PictureOption = _PictureOption, .Post = New UserPost With {.ID = PostID}}
If Not m.URL.IsEmptyString Then m.File = CStr(RegexReplace(m.URL, FilesPattern))
If Not m.PictureOption.IsEmptyString And Not m.File.IsEmptyString And Not m.URL.IsEmptyString Then
m.URL_BASE = $"{m.URL.Replace($".{m.File.Extension}", String.Empty)}?format={m.File.Extension}&name={m.PictureOption}"
End If
If Not PostDate.IsEmptyString Then m.Post.Date = AConvert(Of Date)(PostDate, Declarations.DateProvider, Nothing) Else m.Post.Date = Nothing
Return m
End Function
#End Region
Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
Try
Dim i%
Token.ThrowIfCancellationRequested()
If _ContentNew.Count > 0 Then
_ContentNew.RemoveAll(Function(c) c.URL.IsEmptyString)
If _ContentNew.Count > 0 Then
MyFile.Exists(SFO.Path)
Dim MyDir$ = MyFile.CutPath.Path
Dim vsf As Boolean = SeparateVideoFolderF
Dim f As SFile
Dim v As UserMedia
Using w As New WebClient
If vsf Then SFileShares.SFileExists($"{MyDir}\Video\", SFO.Path)
MainProgress.TotalCount += _ContentNew.Count
For i = 0 To _ContentNew.Count - 1
Token.ThrowIfCancellationRequested()
v = _ContentNew(i)
v.State = UStates.Tried
If v.File.IsEmptyString Then
f = v.URL
Else
f = v.File
End If
f.Separator = "\"
f.Path = MyDir
If v.URL_BASE.IsEmptyString Then v.URL_BASE = v.URL
If Not v.File.IsEmptyString AndAlso Not v.URL_BASE.IsEmptyString Then
Try
If f.Extension = "mp4" And vsf Then f.Path = $"{f.PathWithSeparator}Video"
w.DownloadFile(v.URL_BASE, f.ToString)
Select Case f.Extension
Case "mp4" : v.Type = UserMedia.Types.Video : DownloadedVideos += 1 : _CountVideo += 1
Case Else : v.Type = UserMedia.Types.Picture : DownloadedPictures += 1 : _CountPictures += 1
End Select
v.File = f
v.State = UStates.Downloaded
Catch wex As Exception
ErrorDownloading(f, v.URL_BASE)
End Try
Else
v.State = UStates.Skipped
End If
_ContentNew(i) = v
MainProgress.Perform()
Next
End Using
End If
End If
Catch oex As OperationCanceledException When Token.IsCancellationRequested
Catch ex As Exception
LogError(ex, "content downloading error")
HasError = True
End Try
End Sub
End Class
End Namespace

View File

@@ -0,0 +1,471 @@
Imports PersonalUtilities.Tools
Imports System.Threading
Imports SCrawler.API.Base
Namespace API
Friend Class UserDataBind : Inherits UserDataBase : Implements ICollection(Of IUserData), IMyEnumerator(Of IUserData)
Friend Event OnCollectionSelfRemoved()
#Region "Declarations"
Friend Overrides Property Site As Sites = Sites.Undefined
Friend ReadOnly Property Collections As List(Of IUserData)
Private _CollectionName As String = String.Empty
Friend Overrides Property CollectionName As String
Get
If Count > 0 Then
Return Collections(0).CollectionName
Else
Return _CollectionName
End If
End Get
Set(ByVal NewName As String)
ChangeCollectionName(NewName, True)
End Set
End Property
Friend Overrides Sub ChangeCollectionName(ByVal NewName As String, ByVal UpdateSettings As Boolean)
_CollectionName = NewName
If Count > 0 Then Collections.ForEach(Sub(c) c.CollectionName = NewName)
End Sub
Friend Overrides Property FriendlyName As String
Get
If Count > 0 Then
Return Collections(0).FriendlyName
Else
Return String.Empty
End If
End Get
Set(ByVal NewName As String)
If Count > 0 Then Collections.ForEach(Sub(c)
c.FriendlyName = NewName
c.UpdateUserInformation()
End Sub)
End Set
End Property
#Region "Images"
Friend Overrides Sub SetPicture(ByVal f As SFile)
If Count > 0 Then Collections.ForEach(Sub(c) c.SetPicture(f))
End Sub
Friend Overrides Function GetUserPicture() As Image
If Count > 0 Then
Return Collections(0).GetPicture
Else
Return GetNullPicture(Settings.MaxLargeImageHeigh)
End If
End Function
#End Region
Friend Overrides ReadOnly Property DownloadedTotal(Optional ByVal Total As Boolean = True) As Integer
Get
If Count > 0 Then
Return Collections.Select(Function(u) u.DownloadedTotal(Total)).Sum
Else
Return 0
End If
End Get
End Property
Friend ReadOnly Property Count As Integer Implements ICollection(Of IUserData).Count, IMyEnumerator(Of IUserData).MyEnumeratorCount
Get
If Collections Is Nothing Then
Return 0
Else
Return Collections.Count
End If
End Get
End Property
Friend Overrides Property MyFile As SFile
Get
If Count > 0 Then Return Collections(0).File Else Return Nothing
End Get
Set(ByVal NewFile As SFile)
End Set
End Property
Friend Overrides Property FileExists As Boolean
Get
If Count > 0 Then
Return Collections.Exists(Function(c) c.FileExists)
Else
Return False
End If
End Get
Set(ByVal IsExists As Boolean)
End Set
End Property
Friend Overrides Property DataMerging As Boolean
Get
If Count > 0 Then
Return DirectCast(Collections(0), UserDataBase).DataMerging
Else
Return False
End If
End Get
Set(ByVal IsMerged As Boolean)
MergeData(IsMerged)
End Set
End Property
Friend Overrides Property HasError As Boolean
Get
Return MyBase.HasError Or (Count > 0 AndAlso Collections.Exists(Function(c) c.HasError))
End Get
Set(ByVal __HasError As Boolean)
MyBase.HasError = __HasError
If Count > 0 Then Collections.ForEach(Sub(c) c.HasError = False)
End Set
End Property
Friend Overrides Property Temporary As Boolean
Get
If Count > 0 Then
Return Collections(0).Temporary
Else
Return False
End If
End Get
Set(ByVal Temp As Boolean)
Collections.ForEach(Sub(c) c.Temporary = Temp)
UpdateUserInformation()
End Set
End Property
Friend Overrides Property Favorite As Boolean
Get
If Count > 0 Then
Return Collections(0).Favorite
Else
Return False
End If
End Get
Set(ByVal Fav As Boolean)
Collections.ForEach(Sub(c) c.Favorite = Fav)
UpdateUserInformation()
End Set
End Property
Friend Overrides ReadOnly Property Labels As List(Of String)
Get
If Count > 0 Then
Return ListAddList(Nothing, Collections.SelectMany(Function(c) c.Labels), LAP.NotContainsOnly)
Else
Return New List(Of String)
End If
End Get
End Property
Friend Overrides Function GetUserInformation() As String
Dim OutStr$ = String.Empty
If Count > 0 Then Collections.ForEach(Sub(c) OutStr.StringAppendLine(DirectCast(c, UserDataBase).GetUserInformation(), $"{vbCrLf}{vbCrLf}"))
Return OutStr
End Function
Friend Overrides Property LastUpdated As Date?
Get
If Count > 0 Then
With If((From c In Collections
Where DirectCast(c, UserDataBase).LastUpdated.HasValue
Select DirectCast(c, UserDataBase).LastUpdated.Value).ToList, New List(Of Date))
If .Count > 0 Then Return .Max
End With
End If
Return Nothing
End Get
Set(ByVal NewDate As Date?)
End Set
End Property
Friend Overrides ReadOnly Property FitToAddParams As Boolean
Get
Return Count > 0 AndAlso Collections.Exists(Function(c) c.FitToAddParams)
End Get
End Property
#Region "Context buttons"
Friend ReadOnly Property ContextDown As ToolStripMenuItem()
Get
If Count > 0 Then
Return Collections.Select(Function(c) DirectCast(c, UserDataBase).BTT_CONTEXT_DOWN).ToArray
Else
Return New ToolStripMenuItem() {}
End If
End Get
End Property
Friend ReadOnly Property ContextEdit As ToolStripMenuItem()
Get
If Count > 0 Then
Return Collections.Select(Function(c) DirectCast(c, UserDataBase).BTT_CONTEXT_EDIT).ToArray
Else
Return New ToolStripMenuItem() {}
End If
End Get
End Property
Friend ReadOnly Property ContextDelete As ToolStripMenuItem()
Get
If Count > 0 Then
Return Collections.Select(Function(c) DirectCast(c, UserDataBase).BTT_CONTEXT_DELETE).ToArray
Else
Return New ToolStripMenuItem() {}
End If
End Get
End Property
Friend ReadOnly Property ContextPath As ToolStripMenuItem()
Get
If Count > 0 Then
Return Collections.Select(Function(c) DirectCast(c, UserDataBase).BTT_CONTEXT_OPEN_PATH).ToArray
Else
Return New ToolStripMenuItem() {}
End If
End Get
End Property
Friend ReadOnly Property ContextSite As ToolStripMenuItem()
Get
If Count > 0 Then
Return Collections.Select(Function(c) DirectCast(c, UserDataBase).BTT_CONTEXT_OPEN_SITE).ToArray
Else
Return New ToolStripMenuItem() {}
End If
End Get
End Property
#End Region
#End Region
Friend Sub New()
_IsCollection = True
Collections = New List(Of IUserData)
'ImageHandler(Me, True)
End Sub
Friend Sub New(ByVal _Name As String)
Me.New
CollectionName = _Name
End Sub
Friend Overrides Sub LoadUserInformation()
If Count > 0 Then Collections.ForEach(Sub(c) c.LoadUserInformation())
End Sub
Friend Overrides Sub UpdateUserInformation()
If Count > 0 Then Collections.ForEach(Sub(c) c.UpdateUserInformation())
End Sub
Friend Overrides Sub LoadContentInformation()
If Count > 0 Then Collections.ForEach(Sub(c) DirectCast(c, UserDataBase).LoadContentInformation())
End Sub
Friend Overrides Property DownloadReparseOnly As Boolean
Get
If Count > 0 Then Return Collections(0).DownloadReparseOnly Else Return False
End Get
Set(ByVal DRO As Boolean)
If Count > 0 Then Collections.ForEach(Sub(u) u.DownloadReparseOnly = DRO)
End Set
End Property
Friend Overrides ReadOnly Property DataForReparseExists As Boolean
Get
If Count > 0 Then
Return Collections.Exists(Function(u) u.DataForReparseExists)
Else
Return False
End If
End Get
End Property
Friend Overrides Sub DownloadData(ByVal Token As CancellationToken)
If Count > 0 Then Downloader.AddRange(Collections)
End Sub
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
End Sub
Protected Overrides Sub ReparseVideo(ByVal Token As CancellationToken)
End Sub
Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
End Sub
Private Sub User_OnPictureUpdated(ByVal User As IUserData)
Raise_OnPictureUpdated()
End Sub
Friend Overrides Sub OpenSite()
If Count > 0 Then Collections(0).OpenSite()
End Sub
Friend Overrides Sub OpenFolder()
Try
If Count > 0 Then Collections(0).File.CutPath(2).Open(SFO.Path, EDP.None)
Catch ex As Exception
End Try
End Sub
#Region "ICollection Support"
Default Friend ReadOnly Property Item(ByVal Index As Integer) As IUserData Implements IMyEnumerator(Of IUserData).MyEnumeratorObject
Get
Return Collections(Index)
End Get
End Property
Private ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of IUserData).IsReadOnly
Get
Return False
End Get
End Property
Friend Overloads Sub Add(ByVal _Item As IUserData) Implements ICollection(Of IUserData).Add
With _Item
.Temporary = Temporary
.Favorite = Favorite
ImageHandler(_Item, False)
AddHandler _Item.OnPictureUpdated, AddressOf User_OnPictureUpdated
Dim m As Boolean = DataMerging
If .MoveFiles(CollectionName, m) Then
Collections.Add(_Item)
DirectCast(_Item, UserDataBase).CreateButtons(Count - 1)
End If
End With
End Sub
''' <summary>FOR SETTINGS START LOADING ONLY</summary>
Friend Overloads Sub Add(ByVal u As UserInfo, Optional ByVal _LoadData As Boolean = True)
Select Case u.Site
Case Sites.Reddit : Collections.Add(New Reddit.UserData(u, _LoadData))
Case Sites.Twitter : Collections.Add(New Twitter.UserData(u, _LoadData))
Case Else : Exit Sub
End Select
With DirectCast(Collections(Count - 1), UserDataBase)
.CreateButtons(Count - 1)
AddHandler .BTT_CONTEXT_DELETE.Click, AddressOf BTT_CONTEXT_DELETE_Click
End With
AddHandler Collections(Count - 1).OnPictureUpdated, AddressOf User_OnPictureUpdated
End Sub
Friend Sub AddRange(ByVal _Items As IEnumerable(Of IUserData))
If Not _Items Is Nothing AndAlso _Items.Count > 0 Then
For i% = 0 To _Items.Count - 1 : Add(_Items(i)) : Next
End If
End Sub
Friend Overrides Function MoveFiles(ByVal __CollectionName As String, ByVal _MergeData As Boolean) As Boolean
Throw New NotImplementedException("Files moving does not available if collection context")
End Function
Friend Overloads Sub MergeData(ByVal Merging As Boolean)
If Count > 0 Then
If Merging Then
If DataMerging Then
MsgBoxE($"Collection [{CollectionName}] data already merged")
Else
If Collections.Count > 1 Then
Collections.ForEach(Sub(c) DirectCast(c, UserDataBase).MergeData())
MsgBoxE($"Collection [{CollectionName}] data merged")
Else
MsgBoxE($"Collection [{CollectionName}] contains only one user profile" & vbCr &
"Data merging available from two and more profiles in collection!", MsgBoxStyle.Exclamation)
End If
End If
Else
If DataMerging Then
MsgBoxE($"Collection [{CollectionName}] data is already merged" & vbCr &
"Combined data can not be undone", MsgBoxStyle.Critical)
Else
MsgBoxE($"Collection [{CollectionName}] data was never merged")
End If
End If
End If
End Sub
Friend Sub Clear() Implements ICollection(Of IUserData).Clear
Collections.ListClearDispose
End Sub
Friend Function Contains(ByVal _Item As IUserData) As Boolean Implements ICollection(Of IUserData).Contains
Return Collections.Contains(_Item)
End Function
Private Sub CopyTo(ByVal _Array() As IUserData, ByVal _ArrayIndex As Integer) Implements ICollection(Of IUserData).CopyTo
Throw New NotImplementedException("[CopyTo] method does not supported in collections context")
End Sub
Friend Function Remove(ByVal _Item As IUserData) As Boolean Implements ICollection(Of IUserData).Remove
If DataMerging Then
MsgBoxE($"Collection [{CollectionName}] data is already merged" & vbCr &
"Combined data can not be undone" & vbCr &
"Operation canceled", MsgBoxStyle.Critical)
Return False
Else
DirectCast(_Item, UserDataBase).MoveFiles(String.Empty, False)
ImageHandler(_Item)
Return Collections.Remove(_Item)
End If
End Function
Friend Overrides Function Delete() As Integer
If Count > 0 Then
If MsgBoxE({$"Collection may contain data{vbCr}Do you really want to delete collection and all of it files?", "Collection deleting"},
MsgBoxStyle.Exclamation + MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
Settings.Users.Remove(Me)
Collections.ForEach(Sub(c) c.Delete())
Downloader.UserRemove(Me)
ImageHandler(Me, False)
Collections.ListClearDispose
Dispose(False)
Return 2
Else
If DataMerging Then
MsgBoxE($"Collection [{CollectionName}] data are already merged{vbCr}Cannot split merged collection{vbCr}Operation canceled", MsgBoxStyle.Exclamation)
Return 0
End If
If MsgBoxE({$"Do you want to delete collection only?{vbCr}Users will not be deleted", "Collection deleting"},
MsgBoxStyle.Question + MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
Dim f As SFile = Collections(0).File.CutPath(2)
Settings.Users.Remove(Me)
Collections.ForEach(Sub(c)
c.MoveFiles(String.Empty, False)
ImageHandler(c)
End Sub)
Collections.Clear()
f.Delete(SFO.Path,,, EDP.SendInLog)
Downloader.UserRemove(Me)
ImageHandler(Me, False)
Dispose(False)
Return 3
Else
MsgBoxE("Operation canceled")
End If
End If
End If
Return 0
End Function
Private Sub BTT_CONTEXT_DELETE_Click(sender As Object, e As EventArgs)
With DirectCast(sender, ToolStripMenuItem)
Dim i% = AConvert(Of Integer)(.Tag, -1)
If i >= 0 Then
Dim n$ = Collections(i).Name
Dim s$ = Collections(i).Site.ToString
If MsgBoxE({$"Do you really want to delete user profile [{n}] of site [{s}]?" & vbCr &
"This profile will be removed from collection and all data will be erased",
"Profile removing"}, MsgBoxStyle.Exclamation,,, {"Process", "Cancel"}) = 0 Then
Collections(i).Delete()
Collections(i).Dispose()
Collections.RemoveAt(i)
MsgBoxE($"User profile [{n}] of site [{s}] has been removed")
If Count = 0 Then
Settings.Users.Remove(Me)
ImageHandler(Me, False)
RaiseEvent OnCollectionSelfRemoved()
Dispose(False)
End If
Else
MsgBoxE("Operation canceled")
End If
End If
End With
End Sub
#Region "IEnumerable Support"
Private Function GetEnumerator() As IEnumerator(Of IUserData) Implements IEnumerable(Of IUserData).GetEnumerator
Return New MyEnumerator(Of IUserData)(Me)
End Function
Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Return GetEnumerator()
End Function
#End Region
#End Region
Friend Overrides Function CompareTo(ByVal Other As UserDataBase) As Integer
If TypeOf Other Is UserDataBind Then
Dim x% = CompareValue(Me)
Dim y% = CompareValue(Other)
If x.CompareTo(y) = 0 Then
Return CollectionName.CompareTo(Other.CollectionName)
Else
Return x.CompareTo(y)
End If
Else
Return -1
End If
End Function
Friend Overrides Function CompareTo(ByVal Obj As Object) As Integer
If TypeOf Obj Is UserDataBind Then
Return CompareTo(DirectCast(Obj, UserDataBind))
Else
Return -1
End If
End Function
Friend Overrides Function Equals(ByVal Other As UserDataBase) As Boolean
If Other.IsCollection Then
Return CollectionName = Other.CollectionName
Else
Return Count > 0 AndAlso Collections.Exists(Function(u) u.Equals(Other))
End If
End Function
#Region "IDisposable Support"
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If Not disposedValue Then
If disposing Then Collections.ListClearDispose
End If
MyBase.Dispose(disposing)
End Sub
#End Region
End Class
End Namespace

6
SCrawler/App.config Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
</configuration>

View File

@@ -0,0 +1,225 @@
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Friend Class ChannelViewForm : Inherits System.Windows.Forms.Form
<System.Diagnostics.DebuggerNonUserCode()>
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
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container()
Dim SEP_1 As System.Windows.Forms.ToolStripSeparator
Dim SEP_2 As System.Windows.Forms.ToolStripSeparator
Dim SEP_3 As System.Windows.Forms.ToolStripSeparator
Dim CONTEXT_SEP_1 As System.Windows.Forms.ToolStripSeparator
Dim CONTEXT_SEP_2 As System.Windows.Forms.ToolStripSeparator
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(ChannelViewForm))
Me.TT_MAIN = New System.Windows.Forms.ToolTip(Me.components)
Me.ToolbarTOP = New System.Windows.Forms.ToolStrip()
Me.BTT_DOWNLOAD = New System.Windows.Forms.ToolStripButton()
Me.BTT_STOP = New System.Windows.Forms.ToolStripButton()
Me.BTT_ADD_USERS = New System.Windows.Forms.ToolStripButton()
Me.ToolbarBOTTOM = New System.Windows.Forms.StatusStrip()
Me.PR_CN = New System.Windows.Forms.ToolStripProgressBar()
Me.LBL_STATUS = New System.Windows.Forms.ToolStripStatusLabel()
Me.LIST_POSTS = New System.Windows.Forms.ListView()
Me.LCONTEXT = New System.Windows.Forms.ContextMenuStrip(Me.components)
Me.BTT_C_OPEN_USER = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_C_OPEN_POST = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_C_OPEN_PICTURE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_C_OPEN_FOLDER = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_C_ADD_TO_BLACKLIST = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_C_REMOVE_FROM_SELECTED = New System.Windows.Forms.ToolStripMenuItem()
SEP_1 = New System.Windows.Forms.ToolStripSeparator()
SEP_2 = New System.Windows.Forms.ToolStripSeparator()
SEP_3 = New System.Windows.Forms.ToolStripSeparator()
CONTEXT_SEP_1 = New System.Windows.Forms.ToolStripSeparator()
CONTEXT_SEP_2 = New System.Windows.Forms.ToolStripSeparator()
Me.ToolbarTOP.SuspendLayout()
Me.ToolbarBOTTOM.SuspendLayout()
Me.LCONTEXT.SuspendLayout()
Me.SuspendLayout()
'
'SEP_1
'
SEP_1.Name = "SEP_1"
SEP_1.Size = New System.Drawing.Size(6, 25)
'
'SEP_2
'
SEP_2.Name = "SEP_2"
SEP_2.Size = New System.Drawing.Size(6, 25)
'
'SEP_3
'
SEP_3.Name = "SEP_3"
SEP_3.Size = New System.Drawing.Size(6, 25)
'
'CONTEXT_SEP_1
'
CONTEXT_SEP_1.Name = "CONTEXT_SEP_1"
CONTEXT_SEP_1.Size = New System.Drawing.Size(302, 6)
'
'ToolbarTOP
'
Me.ToolbarTOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden
Me.ToolbarTOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_DOWNLOAD, Me.BTT_STOP, SEP_1, Me.BTT_ADD_USERS, SEP_2, SEP_3})
Me.ToolbarTOP.Location = New System.Drawing.Point(0, 0)
Me.ToolbarTOP.Name = "ToolbarTOP"
Me.ToolbarTOP.Size = New System.Drawing.Size(744, 25)
Me.ToolbarTOP.TabIndex = 0
'
'BTT_DOWNLOAD
'
Me.BTT_DOWNLOAD.AutoToolTip = False
Me.BTT_DOWNLOAD.Image = Global.SCrawler.My.Resources.Resources.StartPic_01_Green_16
Me.BTT_DOWNLOAD.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_DOWNLOAD.Name = "BTT_DOWNLOAD"
Me.BTT_DOWNLOAD.Size = New System.Drawing.Size(104, 22)
Me.BTT_DOWNLOAD.Text = "Download (F5)"
'
'BTT_STOP
'
Me.BTT_STOP.Enabled = False
Me.BTT_STOP.Image = Global.SCrawler.My.Resources.Resources.Delete
Me.BTT_STOP.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_STOP.Name = "BTT_STOP"
Me.BTT_STOP.Size = New System.Drawing.Size(51, 22)
Me.BTT_STOP.Text = "Stop"
Me.BTT_STOP.ToolTipText = "Stop downloading"
'
'BTT_ADD_USERS
'
Me.BTT_ADD_USERS.Image = Global.SCrawler.My.Resources.Resources.PlusPIC
Me.BTT_ADD_USERS.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_ADD_USERS.Name = "BTT_ADD_USERS"
Me.BTT_ADD_USERS.Size = New System.Drawing.Size(49, 22)
Me.BTT_ADD_USERS.Text = "Add"
Me.BTT_ADD_USERS.ToolTipText = "Add pending users to collection (F8)"
'
'ToolbarBOTTOM
'
Me.ToolbarBOTTOM.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.PR_CN, Me.LBL_STATUS})
Me.ToolbarBOTTOM.Location = New System.Drawing.Point(0, 439)
Me.ToolbarBOTTOM.Name = "ToolbarBOTTOM"
Me.ToolbarBOTTOM.Size = New System.Drawing.Size(744, 22)
Me.ToolbarBOTTOM.TabIndex = 1
'
'PR_CN
'
Me.PR_CN.Name = "PR_CN"
Me.PR_CN.Size = New System.Drawing.Size(200, 16)
'
'LBL_STATUS
'
Me.LBL_STATUS.Name = "LBL_STATUS"
Me.LBL_STATUS.Size = New System.Drawing.Size(0, 17)
'
'LIST_POSTS
'
Me.LIST_POSTS.CheckBoxes = True
Me.LIST_POSTS.ContextMenuStrip = Me.LCONTEXT
Me.LIST_POSTS.Dock = System.Windows.Forms.DockStyle.Fill
Me.LIST_POSTS.HideSelection = False
Me.LIST_POSTS.Location = New System.Drawing.Point(0, 25)
Me.LIST_POSTS.MultiSelect = False
Me.LIST_POSTS.Name = "LIST_POSTS"
Me.LIST_POSTS.Size = New System.Drawing.Size(744, 414)
Me.LIST_POSTS.TabIndex = 2
Me.LIST_POSTS.UseCompatibleStateImageBehavior = False
'
'LCONTEXT
'
Me.LCONTEXT.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_C_OPEN_USER, Me.BTT_C_OPEN_POST, Me.BTT_C_OPEN_PICTURE, Me.BTT_C_OPEN_FOLDER, CONTEXT_SEP_1, Me.BTT_C_REMOVE_FROM_SELECTED, CONTEXT_SEP_2, Me.BTT_C_ADD_TO_BLACKLIST})
Me.LCONTEXT.Name = "LCONTEXT"
Me.LCONTEXT.Size = New System.Drawing.Size(306, 170)
'
'BTT_C_OPEN_USER
'
Me.BTT_C_OPEN_USER.Name = "BTT_C_OPEN_USER"
Me.BTT_C_OPEN_USER.Size = New System.Drawing.Size(305, 22)
Me.BTT_C_OPEN_USER.Text = "Open user"
'
'BTT_C_OPEN_POST
'
Me.BTT_C_OPEN_POST.Name = "BTT_C_OPEN_POST"
Me.BTT_C_OPEN_POST.Size = New System.Drawing.Size(305, 22)
Me.BTT_C_OPEN_POST.Text = "Open post"
'
'BTT_C_OPEN_PICTURE
'
Me.BTT_C_OPEN_PICTURE.Name = "BTT_C_OPEN_PICTURE"
Me.BTT_C_OPEN_PICTURE.Size = New System.Drawing.Size(305, 22)
Me.BTT_C_OPEN_PICTURE.Text = "Open picture"
'
'BTT_C_OPEN_FOLDER
'
Me.BTT_C_OPEN_FOLDER.Name = "BTT_C_OPEN_FOLDER"
Me.BTT_C_OPEN_FOLDER.Size = New System.Drawing.Size(305, 22)
Me.BTT_C_OPEN_FOLDER.Text = "Open folder"
'
'BTT_C_ADD_TO_BLACKLIST
'
Me.BTT_C_ADD_TO_BLACKLIST.Name = "BTT_C_ADD_TO_BLACKLIST"
Me.BTT_C_ADD_TO_BLACKLIST.Size = New System.Drawing.Size(305, 22)
Me.BTT_C_ADD_TO_BLACKLIST.Text = "Add/Remove this user to/from the BlackList"
'
'CONTEXT_SEP_2
'
CONTEXT_SEP_2.Name = "CONTEXT_SEP_2"
CONTEXT_SEP_2.Size = New System.Drawing.Size(302, 6)
'
'BTT_C_REMOVE_FROM_SELECTED
'
Me.BTT_C_REMOVE_FROM_SELECTED.AutoToolTip = True
Me.BTT_C_REMOVE_FROM_SELECTED.Name = "BTT_C_REMOVE_FROM_SELECTED"
Me.BTT_C_REMOVE_FROM_SELECTED.Size = New System.Drawing.Size(305, 22)
Me.BTT_C_REMOVE_FROM_SELECTED.Text = "Remove user from selected"
Me.BTT_C_REMOVE_FROM_SELECTED.ToolTipText = "Remove this user from selected users if user was added to"
'
'ChannelViewForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(744, 461)
Me.Controls.Add(Me.LIST_POSTS)
Me.Controls.Add(Me.ToolbarBOTTOM)
Me.Controls.Add(Me.ToolbarTOP)
Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon)
Me.KeyPreview = True
Me.MinimumSize = New System.Drawing.Size(760, 500)
Me.Name = "ChannelViewForm"
Me.Text = "Channels"
Me.ToolbarTOP.ResumeLayout(False)
Me.ToolbarTOP.PerformLayout()
Me.ToolbarBOTTOM.ResumeLayout(False)
Me.ToolbarBOTTOM.PerformLayout()
Me.LCONTEXT.ResumeLayout(False)
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Private WithEvents ToolbarTOP As ToolStrip
Private WithEvents ToolbarBOTTOM As StatusStrip
Private WithEvents LIST_POSTS As ListView
Private WithEvents PR_CN As ToolStripProgressBar
Private WithEvents LBL_STATUS As ToolStripStatusLabel
Private WithEvents BTT_DOWNLOAD As ToolStripButton
Private WithEvents TT_MAIN As ToolTip
Private WithEvents BTT_STOP As ToolStripButton
Private WithEvents BTT_ADD_USERS As ToolStripButton
Private WithEvents LCONTEXT As ContextMenuStrip
Private WithEvents BTT_C_OPEN_USER As ToolStripMenuItem
Private WithEvents BTT_C_OPEN_POST As ToolStripMenuItem
Private WithEvents BTT_C_OPEN_PICTURE As ToolStripMenuItem
Private WithEvents BTT_C_OPEN_FOLDER As ToolStripMenuItem
Private WithEvents BTT_C_ADD_TO_BLACKLIST As ToolStripMenuItem
Private WithEvents BTT_C_REMOVE_FROM_SELECTED As ToolStripMenuItem
End Class

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,704 @@
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Toolbars
Imports PersonalUtilities.Forms.Controls
Imports PersonalUtilities.Forms.Controls.Base
Imports PersonalUtilities.Tools
Imports System.ComponentModel
Imports System.Threading
Imports SCrawler.API.Base
Imports SCrawler.API.Reddit
Imports CmbDefaultButtons = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons
Imports RButton = PersonalUtilities.Tools.RangeSwitcherButton.Types
Friend Class ChannelViewForm : Implements IChannelLimits
Friend Event OnUsersAdded(ByVal StartIndex As Integer)
#Region "Declarations"
Private ReadOnly MyDefs As DefaultFormProps
#Region "Controls"
Private WithEvents CMB_CHANNELS As ComboBoxExtended
Private WithEvents CH_HIDE_EXISTS_USERS As CheckBox
Private WithEvents TXT_LIMIT As TextBoxExtended
Private ReadOnly LBL_LIMITS As ToolStripLabel
Private ReadOnly LBL_LIMIT_TEXT As ToolStripLabel
Private WithEvents OPT_LIMITS_DEFAULT As RadioButton
Private WithEvents OPT_LIMITS_COUNT As RadioButton
Private WithEvents OPT_LIMITS_POST As RadioButton
Private WithEvents OPT_LIMITS_DATE As RadioButton
#End Region
Private ReadOnly CProvider As ANumbers
Private ReadOnly CProgress As MyProgress
Private ReadOnly LimitProvider As ADateTime
Friend ReadOnly Property ImagesInRow As Integer
Get
Return Settings.ChannelsImagesColumns.Value
End Get
End Property
Friend ReadOnly Property ImagesRows As Integer
Get
Return Settings.ChannelsImagesRows.Value
End Get
End Property
#Region "Limits Support"
Private Property AutoGetLimits As Boolean Implements IChannelLimits.AutoGetLimits
Get
Return OPT_LIMITS_DEFAULT.Checked
End Get
Set(ByVal NewLimit As Boolean)
End Set
End Property
Private Property DownloadLimitCount As Integer? Implements IChannelLimits.DownloadLimitCount
Get
If OPT_LIMITS_COUNT.Checked Then
Return AConvert(Of Integer)(TXT_LIMIT.Text, Nothing)
Else
Return Nothing
End If
End Get
Set(ByVal NewLimit As Integer?)
End Set
End Property
Private Property DownloadLimitPost As String Implements IChannelLimits.DownloadLimitPost
Get
If OPT_LIMITS_POST.Checked Then
Return TXT_LIMIT.Text
Else
Return String.Empty
End If
End Get
Set(ByVal NewLimit As String)
End Set
End Property
Private Property DownloadLimitDate As Date? Implements IChannelLimits.DownloadLimitDate
Get
If OPT_LIMITS_DATE.Checked Then
Return AConvert(Of Date)(TXT_LIMIT.Value, Nothing)
Else
Return Nothing
End If
End Get
Set(ByVal NewDate As Date?)
End Set
End Property
Private Sub SetLimit(Optional ByVal Post As String = "", Optional ByVal Count As Integer? = Nothing,
Optional ByVal [Date] As Date? = Nothing) Implements IChannelLimits.SetLimit
End Sub
Private Sub SetLimit(ByVal Source As IChannelLimits) Implements IChannelLimits.SetLimit
End Sub
#End Region
Friend ReadOnly PendingUsers As List(Of String)
Private ReadOnly LNC As New ListAddParams(LAP.NotContainsOnly)
Private WithEvents MyRange As RangeSwitcher(Of UserPost)
Private ReadOnly SelectorExpression As Predicate(Of UserPost) = Function(ByVal Post As UserPost) As Boolean
If Post.UserID.ToLower = "[deleted]" Or Settings.BlackList.Contains(Post.UserID) Then
Return False
Else
If CH_HIDE_EXISTS_USERS.Checked Then
Return Not Settings.UsersList.Exists(Function(u) u.Name = Post.UserID)
Else
Return True
End If
End If
End Function
#End Region
#Region "Initializer and form methods"
Friend Sub New()
InitializeComponent()
MyDefs = New DefaultFormProps
CProgress = New MyProgress(ToolbarBOTTOM, PR_CN, LBL_STATUS, "Downloading data") With {.PerformMod = 10, .DropCurrentProgressOnTotalChange = False}
CProvider = New ANumbers(ANumbers.Modes.USA) With {.GroupSize = 3, .DecimalDigits = 0}
LimitProvider = New ADateTime("dd.MM.yyyy HH:mm")
PendingUsers = New List(Of String)
CMB_CHANNELS = New ComboBoxExtended With {
.CaptionMode = ICaptionControl.Modes.CheckBox,
.CaptionText = "All Channels",
.Margin = New Padding(3),
.ChangeControlsEnableOnCheckedChange = False,
.CaptionBackColor = Color.Transparent,
.ListMaxDropDownItems = 15,
.CaptionPadding = New Padding(0, 3, 0, 0)
}
CMB_CHANNELS.Buttons.AddRange({CmbDefaultButtons.Refresh, CmbDefaultButtons.Add, CmbDefaultButtons.Delete,
New ActionButton(CmbDefaultButtons.Up) With {.ToolTipText = "Previous item (F1)"},
New ActionButton(CmbDefaultButtons.Down) With {.ToolTipText = "Next item (F4)"}})
TXT_LIMIT = New TextBoxExtended With {
.CaptionText = "Limit",
.Margin = New Padding(2),
.CaptionSizeType = SizeType.Absolute,
.CaptionWidth = 50,
.CaptionBackColor = Color.Transparent,
.TextBoxWidthMinimal = 200,
.Width = 200,
.CaptionPadding = New Padding(0, 3, 0, 0)
}
LBL_LIMITS = New ToolStripLabel With {.Text = "Limits:", .Margin = New Padding(2)}
LBL_LIMIT_TEXT = New ToolStripLabel With {.Text = String.Empty, .Margin = New Padding(2)}
OPT_LIMITS_DEFAULT = New RadioButton With {.Text = "Default", .BackColor = Color.Transparent, .Margin = New Padding(2)}
OPT_LIMITS_COUNT = New RadioButton With {.Text = "Count", .BackColor = Color.Transparent, .Margin = New Padding(2)}
OPT_LIMITS_POST = New RadioButton With {.Text = "Post", .BackColor = Color.Transparent, .Margin = New Padding(2)}
OPT_LIMITS_DATE = New RadioButton With {.Text = "Date", .BackColor = Color.Transparent, .Margin = New Padding(2)}
CH_HIDE_EXISTS_USERS = New CheckBox With {.Text = "Hide exists users", .BackColor = Color.Transparent, .Margin = New Padding(2),
.Checked = Settings.ChannelsHideExistsUser}
TT_MAIN.SetToolTip(CH_HIDE_EXISTS_USERS, "Hide users which already exists in collection")
TT_MAIN.SetToolTip(OPT_LIMITS_COUNT, "Total posts count limit")
TT_MAIN.SetToolTip(OPT_LIMITS_POST, "Looking limit till post(-s) (comma separated)")
ToolbarTOP.Items.AddRange({CMB_CHANNELS.GetControlHost,
New ToolStripSeparator,
LBL_LIMITS,
New ToolStripControlHost(OPT_LIMITS_DEFAULT),
New ToolStripControlHost(OPT_LIMITS_COUNT),
New ToolStripControlHost(OPT_LIMITS_POST),
New ToolStripControlHost(OPT_LIMITS_DATE),
TXT_LIMIT.GetControlHost,
LBL_LIMIT_TEXT,
New ToolStripSeparator,
New ToolStripControlHost(CH_HIDE_EXISTS_USERS)})
MyRange = New RangeSwitcher(Of UserPost) With {.Selector = Function(p) Not Settings.UserExists(Sites.Reddit, p.UserID)}
With MyRange
.Limit = ImagesInRow * ImagesRows
.InsertButtons(ToolbarTOP, {RButton.Previous, RButton.Next}, 5)
.SetButtonKey(RButton.Previous, Keys.F2)
.SetButtonKey(RButton.Next, Keys.F3)
.BindForm(Me)
.LabelNumbersProvider = CProvider
.UpdateControls()
.Selector = SelectorExpression
End With
AddHandler Settings.ChannelsImagesColumns.OnValueChanged, AddressOf ImagesCountChanged
AddHandler Settings.ChannelsImagesRows.OnValueChanged, AddressOf ImagesCountChanged
End Sub
Private Sub ChannelViewForm_Load(sender As Object, e As EventArgs) Handles Me.Load
MyDefs.MyViewInitialize(Me, Settings.Design)
RefillChannels(Settings.LatestSelectedChannel.Value)
ChangeComboIndex(0)
CMB_CHANNELS_ActionOnCheckedChange(CMB_CHANNELS.Checked)
With LIST_POSTS
Dim s As Size = GetImageSize()
.LargeImageList = New ImageList With {.ColorDepth = ColorDepth.Depth32Bit, .ImageSize = s}
.SmallImageList = New ImageList With {.ColorDepth = ColorDepth.Depth32Bit, .ImageSize = s}
End With
CMB_CHANNELS.Enabled(False) = Not CMB_CHANNELS.Checked
MyDefs.EndLoaderOperations()
End Sub
Private Sub ChannelViewForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
AppendPendingUsers()
e.Cancel = True
Hide()
End Sub
Private Sub ChannelViewForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
CMB_CHANNELS.Dispose()
CH_HIDE_EXISTS_USERS.Dispose()
TXT_LIMIT.Dispose()
LBL_LIMITS.Dispose()
OPT_LIMITS_DEFAULT.Dispose()
OPT_LIMITS_COUNT.Dispose()
OPT_LIMITS_POST.Dispose()
LBL_LIMIT_TEXT.Dispose()
PendingUsers.Clear()
MyDefs.Dispose()
End Sub
Private Sub ChannelViewForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown, CMB_CHANNELS.KeyDown
Dim b As Boolean = True
If Not Working Then
Select Case e.KeyCode
Case Keys.Insert : AddNewChannel()
Case Keys.F1 : ChangeComboIndex(-1)
Case Keys.F4 : ChangeComboIndex(1)
Case Keys.F5 : BTT_DOWNLOAD.PerformClick()
Case Keys.F8 : BTT_ADD_USERS.PerformClick()
Case Else : b = False
End Select
Else
b = False
If e.KeyCode = Keys.F8 Then BTT_ADD_USERS.PerformClick() : b = True
End If
If b Then LIST_POSTS.Select() : e.Handled = True
End Sub
#End Region
Private Sub RefillChannels(Optional ByVal SelectedChannel As String = Nothing)
CMB_CHANNELS.BeginUpdate()
Dim indx%? = Nothing
Dim t$ = If(SelectedChannel.IsEmptyString, CMB_CHANNELS.Text, SelectedChannel)
CMB_CHANNELS.Clear(ComboBoxExtended.ClearMode.Items + ComboBoxExtended.ClearMode.Text)
If Settings.Channels Is Nothing Then Settings.Channels = New ChannelsCollection : Settings.Channels.Load()
With Settings.Channels
If .Count > 0 Then
For i% = 0 To .Count - 1
CMB_CHANNELS.Items.Add(.Item(i).ID)
If .Item(i).ID = t Then indx = i
Next
If indx >= 0 And indx <= CMB_CHANNELS.Count - 1 Then CMB_CHANNELS.SelectedIndex = indx
End If
End With
CMB_CHANNELS.EndUpdate()
End Sub
#Region "Images refill methods"
Private Sub AppendPendingUsers()
If LIST_POSTS.CheckedIndices.Count > 0 Then
PendingUsers.ListAddList((From p As ListViewItem In LIST_POSTS.Items Where p.Checked Select p.Text), LNC)
Dim a As Action = Sub() BTT_ADD_USERS.Text = $"Add ({PendingUsers.Count.ToString(CProvider)})"
If ToolbarTOP.InvokeRequired Then ToolbarTOP.Invoke(a) Else a.Invoke
End If
End Sub
Friend Function GetImageSize() As Size
Const mhw% = 256
Dim s As Size = LIST_POSTS.Size
With LIST_POSTS
s.Width -= (.Margin.Left + .Margin.Right)
s.Height -= (.Margin.Top + .Margin.Bottom)
s.Width = s.Width / ImagesInRow - .Padding.Left * ImagesInRow - .Padding.Right * ImagesInRow
s.Height = s.Height / ImagesRows - .Padding.Top * ImagesRows - .Padding.Bottom * ImagesRows
If s.Width = 0 Then s.Width = 50
If s.Height = 0 Then s.Height = 100
If s.Width >= mhw Then
s.Width = mhw / 100 * 75
s.Height = mhw
Else
s.Height = s.Width / 75 * 100
If s.Height > mhw Then s.Height = mhw
End If
End With
Return s
End Function
#End Region
#Region "Toolbar controls"
#Region "Downloader"
Private TokenSource As CancellationTokenSource
Private Token As CancellationToken
Friend ReadOnly Property Working As Boolean
Get
Return Not TokenSource Is Nothing
End Get
End Property
Private _ShowCancelNotification As Boolean = True
Private _CollectionDownloading As Boolean = False
Private Async Sub BTT_DOWNLOAD_Click(sender As Object, e As EventArgs) Handles BTT_DOWNLOAD.Click
Try
AppendPendingUsers()
If Not TokenSource Is Nothing Then Exit Sub
Dim InvokeToken As Action = Sub()
If TokenSource Is Nothing Then
CProgress.TotalCount = 0
CProgress.CurrentCounter = 0
CProgress.Enabled = True
TokenSource = New CancellationTokenSource
Token = TokenSource.Token
BTT_DOWNLOAD.Enabled = False
OPT_LIMITS_DEFAULT.Enabled = False
OPT_LIMITS_COUNT.Enabled = False
OPT_LIMITS_POST.Enabled = False
OPT_LIMITS_DATE.Enabled = False
TXT_LIMIT.Enabled = False
CH_HIDE_EXISTS_USERS.Enabled = False
CMB_CHANNELS.Enabled(True) = False
MyRange.EnableButton(RButton.Previous, False)
MyRange.EnableButton(RButton.Next, False)
End If
End Sub
Dim c As Channel
If CMB_CHANNELS.Count > 0 Then
BTT_DOWNLOAD.Enabled = False
BTT_STOP.Enabled = True
If CMB_CHANNELS.Checked Then
InvokeToken.Invoke()
_CollectionDownloading = True
Settings.Channels.SetLimit(Me)
Await Task.Run(Sub() Settings.Channels.DownloadData(Token, CH_HIDE_EXISTS_USERS.Checked, CProgress))
Token.ThrowIfCancellationRequested()
c = GetCurrentChannel()
Else
c = GetCurrentChannel()
If Not c Is Nothing Then
InvokeToken.Invoke()
c.SetLimit(Me)
Await Task.Run(Sub() c.DownloadData(Token, CH_HIDE_EXISTS_USERS.Checked, CProgress))
Token.ThrowIfCancellationRequested()
End If
End If
If Not c Is Nothing Then
SetLimitsByChannel(c)
MyRange.ChangeSource(c)
End If
Else
MsgBoxE("No one channels detected", MsgBoxStyle.Exclamation)
End If
Catch aex As ArgumentException When aex.HelpLink = 1
ErrorsDescriber.Execute(EDP.ShowAllMsg, aex)
Catch oex As OperationCanceledException When Token.IsCancellationRequested
Dim ee As EDP = EDP.SendInLog
If _ShowCancelNotification Then ee += EDP.ShowMainMsg
ErrorsDescriber.Execute(ee, oex, New MMessage("Downloading operation canceled", "Status...",, MsgBoxStyle.Exclamation))
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Channels downloading error")
Finally
If Not TokenSource Is Nothing AndAlso Not Settings.Channels.Downloading Then
TokenSource = Nothing
CProgress.Enabled = False
BTT_DOWNLOAD.Enabled = True
BTT_STOP.Enabled = False
_CollectionDownloading = False
OPT_LIMITS_DEFAULT.Enabled = True
OPT_LIMITS_COUNT.Enabled = True
OPT_LIMITS_POST.Enabled = True
OPT_LIMITS_DATE.Enabled = True
TXT_LIMIT.Enabled = True
CH_HIDE_EXISTS_USERS.Enabled = True
CMB_CHANNELS.Enabled(True) = True
CMB_CHANNELS_ActionOnCheckedChange(CMB_CHANNELS.Checked)
With MyRange
.EnableButton(RButton.Previous, .Count > 0 AndAlso .CurrentIndex > 0)
.EnableButton(RButton.Next, .Count > 0 AndAlso .CurrentIndex < .Max)
End With
End If
End Try
End Sub
Private Function GetCurrentChannel() As Channel
If CMB_CHANNELS.SelectedIndex >= 0 Then
Dim ChannelID$ = CMB_CHANNELS.Value
If Not ChannelID.IsEmptyString Then Return Settings.Channels.Find(ChannelID)
Else
MsgBoxE("No one channel selected", MsgBoxStyle.Exclamation)
End If
Return Nothing
End Function
Private Sub BTT_STOP_Click(sender As Object, e As EventArgs) Handles BTT_STOP.Click
[Stop]()
End Sub
Friend Sub [Stop](Optional ByVal ShowCancelNotification As Boolean = True)
_ShowCancelNotification = ShowCancelNotification
If Not TokenSource Is Nothing Then TokenSource.Cancel() : BTT_STOP.Enabled = False
End Sub
#End Region
Private Sub BTT_ADD_USERS_Click(sender As Object, e As EventArgs) Handles BTT_ADD_USERS.Click
AppendPendingUsers()
Dim i%
If LIST_POSTS.CheckedItems.Count > 0 Then
For i = 0 To LIST_POSTS.Items.Count - 1
If LIST_POSTS.Items(i).Checked Then LIST_POSTS.Items(i).Checked = False
Next
End If
If PendingUsers.Count > 0 Then
Dim Added% = 0, Skipped% = 0
Dim StartIndex% = Settings.Users.Count
Settings.Labels.Add(CannelsLabelName)
Settings.Labels.Add(LabelsKeeper.NoParsedUser)
Dim rUsers$() = UserBanned(PendingUsers.ToArray)
If rUsers.ListExists Then PendingUsers.RemoveAll(Function(u) rUsers.Contains(u))
If PendingUsers.Count > 0 Then
With PendingUsers.Select(Function(u) New UserInfo(u, Sites.Reddit))
For i = 0 To .Count - 1
If Not Settings.UsersList.Contains(.ElementAt(i)) Then
Settings.UpdateUsersList(.ElementAt(i))
Settings.Users.Add(New UserData(.ElementAt(i), False) With {.Temporary = True})
With Settings.Users.Last
.Labels.Add(CannelsLabelName)
.UpdateUserInformation()
End With
Added += 1
Else
Skipped += 1
End If
Next
End With
End If
PendingUsers.Clear()
BTT_ADD_USERS.Text = "Add"
MsgBoxE($"Added users: {Added.ToString(CProvider)}{vbCr}Skipped users: {Skipped.ToString(CProvider)}{vbCr}Total: {PendingUsers.Count.ToString(CProvider)}")
RaiseEvent OnUsersAdded(StartIndex)
Else
MsgBoxE("No one users selected for add to collection")
End If
End Sub
#Region "Limits changer"
Private Sub OPT_LIMITS_DEFAULT_CheckedChanged(sender As Object, e As EventArgs) Handles OPT_LIMITS_DEFAULT.CheckedChanged
If OPT_LIMITS_DEFAULT.Checked Then
TXT_LIMIT.CheckForCompatible = False
TXT_LIMIT.Enabled = False
ChangeLimitMode(TextBoxExtended.ControlModes.TextBox)
End If
End Sub
Private Sub OPT_LIMITS_COUNT_CheckedChanged(sender As Object, e As EventArgs) Handles OPT_LIMITS_COUNT.CheckedChanged
If OPT_LIMITS_COUNT.Checked Then
TXT_LIMIT.Enabled = True
TXT_LIMIT.CheckingType = GetType(Integer)
TXT_LIMIT.CheckForCompatible = True
ChangeLimitMode(TextBoxExtended.ControlModes.TextBox)
If Not ACheck(Of Integer)(TXT_LIMIT.Text) Then TXT_LIMIT.Text = Channel.DefaultDownloadLimitCount
End If
End Sub
Private Sub OPT_LIMITS_POST_CheckedChanged(sender As Object, e As EventArgs) Handles OPT_LIMITS_POST.CheckedChanged
If OPT_LIMITS_POST.Checked Then
TXT_LIMIT.Enabled = True
TXT_LIMIT.CheckForCompatible = False
ChangeLimitMode(TextBoxExtended.ControlModes.TextBox)
End If
End Sub
Private Sub OPT_LIMITS_DATE_CheckedChanged(sender As Object, e As EventArgs) Handles OPT_LIMITS_DATE.CheckedChanged
If OPT_LIMITS_DATE.Checked Then
TXT_LIMIT.CheckForCompatible = False
ChangeLimitMode(TextBoxExtended.ControlModes.DateTimePicker)
End If
End Sub
Private Sub ChangeLimitMode(ByVal Mode As TextBoxExtended.ControlModes)
If Not TXT_LIMIT.ControlMode = Mode Then TXT_LIMIT.ControlMode = Mode
End Sub
#End Region
#Region "CMB_CHANNELS"
Private Sub SetLimitsByChannel(Optional ByVal SelectedChannel As Channel = Nothing)
LBL_STATUS.Text = String.Empty
Dim c As Channel = If(SelectedChannel, GetCurrentChannel())
LBL_LIMIT_TEXT.Text = String.Empty
If Not c Is Nothing Then
Settings.LatestSelectedChannel.Value = c.ID
With c.PostsAll
If .Count > 0 Then
OPT_LIMITS_DEFAULT.Checked = True
Dim d As Date? = .FirstOrDefault(Function(p) p.Date.HasValue).Date
If d.HasValue Then
LBL_LIMIT_TEXT.Text = $"to date {AConvert(Of String)(d, ADateTime.Formats.BaseDateTime, String.Empty)}"
Else
LBL_LIMIT_TEXT.Text = $"to post [{c.First(Function(p) Not p.ID.IsEmptyString).ID}]"
End If
Else
OPT_LIMITS_COUNT.Checked = True
If TXT_LIMIT.Text.IsEmptyString Then TXT_LIMIT.Value = Channel.DefaultDownloadLimitCount
LBL_LIMIT_TEXT.Text = $"first {TXT_LIMIT.Text} posts"
End If
End With
End If
End Sub
Private Sub CMB_CHANNELS_ActionSelectedItemChanged(ByVal _Item As ListViewItem) Handles CMB_CHANNELS.ActionSelectedItemChanged
SetLimitsByChannel()
Dim c As Channel = GetCurrentChannel()
If Not c Is Nothing Then MyRange.ChangeSource(c, EDP.SendInLog)
End Sub
Private Sub CMB_CHANNELS_ActionOnButtonClick(ByVal Sender As ActionButton) Handles CMB_CHANNELS.ActionOnButtonClick
Select Case Sender.DefaultButton
Case CmbDefaultButtons.Refresh : RefillChannels()
Case CmbDefaultButtons.Add : AddNewChannel()
Case CmbDefaultButtons.Delete
Try
Dim c As Channel = GetCurrentChannel()
If Not c Is Nothing AndAlso MsgBoxE($"Do you really want to delete channel [{c}]?", MsgBoxStyle.Exclamation + MsgBoxStyle.YesNo) = 0 Then
Settings.Channels.Remove(c)
RefillChannels()
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Error on trying to delete channel")
End Try
Case CmbDefaultButtons.Up : ChangeComboIndex(-1)
Case CmbDefaultButtons.Down : ChangeComboIndex(1)
End Select
End Sub
Private Sub CMB_CHANNELS_ActionOnCheckedChange(ByVal Mode As Boolean) Handles CMB_CHANNELS.ActionOnCheckedChange
Dim OneChannel As Boolean = Not CMB_CHANNELS.Checked
CMB_CHANNELS.Enabled(False) = OneChannel
If OneChannel Then
OPT_LIMITS_DEFAULT.Checked = True
LBL_LIMIT_TEXT.Text = String.Empty
ChangeComboIndex(0)
Else
CMB_CHANNELS.Button(ActionButton.BTT_UP_NAME).Enabled = False
CMB_CHANNELS.Button(ActionButton.BTT_DOWN_NAME).Enabled = False
End If
End Sub
Private Sub AddNewChannel()
Dim c$ = InputBoxE("Enter Reddit channel:", "New channel")
If Not c.IsEmptyString Then
Dim cc As New Channel With {.Name = c, .ID = c}
If Settings.Channels.Count = 0 OrElse Not Settings.Channels.Contains(cc) Then
Settings.Channels.Add(cc)
Settings.Channels.Last.Save()
RefillChannels()
MsgBoxE($"Channel [{c}] added")
Else
MsgBoxE($"Channel [{c}] already exists")
End If
Else
MsgBoxE("You doesn't enter channel name. Operation canceled.", MsgBoxStyle.Exclamation)
End If
End Sub
Private Sub ChangeComboIndex(ByVal Appender As Integer)
Try
Dim _ComboUpEnabled As Boolean = False
Dim _ComboDownEnabled As Boolean = False
If CMB_CHANNELS.Count > 0 Then
Dim i% = CMB_CHANNELS.SelectedIndex
If i < 0 And Appender = 0 Then
CMB_CHANNELS.SelectedIndex = 0
Else
If i < 0 Then i = 0
i += Appender
If i >= 0 And i <= CMB_CHANNELS.Count - 1 And Not CMB_CHANNELS.SelectedIndex = i Then CMB_CHANNELS.SelectedIndex = i
End If
i = CMB_CHANNELS.SelectedIndex
Dim c% = CMB_CHANNELS.Count - 1
_ComboUpEnabled = i > 0 And c > 0
_ComboDownEnabled = i < c And c > 0
End If
CMB_CHANNELS.Button(ActionButton.BTT_UP_NAME).Enabled = _ComboUpEnabled
CMB_CHANNELS.Button(ActionButton.BTT_DOWN_NAME).Enabled = _ComboDownEnabled
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "ComboBox index changing")
End Try
End Sub
#End Region
Private Sub CH_HIDE_EXISTS_USERS_CheckedChanged(sender As Object, e As EventArgs) Handles CH_HIDE_EXISTS_USERS.CheckedChanged
If Not MyDefs.Initializing Then
Settings.ChannelsHideExistsUser.Value = CH_HIDE_EXISTS_USERS.Checked
MyRange.Update()
End If
End Sub
#End Region
#Region "CONTEXT"
Private Sub BTT_C_OPEN_USER_Click(sender As Object, e As EventArgs) Handles BTT_C_OPEN_USER.Click
Dim p As UserPost = GetPostBySelected()
Try
If Not p.UserID.IsEmptyString Then Process.Start($"https://www.reddit.com/user/{p.UserID}")
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, $"Error on opening user by [https://www.reddit.com/user/{p.UserID}]")
End Try
End Sub
Private Sub BTT_C_OPEN_POST_Click(sender As Object, e As EventArgs) Handles BTT_C_OPEN_POST.Click
Dim p As UserPost = GetPostBySelected()
Dim URL$ = String.Empty
Try
URL = $"https://www.reddit.com/r/{CMB_CHANNELS.Value}/comments/{p.ID.Split("_").Last}"
If Not p.ID.IsEmptyString Then Process.Start(URL)
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, $"Error on opening post by [{URL}]")
End Try
End Sub
Private Sub BTT_C_OPEN_PICTURE_Click(sender As Object, e As EventArgs) Handles BTT_C_OPEN_PICTURE.Click
OpenPostPicture()
End Sub
Private Sub BTT_C_OPEN_FOLDER_Click(sender As Object, e As EventArgs) Handles BTT_C_OPEN_FOLDER.Click
Dim f As SFile = GetPostBySelected().CachedFile
If Not f.IsEmptyString Then f.Open(SFO.Path)
End Sub
Private Sub BTT_C_REMOVE_FROM_SELECTED_Click(sender As Object, e As EventArgs) Handles BTT_C_REMOVE_FROM_SELECTED.Click
Try
Dim u$ = GetPostBySelected().UserID
If Not u.IsEmptyString Then
Dim uRemoved As Boolean = False
If PendingUsers.Contains(u) Then PendingUsers.Remove(u) : uRemoved = True
With LIST_POSTS
If .Items.Count > 0 Then
Dim i%
Dim a As Action = Sub() .Items(i).Checked = False
For i = 0 To .Items.Count - 1
If .Items(i).Text = u And .Items(i).Checked Then
If LIST_POSTS.InvokeRequired Then LIST_POSTS.Invoke(a) Else a.Invoke
End If
Next
End If
End With
If uRemoved Then
MsgBoxE($"User [{u}] was successfully removed")
Else
MsgBoxE($"User [{u}] was not added to selected users")
End If
BTT_ADD_USERS.Text = $"Add ({PendingUsers.Count.ToString(CProvider)})"
Else
MsgBoxE("User does not selected", MsgBoxStyle.Exclamation)
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Error on removing user from selected")
End Try
End Sub
Private Sub BTT_C_ADD_TO_BLACKLIST_Click(sender As Object, e As EventArgs) Handles BTT_C_ADD_TO_BLACKLIST.Click
Try
Dim u$ = GetPostBySelected().UserID
If Not u.IsEmptyString Then
Dim result% = MsgBoxE(New MMessage($"Do you really want to add user [{u}] to the BlackList?",
"Adding user to the BlackList",
{"Add", "Add and update ranges",
"Add with the reason", "Add with the reason and update ranges",
"Remove from BlackList", "Cancel"},
MsgBoxStyle.Exclamation) With {.ButtonsPerRow = 2})
If result < 4 Then
Dim reason$ = String.Empty
If result = 2 Or result = 3 Then reason = InputBoxE("Enter the ban reason:", "Ban reason")
Settings.BlackList.ListAddValue(New UserBan(u, reason), LAP.NotContainsOnly)
Settings.UpdateBlackList()
If result = 1 Or result = 3 Then MyRange.Update()
MsgBoxE($"User {u} was added to the BlackList")
ElseIf result = 4 Then
If Settings.BlackList.Contains(u) Then
Settings.BlackList.Remove(u)
Settings.UpdateBlackList()
MsgBoxE($"User [{u}] was removed from the BlackList")
Else
MsgBoxE($"User [{u}] was not banned")
End If
End If
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Adding user to the BlackList")
End Try
End Sub
#End Region
Private Sub OpenPostPicture()
Dim f As SFile = GetPostBySelected().CachedFile
If f.Exists Then f.Open() Else MsgBoxE($"Picture file [{f}] does not found", MsgBoxStyle.Critical)
End Sub
Private Function GetPostBySelected() As UserPost
Dim p As UserPost = Nothing
Try
If LIST_POSTS.SelectedItems.Count > 0 Then
Dim t$ = LIST_POSTS.SelectedItems(0).Tag
With Settings.Channels.Find(CMB_CHANNELS.Value)
If .Count > 0 Then p = .Posts.Find(Function(pp) pp.ID = t)
End With
End If
Catch aex As ArgumentException When aex.HelpLink = 1
ErrorsDescriber.Execute(EDP.LogMessageValue, aex)
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendInLog, ex, "Post searching error")
End Try
Return p
End Function
Private Sub LIST_POSTS_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles LIST_POSTS.MouseDoubleClick
OpenPostPicture()
End Sub
#Region "MyRange"
Private Sub ImagesCountChanged(ByVal Sender As Object, ByVal _Name As String, ByVal _Value As Object)
AppendPendingUsers()
MyRange.Update(ImagesInRow * ImagesRows)
MyRange.GoTo(0, EDP.SendInLog)
End Sub
Private Sub MyRange_IndexChanged(ByVal Index As Integer) Handles MyRange.IndexChanged
Try
If MyDefs.Initializing Then Exit Sub
AppendPendingUsers()
LIST_POSTS.LargeImageList.Images.Clear()
LIST_POSTS.Items.Clear()
Dim p As UserPost
With MyRange.Current(EDP.ReturnValue).ListIfNothing
If .Count > 0 Then
Dim s As Size = GetImageSize()
Dim NullImage As Image = New Bitmap(s.Width, s.Height)
Dim ie As New ErrorsDescriber(EDP.ReturnValue)
For i% = 0 To .Count - 1
p = .Item(i)
With p
LIST_POSTS.LargeImageList.Images.Add(.GetImage(s, ie, NullImage))
LIST_POSTS.Items.Add(New ListViewItem(.UserID, i) With {.Tag = p.ID})
With LIST_POSTS.Items(LIST_POSTS.Items.Count - 1)
If PendingUsers.Contains(.Text) Then .Checked = True
End With
End With
Next
End If
End With
Catch aex As ArgumentException When aex.HelpLink = 1
MsgBoxE(aex.Message, MsgBoxStyle.Critical)
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex)
End Try
End Sub
Private Sub MyRange_RangesChanged(ByVal Sender As RangeSwitcher(Of UserPost)) Handles MyRange.RangesChanged
If Sender.Count > 0 Then MyRange_IndexChanged(0)
End Sub
#End Region
End Class

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 373 B

115
SCrawler/DownloadedInfoForm.Designer.vb generated Normal file
View File

@@ -0,0 +1,115 @@
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Friend Class DownloadedInfoForm : Inherits System.Windows.Forms.Form
<System.Diagnostics.DebuggerNonUserCode()>
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
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(DownloadedInfoForm))
Me.ToolbarTOP = New System.Windows.Forms.ToolStrip()
Me.MENU_VIEW = New System.Windows.Forms.ToolStripDropDownButton()
Me.MENU_VIEW_SESSION = New System.Windows.Forms.ToolStripMenuItem()
Me.MENU_VIEW_ALL = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_REFRESH = New System.Windows.Forms.ToolStripButton()
Me.ToolbarBOTTOM = New System.Windows.Forms.StatusStrip()
Me.LIST_DOWN = New System.Windows.Forms.ListBox()
Me.ToolbarTOP.SuspendLayout()
Me.SuspendLayout()
'
'ToolbarTOP
'
Me.ToolbarTOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden
Me.ToolbarTOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.MENU_VIEW, Me.BTT_REFRESH})
Me.ToolbarTOP.Location = New System.Drawing.Point(0, 0)
Me.ToolbarTOP.Name = "ToolbarTOP"
Me.ToolbarTOP.Size = New System.Drawing.Size(554, 25)
Me.ToolbarTOP.TabIndex = 0
'
'MENU_VIEW
'
Me.MENU_VIEW.AutoToolTip = False
Me.MENU_VIEW.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text
Me.MENU_VIEW.DropDownItems.AddRange(New System.Windows.Forms.ToolStripItem() {Me.MENU_VIEW_SESSION, Me.MENU_VIEW_ALL})
Me.MENU_VIEW.Image = CType(resources.GetObject("MENU_VIEW.Image"), System.Drawing.Image)
Me.MENU_VIEW.ImageTransparentColor = System.Drawing.Color.Magenta
Me.MENU_VIEW.Name = "MENU_VIEW"
Me.MENU_VIEW.Size = New System.Drawing.Size(45, 22)
Me.MENU_VIEW.Text = "View"
'
'MENU_VIEW_SESSION
'
Me.MENU_VIEW_SESSION.AutoToolTip = True
Me.MENU_VIEW_SESSION.Name = "MENU_VIEW_SESSION"
Me.MENU_VIEW_SESSION.Size = New System.Drawing.Size(180, 22)
Me.MENU_VIEW_SESSION.Text = "Session"
Me.MENU_VIEW_SESSION.ToolTipText = "Show downloaded users by this session"
'
'MENU_VIEW_ALL
'
Me.MENU_VIEW_ALL.AutoToolTip = True
Me.MENU_VIEW_ALL.Name = "MENU_VIEW_ALL"
Me.MENU_VIEW_ALL.Size = New System.Drawing.Size(180, 22)
Me.MENU_VIEW_ALL.Text = "All"
Me.MENU_VIEW_ALL.ToolTipText = "Show all users (sorted by latest download)"
'
'BTT_REFRESH
'
Me.BTT_REFRESH.Image = Global.SCrawler.My.Resources.Resources.Refresh
Me.BTT_REFRESH.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_REFRESH.Name = "BTT_REFRESH"
Me.BTT_REFRESH.Size = New System.Drawing.Size(89, 22)
Me.BTT_REFRESH.Text = "Refresh (F5)"
Me.BTT_REFRESH.ToolTipText = "Force list refresh"
'
'ToolbarBOTTOM
'
Me.ToolbarBOTTOM.Location = New System.Drawing.Point(0, 389)
Me.ToolbarBOTTOM.Name = "ToolbarBOTTOM"
Me.ToolbarBOTTOM.Size = New System.Drawing.Size(554, 22)
Me.ToolbarBOTTOM.TabIndex = 1
'
'LIST_DOWN
'
Me.LIST_DOWN.Dock = System.Windows.Forms.DockStyle.Fill
Me.LIST_DOWN.FormattingEnabled = True
Me.LIST_DOWN.Location = New System.Drawing.Point(0, 25)
Me.LIST_DOWN.Name = "LIST_DOWN"
Me.LIST_DOWN.Size = New System.Drawing.Size(554, 364)
Me.LIST_DOWN.TabIndex = 2
'
'DownloadedInfoForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(554, 411)
Me.Controls.Add(Me.LIST_DOWN)
Me.Controls.Add(Me.ToolbarBOTTOM)
Me.Controls.Add(Me.ToolbarTOP)
Me.KeyPreview = True
Me.MinimumSize = New System.Drawing.Size(570, 450)
Me.Name = "DownloadedInfoForm"
Me.ShowIcon = False
Me.Text = "Downloaded items"
Me.ToolbarTOP.ResumeLayout(False)
Me.ToolbarTOP.PerformLayout()
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Private WithEvents ToolbarTOP As ToolStrip
Private WithEvents MENU_VIEW As ToolStripDropDownButton
Private WithEvents MENU_VIEW_SESSION As ToolStripMenuItem
Private WithEvents MENU_VIEW_ALL As ToolStripMenuItem
Private WithEvents BTT_REFRESH As ToolStripButton
Private WithEvents ToolbarBOTTOM As StatusStrip
Private WithEvents LIST_DOWN As ListBox
End Class

View File

@@ -0,0 +1,142 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="ToolbarTOP.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="MENU_VIEW.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
TgDQASA1MVpwzwAAAABJRU5ErkJggg==
</value>
</data>
<metadata name="ToolbarBOTTOM.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>133, 17</value>
</metadata>
</root>

View File

@@ -0,0 +1,124 @@
Imports System.ComponentModel
Imports PersonalUtilities.Forms
Imports SCrawler.API.Base
Friend Class DownloadedInfoForm
Private MyView As FormsView
Private ReadOnly LParams As New ListAddParams(LAP.IgnoreICopier) With {.e = EDP.None}
Friend Enum ViewModes As Integer
Session = 0
All = 1
End Enum
Friend Property ViewMode As ViewModes
Get
Return IIf(MENU_VIEW_ALL.Checked, ViewModes.All, ViewModes.Session)
End Get
Set(ByVal SMode As ViewModes)
Settings.InfoViewMode.Value = CInt(SMode)
End Set
End Property
Private ReadOnly _TempUsersList As List(Of IUserData)
Friend Sub New()
InitializeComponent()
_TempUsersList = New List(Of IUserData)
If Settings.InfoViewMode.Value = CInt(ViewModes.All) Then
MENU_VIEW_SESSION.Checked = False
MENU_VIEW_ALL.Checked = True
Else
MENU_VIEW_SESSION.Checked = True
MENU_VIEW_ALL.Checked = False
End If
Settings.InfoViewMode.Value = ViewMode
RefillList()
End Sub
Private Sub DownloadedInfoForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
If MyView Is Nothing Then
MyView = New FormsView(Me)
MyView.ImportFromXML(Settings.Design)
MyView.SetMeSize()
End If
RefillList()
Catch ex As Exception
End Try
End Sub
Private Sub DownloadedInfoForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
e.Cancel = True
Hide()
End Sub
Private Sub DownloadedInfoForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
If Not MyView Is Nothing Then MyView.Dispose(Settings.Design)
_TempUsersList.Clear()
End Sub
Private Sub DownloadedInfoForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If e.KeyCode = Keys.F5 Then RefillList() : e.Handled = True
End Sub
Private Class UsersDateOrder : Implements IComparer(Of IUserData)
Friend Function Compare(ByVal x As IUserData, ByVal y As IUserData) As Integer Implements IComparer(Of IUserData).Compare
Dim xv& = If(DirectCast(x, UserDataBase).LastUpdated.HasValue, DirectCast(x, UserDataBase).LastUpdated.Value.Ticks, 0)
Dim yv& = If(DirectCast(y, UserDataBase).LastUpdated.HasValue, DirectCast(y, UserDataBase).LastUpdated.Value.Ticks, 0)
Return xv.CompareTo(yv) * -1
End Function
End Class
Private Sub RefillList()
Try
_TempUsersList.Clear()
Dim lClear As Action = Sub() LIST_DOWN.Items.Clear()
If LIST_DOWN.InvokeRequired Then LIST_DOWN.Invoke(lClear) Else lClear.Invoke
If ViewMode = ViewModes.Session Then
_TempUsersList.ListAddList(Downloader.Downloaded, LParams)
Else
_TempUsersList.ListAddList(Settings.Users.SelectMany(Of IUserData) _
(Function(u) If(u.IsCollection, DirectCast(u, API.UserDataBind).Collections, {u})), LParams)
End If
If _TempUsersList.Count > 0 Then
_TempUsersList.Sort(New UsersDateOrder)
For Each user As IUserData In _TempUsersList
If LIST_DOWN.InvokeRequired Then
LIST_DOWN.Invoke(Sub() LIST_DOWN.Items.Add(user.DownloadedInformation))
Else
LIST_DOWN.Items.Add(user.DownloadedInformation)
End If
Next
If _LatestSelected >= 0 AndAlso _LatestSelected <= LIST_DOWN.Items.Count - 1 Then
Dim aSel As Action = Sub() LIST_DOWN.SelectedIndex = _LatestSelected
If LIST_DOWN.InvokeRequired Then LIST_DOWN.Invoke(aSel) Else aSel.Invoke
Else
_LatestSelected = -1
End If
Else
_LatestSelected = -1
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendInLog, ex, "[DownloadedInfoForm.RefillList]")
End Try
End Sub
Private Sub MENU_VIEW_SESSION_Click(sender As Object, e As EventArgs) Handles MENU_VIEW_SESSION.Click
MENU_VIEW_SESSION.Checked = True
MENU_VIEW_ALL.Checked = False
ViewMode = ViewModes.Session
RefillList()
End Sub
Private Sub MENU_VIEW_ALL_Click(sender As Object, e As EventArgs) Handles MENU_VIEW_ALL.Click
MENU_VIEW_SESSION.Checked = False
MENU_VIEW_ALL.Checked = True
ViewMode = ViewModes.All
RefillList()
End Sub
Private Sub BTT_REFRESH_Click(sender As Object, e As EventArgs) Handles BTT_REFRESH.Click
RefillList()
End Sub
Private _LatestSelected As Integer = -1
Private Sub LIST_DOWN_SelectedIndexChanged(sender As Object, e As EventArgs) Handles LIST_DOWN.SelectedIndexChanged
_LatestSelected = LIST_DOWN.SelectedIndex
End Sub
Private Sub LIST_DOWN_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles LIST_DOWN.MouseDoubleClick
Try
If _LatestSelected >= 0 AndAlso _LatestSelected <= _TempUsersList.Count - 1 AndAlso
Not DirectCast(_TempUsersList(_LatestSelected), UserDataBase).Disposed Then _TempUsersList(_LatestSelected).OpenFolder()
Catch ex As Exception
End Try
End Sub
Friend Sub Downloader_OnDownloadCountChange()
If ViewMode = ViewModes.Session Then RefillList()
End Sub
End Class

View File

@@ -0,0 +1,87 @@
Namespace Editors
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Friend Class CollectionEditorForm : Inherits System.Windows.Forms.Form
<System.Diagnostics.DebuggerNonUserCode()>
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
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(CollectionEditorForm))
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
Me.CMB_COLLECTIONS = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
Me.CONTAINER_MAIN.ContentPanel.SuspendLayout()
Me.CONTAINER_MAIN.SuspendLayout()
CType(Me.CMB_COLLECTIONS, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'CONTAINER_MAIN
'
'
'CONTAINER_MAIN.ContentPanel
'
Me.CONTAINER_MAIN.ContentPanel.Controls.Add(Me.CMB_COLLECTIONS)
Me.CONTAINER_MAIN.ContentPanel.Padding = New System.Windows.Forms.Padding(2, 0, 2, 0)
Me.CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(454, 251)
Me.CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
Me.CONTAINER_MAIN.LeftToolStripPanelVisible = False
Me.CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
Me.CONTAINER_MAIN.Name = "CONTAINER_MAIN"
Me.CONTAINER_MAIN.RightToolStripPanelVisible = False
Me.CONTAINER_MAIN.Size = New System.Drawing.Size(454, 251)
Me.CONTAINER_MAIN.TabIndex = 0
Me.CONTAINER_MAIN.TopToolStripPanelVisible = False
'
'CMB_COLLECTIONS
'
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
ActionButton1.Index = 0
ActionButton1.Name = "BTT_COMBOBOX_ARROW"
ActionButton1.Visible = False
ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image)
ActionButton2.Index = 1
ActionButton2.Name = "BTT_ADD"
ActionButton2.ToolTipText = "Add new collection"
Me.CMB_COLLECTIONS.Buttons.Add(ActionButton1)
Me.CMB_COLLECTIONS.Buttons.Add(ActionButton2)
Me.CMB_COLLECTIONS.Dock = System.Windows.Forms.DockStyle.Fill
Me.CMB_COLLECTIONS.ListDropDownStyle = PersonalUtilities.Forms.Controls.ComboBoxExtended.ListMode.Simple
Me.CMB_COLLECTIONS.Location = New System.Drawing.Point(2, 0)
Me.CMB_COLLECTIONS.Name = "CMB_COLLECTIONS"
Me.CMB_COLLECTIONS.Size = New System.Drawing.Size(452, 252)
Me.CMB_COLLECTIONS.TabIndex = 0
'
'CollectionEditorForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(454, 251)
Me.Controls.Add(Me.CONTAINER_MAIN)
Me.KeyPreview = True
Me.MinimizeBox = False
Me.MinimumSize = New System.Drawing.Size(470, 290)
Me.Name = "CollectionEditorForm"
Me.ShowIcon = False
Me.ShowInTaskbar = False
Me.Text = "Collection"
Me.CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
Me.CONTAINER_MAIN.ResumeLayout(False)
Me.CONTAINER_MAIN.PerformLayout()
CType(Me.CMB_COLLECTIONS, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
End Sub
Private WithEvents CONTAINER_MAIN As ToolStripContainer
Private WithEvents CMB_COLLECTIONS As PersonalUtilities.Forms.Controls.ComboBoxExtended
End Class
End Namespace

View File

@@ -0,0 +1,233 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="ActionButton1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
AAAASUVORK5CYII=
</value>
</data>
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAADmUlE
QVRIS62WWWxMURjHL220JW1HausmlFrDFKUhnUGH6bRFzJ2idImlC0Vp2mlji1A8iNhCPIjIRES8EU+W
h2oEtbSDTk3HNNM7S01VKsXjkb/vXBo3k1Ee7sMvmZzzzf//ne/+z50RAAxL1MUIG4G/YAv3HSVhF5Vw
IYNdz3LadVj9RgdTB+HQYYPHIJuE1ocSdlEJFzG+1bPRLQLinglIeCkg+XUkKvz56hnkOfQs/rmA8S9H
YEp7FDI64tAQtKhnsMapZ7zzNHsUFnbGY4VzIk70l6hnIH4wsDR7NBZ3apDrSqL5T8eFgUr1DLZ78lim
Q4N8VzK29MxEpZSBa4M16hnU+c3M9CEFpdJsVHsXos63DDcHrf9nQEXD5VymwW/5USLNwl5vJhp7dTgW
NML2pR7jbsUMS+KdMTa5Q8NQxinfBU4dRFcOyjy52OtbhwOBDTgZLKPPmTgY0ON4MBdNfSbYBupxY8Aq
G10dqMG5/nIc7ytGQ6CQRliAamkTN/g1Ai4e95Qy3iogpX0UtBRDnhRzdxq2SXOxz5eFQ70rScCEU335
ssGxj0YS06HSm4GN3ekwdE2C1hGH1LZR0JDOJof5jwHvnIvzTa0jlooTYfktvt+fhcOBHDQFTWRgxJGP
ObAGsulZLMLWnjlY756K5c4JmNcRi6T2SGheCIihS2l5ozAo6NRhMolnUAcGV6IcwwqvFrX+JTjYuwKH
SfRAYDms/mzs9y1GFe2VSnOw1j0FejqpLN4WCX4ZufiIBwLMLxQGm12rsLQzgWKYgmLPLNTQw6ynpDSS
IBet8y+TqaVRVdFIeJrWuCcj+/0EzH43BomvIhBLI45uFiDcJ+6QwROFwa6+Amb9bGFNg6Xs9Ncd7Oy3
Knb2eyU7/20nu9y/m136tIvEl6BC0qKoZwby3alo9JVhj7T5R7m/kJVIIityi8zyXmTiW+I10SqyIQNb
uIgNwYuuf25kFd75KPKkI49OmUWnrfYWyXv/wBb2cijhhVf6a9lGei65XclYRDd6mj0GWz2iLBJaH0rY
RSVc5Eywmhm7kuQXHX+bJlBStrh+zTi0PpSwi0q4yNFAOVvgiEcKJWUsxZn/NhT+znlofShhF5VwkRpv
MUtti4KGYjj6sYCIh5QSu4oG27stjItHU+cjeQzvkcFzFQ2KnSKLoc4FukDCXeI2GbSoaFD4ziyPxNxK
0AUyNxOP1DOwcaG/8I+/LRB+At7psBnyDBG0AAAAAElFTkSuQmCC
</value>
</data>
</root>

View File

@@ -0,0 +1,81 @@
Imports System.ComponentModel
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Controls.Base
Imports PersonalUtilities.Forms.Toolbars
Namespace Editors
Friend Class CollectionEditorForm : Implements IOkCancelToolbar
Private ReadOnly MyDefs As DefaultFormProps
Private ReadOnly Collections As List(Of String)
Friend Property [Collection] As String = String.Empty
Friend Sub New()
InitializeComponent()
MyDefs = New DefaultFormProps
Collections = New List(Of String)
End Sub
Friend Sub New(ByVal CollectionName As String)
Me.New
Collection = CollectionName
End Sub
Private Sub CollectionEditorForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
With MyDefs
.MyViewInitialize(Me, Settings.Design)
.MyOkCancel = New OkCancelToolbar(Me, Me, CONTAINER_MAIN.BottomToolStripPanel)
.MyOkCancel.AddThisToolbar()
Collections.ListAddList((From c In Settings.Users Where c.IsCollection Select c.CollectionName), LAP.NotContainsOnly, EDP.ThrowException)
If Collections.ListExists Then CMB_COLLECTIONS.Items.AddRange(From c In Collections Select New Controls.Base.ListItem(c))
If Not Collection.IsEmptyString And Collections.Contains(Collection) Then CMB_COLLECTIONS.SelectedIndex = Collections.IndexOf(Collection)
End With
Catch ex As Exception
MyDefs.InvokeLoaderError(ex)
End Try
End Sub
Private Sub CollectionEditorForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
If Not BeforeCloseChecker(MyDefs.ChangesDetected) Then
e.Cancel = True
Else
Collections.Clear()
MyDefs.Dispose()
End If
End Sub
Private Sub CollectionEditorForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If e.KeyCode = Keys.Insert Then
AddNewCollection()
e.Handled = True
Else
e.Handled = False
End If
End Sub
Private Sub ToolbarBttOK() Implements IOkCancelToolbar.ToolbarBttOK
If CMB_COLLECTIONS.SelectedIndex >= 0 Then
Collection = CMB_COLLECTIONS.Value.ToString
MyDefs.ChangesDetected = False
DialogResult = DialogResult.OK
Close()
Else
MsgBoxE("Collection does not selected", MsgBoxStyle.Exclamation)
End If
End Sub
Private Sub ToolbarBttCancel() Implements IOkCancelToolbar.ToolbarBttCancel
MyDefs.ChangesDetected = False
DialogResult = DialogResult.Cancel
Close()
End Sub
Private Sub CMB_COLLECTIONS_ActionOnButtonClick(ByVal Sender As ActionButton) Handles CMB_COLLECTIONS.ActionOnButtonClick
If Sender.DefaultButton = ActionButton.DefaultButtons.Add Then AddNewCollection()
End Sub
Private Sub AddNewCollection()
Dim c$ = InputBoxE("Enter new collection name:", "Collection name")
If Not c.IsEmptyString Then
If Not Collections.Contains(c) Then
Collections.Add(c)
CMB_COLLECTIONS.Items.Add(c)
CMB_COLLECTIONS.SelectedIndex = CMB_COLLECTIONS.Count - 1
Else
Dim i% = Collections.IndexOf(c)
If i >= 0 Then CMB_COLLECTIONS.SelectedIndex = i
End If
End If
End Sub
End Class
End Namespace

View File

@@ -0,0 +1,290 @@
Namespace Editors
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Friend Class GlobalSettingsForm : Inherits System.Windows.Forms.Form
<System.Diagnostics.DebuggerNonUserCode()>
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
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container()
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(GlobalSettingsForm))
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton3 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TP_IMAGES As System.Windows.Forms.TableLayoutPanel
Dim TP_CHANNELS_IMGS As System.Windows.Forms.TableLayoutPanel
Dim TT_MAIN As System.Windows.Forms.ToolTip
Me.TXT_GLOBAL_PATH = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.CH_SEPARATE_VIDEO_FOLDER = New System.Windows.Forms.CheckBox()
Me.TXT_COLLECTIONS_PATH = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_IMAGE_LARGE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_IMAGE_SMALL = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.CH_DEF_TEMP = New System.Windows.Forms.CheckBox()
Me.TXT_CHANNELS_ROWS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_CHANNELS_COLUMNS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
TP_IMAGES = New System.Windows.Forms.TableLayoutPanel()
TP_CHANNELS_IMGS = New System.Windows.Forms.TableLayoutPanel()
TT_MAIN = New System.Windows.Forms.ToolTip(Me.components)
TP_MAIN.SuspendLayout()
CType(Me.TXT_GLOBAL_PATH, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_COLLECTIONS_PATH, System.ComponentModel.ISupportInitialize).BeginInit()
TP_IMAGES.SuspendLayout()
CType(Me.TXT_IMAGE_LARGE, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_IMAGE_SMALL, System.ComponentModel.ISupportInitialize).BeginInit()
TP_CHANNELS_IMGS.SuspendLayout()
CType(Me.TXT_CHANNELS_ROWS, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_CHANNELS_COLUMNS, System.ComponentModel.ISupportInitialize).BeginInit()
Me.CONTAINER_MAIN.ContentPanel.SuspendLayout()
Me.CONTAINER_MAIN.SuspendLayout()
Me.SuspendLayout()
'
'TP_MAIN
'
TP_MAIN.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
TP_MAIN.ColumnCount = 1
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MAIN.Controls.Add(Me.TXT_GLOBAL_PATH, 0, 0)
TP_MAIN.Controls.Add(Me.CH_SEPARATE_VIDEO_FOLDER, 0, 2)
TP_MAIN.Controls.Add(Me.TXT_COLLECTIONS_PATH, 0, 4)
TP_MAIN.Controls.Add(TP_IMAGES, 0, 1)
TP_MAIN.Controls.Add(Me.CH_DEF_TEMP, 0, 3)
TP_MAIN.Controls.Add(TP_CHANNELS_IMGS, 0, 5)
TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
TP_MAIN.Location = New System.Drawing.Point(0, 0)
TP_MAIN.Name = "TP_MAIN"
TP_MAIN.RowCount = 6
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667!))
TP_MAIN.Size = New System.Drawing.Size(584, 191)
TP_MAIN.TabIndex = 0
'
'TXT_GLOBAL_PATH
'
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
ActionButton1.Index = 0
ActionButton1.Name = "BTT_OPEN"
ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image)
ActionButton2.Index = 1
ActionButton2.Name = "BTT_CLEAR"
Me.TXT_GLOBAL_PATH.Buttons.Add(ActionButton1)
Me.TXT_GLOBAL_PATH.Buttons.Add(ActionButton2)
Me.TXT_GLOBAL_PATH.CaptionText = "Data Path"
Me.TXT_GLOBAL_PATH.CaptionToolTipEnabled = True
Me.TXT_GLOBAL_PATH.CaptionToolTipText = "Root path for storing users' data"
Me.TXT_GLOBAL_PATH.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_GLOBAL_PATH.Location = New System.Drawing.Point(4, 4)
Me.TXT_GLOBAL_PATH.Name = "TXT_GLOBAL_PATH"
Me.TXT_GLOBAL_PATH.Size = New System.Drawing.Size(576, 22)
Me.TXT_GLOBAL_PATH.TabIndex = 0
'
'CH_SEPARATE_VIDEO_FOLDER
'
Me.CH_SEPARATE_VIDEO_FOLDER.AutoSize = True
Me.CH_SEPARATE_VIDEO_FOLDER.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_SEPARATE_VIDEO_FOLDER.Location = New System.Drawing.Point(4, 66)
Me.CH_SEPARATE_VIDEO_FOLDER.Name = "CH_SEPARATE_VIDEO_FOLDER"
Me.CH_SEPARATE_VIDEO_FOLDER.Padding = New System.Windows.Forms.Padding(100, 0, 0, 0)
Me.CH_SEPARATE_VIDEO_FOLDER.Size = New System.Drawing.Size(576, 24)
Me.CH_SEPARATE_VIDEO_FOLDER.TabIndex = 2
Me.CH_SEPARATE_VIDEO_FOLDER.Text = "Separate video folders"
TT_MAIN.SetToolTip(Me.CH_SEPARATE_VIDEO_FOLDER, resources.GetString("CH_SEPARATE_VIDEO_FOLDER.ToolTip"))
Me.CH_SEPARATE_VIDEO_FOLDER.UseVisualStyleBackColor = True
'
'TXT_COLLECTIONS_PATH
'
ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image)
ActionButton3.Index = 0
ActionButton3.Name = "BTT_CLEAR"
Me.TXT_COLLECTIONS_PATH.Buttons.Add(ActionButton3)
Me.TXT_COLLECTIONS_PATH.CaptionText = "Collections folder"
Me.TXT_COLLECTIONS_PATH.CaptionToolTipEnabled = True
Me.TXT_COLLECTIONS_PATH.CaptionToolTipText = "Set collections folder name (name only)"
Me.TXT_COLLECTIONS_PATH.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_COLLECTIONS_PATH.Location = New System.Drawing.Point(4, 128)
Me.TXT_COLLECTIONS_PATH.Name = "TXT_COLLECTIONS_PATH"
Me.TXT_COLLECTIONS_PATH.Size = New System.Drawing.Size(576, 22)
Me.TXT_COLLECTIONS_PATH.TabIndex = 4
'
'TP_IMAGES
'
TP_IMAGES.ColumnCount = 2
TP_IMAGES.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_IMAGES.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_IMAGES.Controls.Add(Me.TXT_IMAGE_LARGE, 0, 0)
TP_IMAGES.Controls.Add(Me.TXT_IMAGE_SMALL, 1, 0)
TP_IMAGES.Dock = System.Windows.Forms.DockStyle.Fill
TP_IMAGES.Location = New System.Drawing.Point(1, 32)
TP_IMAGES.Margin = New System.Windows.Forms.Padding(0)
TP_IMAGES.Name = "TP_IMAGES"
TP_IMAGES.RowCount = 1
TP_IMAGES.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_IMAGES.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30.0!))
TP_IMAGES.Size = New System.Drawing.Size(582, 30)
TP_IMAGES.TabIndex = 1
'
'TXT_IMAGE_LARGE
'
Me.TXT_IMAGE_LARGE.CaptionText = "Large image size"
Me.TXT_IMAGE_LARGE.CaptionToolTipEnabled = True
Me.TXT_IMAGE_LARGE.CaptionToolTipText = "Maximum large image size by height"
Me.TXT_IMAGE_LARGE.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown
Me.TXT_IMAGE_LARGE.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_IMAGE_LARGE.Location = New System.Drawing.Point(3, 3)
Me.TXT_IMAGE_LARGE.Name = "TXT_IMAGE_LARGE"
Me.TXT_IMAGE_LARGE.NumberMaximum = New Decimal(New Integer() {1000, 0, 0, 0})
Me.TXT_IMAGE_LARGE.NumberMinimum = New Decimal(New Integer() {50, 0, 0, 0})
Me.TXT_IMAGE_LARGE.Size = New System.Drawing.Size(285, 22)
Me.TXT_IMAGE_LARGE.TabIndex = 0
Me.TXT_IMAGE_LARGE.Text = "50"
Me.TXT_IMAGE_LARGE.TextBoxTextAlign = System.Windows.Forms.HorizontalAlignment.Center
'
'TXT_IMAGE_SMALL
'
Me.TXT_IMAGE_SMALL.CaptionText = "Small image size"
Me.TXT_IMAGE_SMALL.CaptionToolTipEnabled = True
Me.TXT_IMAGE_SMALL.CaptionToolTipText = "Maximum small image size by height"
Me.TXT_IMAGE_SMALL.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown
Me.TXT_IMAGE_SMALL.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_IMAGE_SMALL.Location = New System.Drawing.Point(294, 3)
Me.TXT_IMAGE_SMALL.Name = "TXT_IMAGE_SMALL"
Me.TXT_IMAGE_SMALL.NumberMaximum = New Decimal(New Integer() {500, 0, 0, 0})
Me.TXT_IMAGE_SMALL.NumberMinimum = New Decimal(New Integer() {10, 0, 0, 0})
Me.TXT_IMAGE_SMALL.Size = New System.Drawing.Size(285, 22)
Me.TXT_IMAGE_SMALL.TabIndex = 1
Me.TXT_IMAGE_SMALL.Text = "10"
Me.TXT_IMAGE_SMALL.TextBoxTextAlign = System.Windows.Forms.HorizontalAlignment.Center
'
'CH_DEF_TEMP
'
Me.CH_DEF_TEMP.AutoSize = True
Me.CH_DEF_TEMP.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_DEF_TEMP.Location = New System.Drawing.Point(4, 97)
Me.CH_DEF_TEMP.Name = "CH_DEF_TEMP"
Me.CH_DEF_TEMP.Padding = New System.Windows.Forms.Padding(100, 0, 0, 0)
Me.CH_DEF_TEMP.Size = New System.Drawing.Size(576, 24)
Me.CH_DEF_TEMP.TabIndex = 3
Me.CH_DEF_TEMP.Text = "Temporary default"
TT_MAIN.SetToolTip(Me.CH_DEF_TEMP, "Default value on user creating")
Me.CH_DEF_TEMP.UseVisualStyleBackColor = True
'
'TP_CHANNELS_IMGS
'
TP_CHANNELS_IMGS.ColumnCount = 2
TP_CHANNELS_IMGS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_CHANNELS_IMGS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_CHANNELS_IMGS.Controls.Add(Me.TXT_CHANNELS_ROWS, 0, 0)
TP_CHANNELS_IMGS.Controls.Add(Me.TXT_CHANNELS_COLUMNS, 1, 0)
TP_CHANNELS_IMGS.Dock = System.Windows.Forms.DockStyle.Fill
TP_CHANNELS_IMGS.Location = New System.Drawing.Point(1, 156)
TP_CHANNELS_IMGS.Margin = New System.Windows.Forms.Padding(0)
TP_CHANNELS_IMGS.Name = "TP_CHANNELS_IMGS"
TP_CHANNELS_IMGS.RowCount = 1
TP_CHANNELS_IMGS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_CHANNELS_IMGS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 34.0!))
TP_CHANNELS_IMGS.Size = New System.Drawing.Size(582, 34)
TP_CHANNELS_IMGS.TabIndex = 5
'
'TXT_CHANNELS_ROWS
'
Me.TXT_CHANNELS_ROWS.CaptionText = "Channels rows"
Me.TXT_CHANNELS_ROWS.CaptionToolTipEnabled = True
Me.TXT_CHANNELS_ROWS.CaptionToolTipText = "How many images' rows should be shown in the channels form"
Me.TXT_CHANNELS_ROWS.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown
Me.TXT_CHANNELS_ROWS.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_CHANNELS_ROWS.Location = New System.Drawing.Point(3, 3)
Me.TXT_CHANNELS_ROWS.Name = "TXT_CHANNELS_ROWS"
Me.TXT_CHANNELS_ROWS.Size = New System.Drawing.Size(285, 22)
Me.TXT_CHANNELS_ROWS.TabIndex = 0
Me.TXT_CHANNELS_ROWS.Text = "0"
Me.TXT_CHANNELS_ROWS.TextBoxTextAlign = System.Windows.Forms.HorizontalAlignment.Center
'
'TXT_CHANNELS_COLUMNS
'
Me.TXT_CHANNELS_COLUMNS.CaptionText = "Channels columns"
Me.TXT_CHANNELS_COLUMNS.CaptionToolTipEnabled = True
Me.TXT_CHANNELS_COLUMNS.CaptionToolTipText = "How many images' columns should be shown in the channels form"
Me.TXT_CHANNELS_COLUMNS.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown
Me.TXT_CHANNELS_COLUMNS.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_CHANNELS_COLUMNS.Location = New System.Drawing.Point(294, 3)
Me.TXT_CHANNELS_COLUMNS.Name = "TXT_CHANNELS_COLUMNS"
Me.TXT_CHANNELS_COLUMNS.Size = New System.Drawing.Size(285, 22)
Me.TXT_CHANNELS_COLUMNS.TabIndex = 1
Me.TXT_CHANNELS_COLUMNS.Text = "0"
Me.TXT_CHANNELS_COLUMNS.TextBoxTextAlign = System.Windows.Forms.HorizontalAlignment.Center
'
'CONTAINER_MAIN
'
'
'CONTAINER_MAIN.ContentPanel
'
Me.CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
Me.CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(584, 191)
Me.CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
Me.CONTAINER_MAIN.LeftToolStripPanelVisible = False
Me.CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
Me.CONTAINER_MAIN.Name = "CONTAINER_MAIN"
Me.CONTAINER_MAIN.RightToolStripPanelVisible = False
Me.CONTAINER_MAIN.Size = New System.Drawing.Size(584, 191)
Me.CONTAINER_MAIN.TabIndex = 0
Me.CONTAINER_MAIN.TopToolStripPanelVisible = False
'
'GlobalSettingsForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(584, 191)
Me.Controls.Add(Me.CONTAINER_MAIN)
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
Me.KeyPreview = True
Me.MaximizeBox = False
Me.MaximumSize = New System.Drawing.Size(600, 230)
Me.MinimizeBox = False
Me.MinimumSize = New System.Drawing.Size(600, 230)
Me.Name = "GlobalSettingsForm"
Me.ShowIcon = False
Me.ShowInTaskbar = False
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
Me.Text = "Settings"
TP_MAIN.ResumeLayout(False)
TP_MAIN.PerformLayout()
CType(Me.TXT_GLOBAL_PATH, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_COLLECTIONS_PATH, System.ComponentModel.ISupportInitialize).EndInit()
TP_IMAGES.ResumeLayout(False)
CType(Me.TXT_IMAGE_LARGE, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_IMAGE_SMALL, System.ComponentModel.ISupportInitialize).EndInit()
TP_CHANNELS_IMGS.ResumeLayout(False)
CType(Me.TXT_CHANNELS_ROWS, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_CHANNELS_COLUMNS, System.ComponentModel.ISupportInitialize).EndInit()
Me.CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
Me.CONTAINER_MAIN.ResumeLayout(False)
Me.CONTAINER_MAIN.PerformLayout()
Me.ResumeLayout(False)
End Sub
Private WithEvents CONTAINER_MAIN As ToolStripContainer
Private WithEvents TXT_GLOBAL_PATH As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents CH_SEPARATE_VIDEO_FOLDER As CheckBox
Private WithEvents TXT_COLLECTIONS_PATH As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents TXT_IMAGE_LARGE As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents TXT_IMAGE_SMALL As PersonalUtilities.Forms.Controls.TextBoxExtended
Friend WithEvents CH_DEF_TEMP As CheckBox
Private WithEvents TXT_CHANNELS_ROWS As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents TXT_CHANNELS_COLUMNS As PersonalUtilities.Forms.Controls.TextBoxExtended
End Class
End Namespace

View File

@@ -0,0 +1,168 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="TP_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="ActionButton1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
cMaRN0UdBBkAAAAASUVORK5CYII=
</value>
</data>
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<metadata name="TT_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="TT_MAIN.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<data name="CH_SEPARATE_VIDEO_FOLDER.ToolTip" xml:space="preserve">
<value>This is global setting for new added only users.
This parameter indicates how video will be stored in users' download path.
If checked then videos will be stored in separated folder; otherwise, videos will be stored with pictures together.</value>
</data>
<data name="ActionButton3.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<metadata name="TP_IMAGES.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="TP_CHANNELS_IMGS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
</root>

View File

@@ -0,0 +1,65 @@
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Controls.Base
Imports PersonalUtilities.Forms.Toolbars
Namespace Editors
Friend Class GlobalSettingsForm : Implements IOkCancelToolbar
Private ReadOnly MyDefs As DefaultFormProps(Of FieldsChecker)
Friend Sub New()
InitializeComponent()
MyDefs = New DefaultFormProps(Of FieldsChecker)
End Sub
Private Sub GlobalSettingsForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
With MyDefs
.MyViewInitialize(Me, Settings.Design, True)
.AddOkCancelToolbar()
.DelegateClosingChecker()
With Settings
TXT_GLOBAL_PATH.Text = .GlobalPath.Value
TXT_IMAGE_LARGE.Value = .MaxLargeImageHeigh.Value
TXT_IMAGE_SMALL.Value = .MaxSmallImageHeigh.Value
TXT_COLLECTIONS_PATH.Text = .CollectionsPath
CH_SEPARATE_VIDEO_FOLDER.Checked = .SeparateVideoFolder.Value
CH_DEF_TEMP.Checked = .DefaultTemporary.Value
TXT_CHANNELS_COLUMNS.Value = .ChannelsImagesColumns.Value
TXT_CHANNELS_ROWS.Value = .ChannelsImagesRows.Value
End With
.MyFieldsChecker = New FieldsChecker
With .MyFieldsChecker
.AddControl(Of String)(TXT_GLOBAL_PATH, TXT_GLOBAL_PATH.CaptionText)
.AddControl(Of String)(TXT_COLLECTIONS_PATH, TXT_COLLECTIONS_PATH.CaptionText)
.EndLoaderOperations()
End With
.AppendDetectors()
.EndLoaderOperations()
End With
Catch ex As Exception
MyDefs.InvokeLoaderError(ex)
End Try
End Sub
Private Sub ToolbarBttOK() Implements IOkCancelToolbar.ToolbarBttOK
If MyDefs.MyFieldsChecker.AllParamsOK Then
With Settings
.GlobalPath.Value = TXT_GLOBAL_PATH.Text
.MaxLargeImageHeigh.Value = CInt(TXT_IMAGE_LARGE.Value)
.MaxSmallImageHeigh.Value = CInt(TXT_IMAGE_SMALL.Value)
.SeparateVideoFolder.Value = CH_SEPARATE_VIDEO_FOLDER.Checked
.CollectionsPath.Value = TXT_COLLECTIONS_PATH.Text
.DefaultTemporary.Value = CH_DEF_TEMP.Checked
.ChannelsImagesRows.Value = CInt(TXT_CHANNELS_ROWS.Value)
.ChannelsImagesColumns.Value = CInt(TXT_CHANNELS_COLUMNS.Value)
End With
MyDefs.CloseForm()
End If
End Sub
Private Sub ToolbarBttCancel() Implements IOkCancelToolbar.ToolbarBttCancel
MyDefs.CloseForm(DialogResult.Cancel)
End Sub
Private Sub TXT_GLOBAL_PATH_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_GLOBAL_PATH.ActionOnButtonClick
If Sender.DefaultButton = ActionButton.DefaultButtons.Open Then
Dim f As SFile = SFile.SelectPath(Settings.GlobalPath.Value)
If Not f.IsEmptyString Then TXT_GLOBAL_PATH.Text = f
End If
End Sub
End Class
End Namespace

92
SCrawler/Editors/LabelsForm.Designer.vb generated Normal file
View File

@@ -0,0 +1,92 @@
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Friend Class LabelsForm : Inherits System.Windows.Forms.Form
<System.Diagnostics.DebuggerNonUserCode()>
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
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(LabelsForm))
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton3 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
Me.CMB_LABELS = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
Me.CONTAINER_MAIN.ContentPanel.SuspendLayout()
Me.CONTAINER_MAIN.SuspendLayout()
CType(Me.CMB_LABELS, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'CONTAINER_MAIN
'
'
'CONTAINER_MAIN.ContentPanel
'
Me.CONTAINER_MAIN.ContentPanel.Controls.Add(Me.CMB_LABELS)
Me.CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(374, 421)
Me.CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
Me.CONTAINER_MAIN.LeftToolStripPanelVisible = False
Me.CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
Me.CONTAINER_MAIN.Name = "CONTAINER_MAIN"
Me.CONTAINER_MAIN.RightToolStripPanelVisible = False
Me.CONTAINER_MAIN.Size = New System.Drawing.Size(374, 421)
Me.CONTAINER_MAIN.TabIndex = 0
Me.CONTAINER_MAIN.TopToolStripPanelVisible = False
'
'CMB_LABELS
'
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
ActionButton1.Index = 0
ActionButton1.Name = "BTT_COMBOBOX_ARROW"
ActionButton1.Visible = False
ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image)
ActionButton2.Index = 1
ActionButton2.Name = "BTT_ADD"
ActionButton2.ToolTipText = "Add new label (Insert)"
ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image)
ActionButton3.Index = 2
ActionButton3.Name = "BTT_CLEAR"
ActionButton3.ToolTipText = "Clear checked labels"
Me.CMB_LABELS.Buttons.Add(ActionButton1)
Me.CMB_LABELS.Buttons.Add(ActionButton2)
Me.CMB_LABELS.Buttons.Add(ActionButton3)
Me.CMB_LABELS.Dock = System.Windows.Forms.DockStyle.Fill
Me.CMB_LABELS.ListCheckBoxes = True
Me.CMB_LABELS.ListDropDownStyle = PersonalUtilities.Forms.Controls.ComboBoxExtended.ListMode.Simple
Me.CMB_LABELS.ListGridVisible = True
Me.CMB_LABELS.ListMultiSelect = True
Me.CMB_LABELS.Location = New System.Drawing.Point(0, 0)
Me.CMB_LABELS.Name = "CMB_LABELS"
Me.CMB_LABELS.Size = New System.Drawing.Size(374, 421)
Me.CMB_LABELS.TabIndex = 0
'
'LabelsForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(374, 421)
Me.Controls.Add(Me.CONTAINER_MAIN)
Me.MinimizeBox = False
Me.MinimumSize = New System.Drawing.Size(390, 460)
Me.Name = "LabelsForm"
Me.ShowIcon = False
Me.ShowInTaskbar = False
Me.Text = "Labels"
Me.CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
Me.CONTAINER_MAIN.ResumeLayout(False)
Me.CONTAINER_MAIN.PerformLayout()
CType(Me.CMB_LABELS, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
End Sub
Private WithEvents CONTAINER_MAIN As ToolStripContainer
Private WithEvents CMB_LABELS As PersonalUtilities.Forms.Controls.ComboBoxExtended
End Class

View File

@@ -0,0 +1,241 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="ActionButton1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
AAAASUVORK5CYII=
</value>
</data>
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAADmUlE
QVRIS62WWWxMURjHL220JW1HausmlFrDFKUhnUGH6bRFzJ2idImlC0Vp2mlji1A8iNhCPIjIRES8EU+W
h2oEtbSDTk3HNNM7S01VKsXjkb/vXBo3k1Ee7sMvmZzzzf//ne/+z50RAAxL1MUIG4G/YAv3HSVhF5Vw
IYNdz3LadVj9RgdTB+HQYYPHIJuE1ocSdlEJFzG+1bPRLQLinglIeCkg+XUkKvz56hnkOfQs/rmA8S9H
YEp7FDI64tAQtKhnsMapZ7zzNHsUFnbGY4VzIk70l6hnIH4wsDR7NBZ3apDrSqL5T8eFgUr1DLZ78lim
Q4N8VzK29MxEpZSBa4M16hnU+c3M9CEFpdJsVHsXos63DDcHrf9nQEXD5VymwW/5USLNwl5vJhp7dTgW
NML2pR7jbsUMS+KdMTa5Q8NQxinfBU4dRFcOyjy52OtbhwOBDTgZLKPPmTgY0ON4MBdNfSbYBupxY8Aq
G10dqMG5/nIc7ytGQ6CQRliAamkTN/g1Ai4e95Qy3iogpX0UtBRDnhRzdxq2SXOxz5eFQ70rScCEU335
ssGxj0YS06HSm4GN3ekwdE2C1hGH1LZR0JDOJof5jwHvnIvzTa0jlooTYfktvt+fhcOBHDQFTWRgxJGP
ObAGsulZLMLWnjlY756K5c4JmNcRi6T2SGheCIihS2l5ozAo6NRhMolnUAcGV6IcwwqvFrX+JTjYuwKH
SfRAYDms/mzs9y1GFe2VSnOw1j0FejqpLN4WCX4ZufiIBwLMLxQGm12rsLQzgWKYgmLPLNTQw6ynpDSS
IBet8y+TqaVRVdFIeJrWuCcj+/0EzH43BomvIhBLI45uFiDcJ+6QwROFwa6+Amb9bGFNg6Xs9Ncd7Oy3
Knb2eyU7/20nu9y/m136tIvEl6BC0qKoZwby3alo9JVhj7T5R7m/kJVIIityi8zyXmTiW+I10SqyIQNb
uIgNwYuuf25kFd75KPKkI49OmUWnrfYWyXv/wBb2cijhhVf6a9lGei65XclYRDd6mj0GWz2iLBJaH0rY
RSVc5Eywmhm7kuQXHX+bJlBStrh+zTi0PpSwi0q4yNFAOVvgiEcKJWUsxZn/NhT+znlofShhF5VwkRpv
MUtti4KGYjj6sYCIh5QSu4oG27stjItHU+cjeQzvkcFzFQ2KnSKLoc4FukDCXeI2GbSoaFD4ziyPxNxK
0AUyNxOP1DOwcaG/8I+/LRB+At7psBnyDBG0AAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton3.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
</root>

View File

@@ -0,0 +1,97 @@
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Toolbars
Imports PersonalUtilities.Forms.Controls
Imports PersonalUtilities.Forms.Controls.Base
Imports PersonalUtilities.Functions.Messaging
Friend Class LabelsForm : Implements IOkCancelToolbar
Private ReadOnly MyDefs As DefaultFormProps
Friend ReadOnly Property LabelsList As List(Of String)
Private _AnyLabelAdd As Boolean = False
Friend Property MultiUser As Boolean = False
Public Property MultiUserClearExists As Boolean = False
Friend Sub New(ByVal LabelsArr As IEnumerable(Of String))
InitializeComponent()
LabelsList = New List(Of String)
LabelsList.ListAddList(LabelsArr)
MyDefs = New DefaultFormProps
End Sub
Private Sub LabelsForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
With MyDefs
.MyViewInitialize(Me, Settings.Design)
.MyOkCancel = New OkCancelToolbar(Me, Me, CONTAINER_MAIN.BottomToolStripPanel)
.MyOkCancel.AddThisToolbar()
.DelegateClosingChecker()
If Settings.Labels.Count > 0 Then
Dim items As New List(Of Integer)
CMB_LABELS.BeginUpdate()
For i% = 0 To Settings.Labels.Count - 1
If LabelsList.Contains(Settings.Labels(i)) Then items.Add(i)
CMB_LABELS.Items.Add(New ListItem(Settings.Labels(i)))
Next
CMB_LABELS.EndUpdate()
CMB_LABELS.ListCheckedIndexes = items
End If
.AppendDetectors()
.EndLoaderOperations()
End With
Catch ex As Exception
MyDefs.InvokeLoaderError(ex)
End Try
End Sub
Private Sub LabelsForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If e.KeyCode = Keys.Insert Then AddNewLabel() : e.Handled = True
End Sub
Private Sub LabelsForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
LabelsList.Clear()
End Sub
Private Sub ToolbarBttOK() Implements IOkCancelToolbar.ToolbarBttOK
Try
If MultiUser Then
Dim m As New MMessage("You are changing labels for more one user" & vbNewLine & "What do you want to do?",
"MultiUser labels changing",
{New MsgBoxButton("Replace exists") With {.ToolTip = "For each user: all exists labels will be deleted and replaced to these labels"},
New MsgBoxButton("Add to exists") With {.ToolTip = "For each user: these labels will be appended to exists labels"},
New MsgBoxButton("Cancel")},
MsgBoxStyle.Exclamation)
Select Case MsgBoxE(m).Index
Case 0 : MultiUserClearExists = True
Case 1 : MultiUserClearExists = False
Case 2 : Exit Sub
End Select
End If
LabelsList.Clear()
Dim s As List(Of Integer) = CMB_LABELS.ListCheckedIndexes.ListIfNothing
If s.Count > 0 Then
For Each i% In s : LabelsList.Add(Settings.Labels(i)) : Next
End If
If _AnyLabelAdd Then Settings.Labels.Update()
MyDefs.CloseForm()
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Choosing labels")
End Try
End Sub
Private Sub ToolbarBttCancel() Implements IOkCancelToolbar.ToolbarBttCancel
MyDefs.CloseForm(DialogResult.Cancel)
End Sub
Private Sub CMB_LABELS_ActionOnButtonClick(ByVal Sender As ActionButton) Handles CMB_LABELS.ActionOnButtonClick
If Sender.DefaultButton = ActionButton.DefaultButtons.Add Then AddNewLabel()
End Sub
Private Sub CMB_LABELS_ActionOnButtonClearClick() Handles CMB_LABELS.ActionOnButtonClearClick
CMB_LABELS.Clear(ComboBoxExtended.ClearMode.CheckedInexes)
End Sub
Private Sub AddNewLabel()
Dim nl$ = InputBoxE("Enter new label name:", "New label")
If Not nl.IsEmptyString Then
If Settings.Labels.Contains(nl) Then
MsgBoxE($"Label [{nl}] already exists")
Else
Settings.Labels.Add(nl)
_AnyLabelAdd = True
CMB_LABELS.Items.Add(New ListItem(nl))
End If
End If
End Sub
End Class

View File

@@ -0,0 +1,134 @@
Namespace Editors
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Friend Class RedditEditorForm : Inherits System.Windows.Forms.Form
<System.Diagnostics.DebuggerNonUserCode()>
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
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(RedditEditorForm))
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton3 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton4 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Me.TXT_PATH = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_COOKIES = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
TP_MAIN.SuspendLayout()
CType(Me.TXT_PATH, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_COOKIES, System.ComponentModel.ISupportInitialize).BeginInit()
Me.CONTAINER_MAIN.ContentPanel.SuspendLayout()
Me.CONTAINER_MAIN.SuspendLayout()
Me.SuspendLayout()
'
'TP_MAIN
'
TP_MAIN.ColumnCount = 1
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
TP_MAIN.Controls.Add(Me.TXT_PATH, 0, 0)
TP_MAIN.Controls.Add(Me.TXT_COOKIES, 0, 1)
TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
TP_MAIN.Location = New System.Drawing.Point(0, 0)
TP_MAIN.Name = "TP_MAIN"
TP_MAIN.RowCount = 2
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_MAIN.Size = New System.Drawing.Size(524, 80)
TP_MAIN.TabIndex = 0
'
'TXT_PATH
'
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
ActionButton1.Index = 0
ActionButton1.Name = "BTT_OPEN"
ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image)
ActionButton2.Index = 1
ActionButton2.Name = "BTT_CLEAR"
Me.TXT_PATH.Buttons.Add(ActionButton1)
Me.TXT_PATH.Buttons.Add(ActionButton2)
Me.TXT_PATH.CaptionText = "Path"
Me.TXT_PATH.CaptionToolTipEnabled = True
Me.TXT_PATH.CaptionToolTipText = "Specific path to store Reddit files"
Me.TXT_PATH.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_PATH.Location = New System.Drawing.Point(3, 3)
Me.TXT_PATH.Name = "TXT_PATH"
Me.TXT_PATH.Size = New System.Drawing.Size(518, 22)
Me.TXT_PATH.TabIndex = 0
'
'TXT_COOKIES
'
ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image)
ActionButton3.Index = 0
ActionButton3.Name = "BTT_EDIT"
ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image)
ActionButton4.Index = 1
ActionButton4.Name = "BTT_CLEAR"
Me.TXT_COOKIES.Buttons.Add(ActionButton3)
Me.TXT_COOKIES.Buttons.Add(ActionButton4)
Me.TXT_COOKIES.CaptionText = "Cookies"
Me.TXT_COOKIES.ClearTextByButtonClear = False
Me.TXT_COOKIES.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_COOKIES.Location = New System.Drawing.Point(3, 43)
Me.TXT_COOKIES.Name = "TXT_COOKIES"
Me.TXT_COOKIES.Size = New System.Drawing.Size(518, 22)
Me.TXT_COOKIES.TabIndex = 1
Me.TXT_COOKIES.TextBoxReadOnly = True
'
'CONTAINER_MAIN
'
'
'CONTAINER_MAIN.ContentPanel
'
Me.CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
Me.CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(524, 80)
Me.CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
Me.CONTAINER_MAIN.LeftToolStripPanelVisible = False
Me.CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
Me.CONTAINER_MAIN.Name = "CONTAINER_MAIN"
Me.CONTAINER_MAIN.RightToolStripPanelVisible = False
Me.CONTAINER_MAIN.Size = New System.Drawing.Size(524, 80)
Me.CONTAINER_MAIN.TabIndex = 0
Me.CONTAINER_MAIN.TopToolStripPanelVisible = False
'
'RedditEditorForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(524, 80)
Me.Controls.Add(Me.CONTAINER_MAIN)
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon)
Me.KeyPreview = True
Me.MaximizeBox = False
Me.MaximumSize = New System.Drawing.Size(540, 119)
Me.MinimizeBox = False
Me.MinimumSize = New System.Drawing.Size(540, 119)
Me.Name = "RedditEditorForm"
Me.ShowInTaskbar = False
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
Me.Text = "Reddit"
TP_MAIN.ResumeLayout(False)
CType(Me.TXT_PATH, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_COOKIES, System.ComponentModel.ISupportInitialize).EndInit()
Me.CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
Me.CONTAINER_MAIN.ResumeLayout(False)
Me.CONTAINER_MAIN.PerformLayout()
Me.ResumeLayout(False)
End Sub
Private WithEvents CONTAINER_MAIN As ToolStripContainer
Private WithEvents TXT_PATH As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents TXT_COOKIES As PersonalUtilities.Forms.Controls.TextBoxExtended
End Class
End Namespace

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,68 @@
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Controls
Imports PersonalUtilities.Forms.Controls.Base
Imports PersonalUtilities.Forms.Toolbars
Imports PersonalUtilities.Tools.WEB
Namespace Editors
Friend Class RedditEditorForm : Implements IOkCancelToolbar
Private ReadOnly MyDefs As DefaultFormProps
Friend Sub New()
InitializeComponent()
MyDefs = New DefaultFormProps
End Sub
Private Sub RedditEditorForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
With MyDefs
.MyViewInitialize(Me, Settings.Design, True)
.AddOkCancelToolbar()
.DelegateClosingChecker()
With Settings.Site(Sites.Reddit)
TXT_PATH.Text = .Path
If .Responser.Cookies Is Nothing Then .Responser.Cookies = New CookieKeeper(.Responser.CookiesDomain)
End With
SetCookieText()
TextBoxExtended.SetFalseDetector(Me, True, AddressOf .Detector)
.EndLoaderOperations()
End With
Catch ex As Exception
MyDefs.InvokeLoaderError(ex)
End Try
End Sub
Private Sub ToolbarBttOK() Implements IOkCancelToolbar.ToolbarBttOK
With Settings.Site(Sites.Reddit)
If TXT_PATH.IsEmptyString Then .Path = Nothing Else .Path = TXT_PATH.Text
.Update()
End With
MyDefs.CloseForm()
End Sub
Private Sub ToolbarBttCancel() Implements IOkCancelToolbar.ToolbarBttCancel
MyDefs.CloseForm(DialogResult.Cancel)
End Sub
Private Sub TXT_PATH_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_PATH.ActionOnButtonClick
If Sender.DefaultButton = ActionButton.DefaultButtons.Open Then
Dim f As SFile = SFile.SelectPath(Settings.Site(Sites.Reddit).Path)
If Not f.IsEmptyString Then TXT_PATH.Text = f
End If
End Sub
Private Sub TXT_COOKIES_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_COOKIES.ActionOnButtonClick
If Sender.DefaultButton = ActionButton.DefaultButtons.Edit Then
Using f As New CookieListForm(Settings.Site(Sites.Reddit).Responser.Cookies) : f.ShowDialog() : End Using
SetCookieText()
End If
End Sub
Private Sub TXT_COOKIES_ActionOnButtonClearClick() Handles TXT_COOKIES.ActionOnButtonClearClick
With Settings.Site(Sites.Reddit).Responser
If Not .Cookies Is Nothing Then .Cookies.Dispose()
.Cookies = New CookieKeeper(.CookiesDomain)
End With
SetCookieText()
End Sub
Private Sub SetCookieText()
Dim c% = 0
With Settings.Site(Sites.Reddit).Responser
If Not .Cookies Is Nothing Then c = .Cookies.Count
End With
TXT_COOKIES.Text = $"{c} cookies"
End Sub
End Class
End Namespace

View File

@@ -0,0 +1,180 @@
Namespace Editors
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Friend Class TwitterEditorForm : Inherits System.Windows.Forms.Form
<System.Diagnostics.DebuggerNonUserCode()>
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
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(TwitterEditorForm))
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton3 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton4 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton5 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton6 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Me.TXT_PATH = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_COOKIES = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_TOKEN = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_AUTH = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
TP_MAIN.SuspendLayout()
CType(Me.TXT_PATH, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_COOKIES, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_TOKEN, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_AUTH, System.ComponentModel.ISupportInitialize).BeginInit()
Me.CONTAINER_MAIN.ContentPanel.SuspendLayout()
Me.CONTAINER_MAIN.SuspendLayout()
Me.SuspendLayout()
'
'TP_MAIN
'
TP_MAIN.ColumnCount = 1
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
TP_MAIN.Controls.Add(Me.TXT_PATH, 0, 0)
TP_MAIN.Controls.Add(Me.TXT_COOKIES, 0, 1)
TP_MAIN.Controls.Add(Me.TXT_TOKEN, 0, 2)
TP_MAIN.Controls.Add(Me.TXT_AUTH, 0, 3)
TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
TP_MAIN.Location = New System.Drawing.Point(0, 0)
TP_MAIN.Name = "TP_MAIN"
TP_MAIN.RowCount = 4
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25.0!))
TP_MAIN.Size = New System.Drawing.Size(544, 107)
TP_MAIN.TabIndex = 0
'
'TXT_PATH
'
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
ActionButton1.Index = 0
ActionButton1.Name = "BTT_OPEN"
ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image)
ActionButton2.Index = 1
ActionButton2.Name = "BTT_CLEAR"
Me.TXT_PATH.Buttons.Add(ActionButton1)
Me.TXT_PATH.Buttons.Add(ActionButton2)
Me.TXT_PATH.CaptionText = "Path"
Me.TXT_PATH.CaptionToolTipEnabled = True
Me.TXT_PATH.CaptionToolTipText = "Specific path to store Twitter files"
Me.TXT_PATH.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_PATH.Location = New System.Drawing.Point(3, 3)
Me.TXT_PATH.Name = "TXT_PATH"
Me.TXT_PATH.Size = New System.Drawing.Size(538, 22)
Me.TXT_PATH.TabIndex = 0
'
'TXT_COOKIES
'
ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image)
ActionButton3.Index = 0
ActionButton3.Name = "BTT_EDIT"
ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image)
ActionButton4.Index = 1
ActionButton4.Name = "BTT_CLEAR"
Me.TXT_COOKIES.Buttons.Add(ActionButton3)
Me.TXT_COOKIES.Buttons.Add(ActionButton4)
Me.TXT_COOKIES.CaptionText = "Cookies"
Me.TXT_COOKIES.ClearTextByButtonClear = False
Me.TXT_COOKIES.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_COOKIES.Location = New System.Drawing.Point(3, 29)
Me.TXT_COOKIES.Name = "TXT_COOKIES"
Me.TXT_COOKIES.Size = New System.Drawing.Size(538, 22)
Me.TXT_COOKIES.TabIndex = 1
Me.TXT_COOKIES.TextBoxReadOnly = True
'
'TXT_TOKEN
'
ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image)
ActionButton5.Index = 0
ActionButton5.Name = "BTT_CLEAR"
Me.TXT_TOKEN.Buttons.Add(ActionButton5)
Me.TXT_TOKEN.CaptionText = "Token"
Me.TXT_TOKEN.CaptionToolTipEnabled = True
Me.TXT_TOKEN.CaptionToolTipText = "Set token from [x-csrf-token] response header"
Me.TXT_TOKEN.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_TOKEN.Location = New System.Drawing.Point(3, 55)
Me.TXT_TOKEN.Name = "TXT_TOKEN"
Me.TXT_TOKEN.Size = New System.Drawing.Size(538, 22)
Me.TXT_TOKEN.TabIndex = 2
'
'TXT_AUTH
'
ActionButton6.BackgroundImage = CType(resources.GetObject("ActionButton6.BackgroundImage"), System.Drawing.Image)
ActionButton6.Index = 0
ActionButton6.Name = "BTT_CLEAR"
Me.TXT_AUTH.Buttons.Add(ActionButton6)
Me.TXT_AUTH.CaptionText = "Authorization"
Me.TXT_AUTH.CaptionToolTipEnabled = True
Me.TXT_AUTH.CaptionToolTipText = "Set authorization from [authorization] response header. This field must start fro" &
"m [Bearer] key word"
Me.TXT_AUTH.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_AUTH.Location = New System.Drawing.Point(3, 81)
Me.TXT_AUTH.Name = "TXT_AUTH"
Me.TXT_AUTH.Size = New System.Drawing.Size(538, 22)
Me.TXT_AUTH.TabIndex = 3
'
'CONTAINER_MAIN
'
'
'CONTAINER_MAIN.ContentPanel
'
Me.CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
Me.CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(544, 107)
Me.CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
Me.CONTAINER_MAIN.LeftToolStripPanelVisible = False
Me.CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
Me.CONTAINER_MAIN.Name = "CONTAINER_MAIN"
Me.CONTAINER_MAIN.RightToolStripPanelVisible = False
Me.CONTAINER_MAIN.Size = New System.Drawing.Size(544, 132)
Me.CONTAINER_MAIN.TabIndex = 0
Me.CONTAINER_MAIN.TopToolStripPanelVisible = False
'
'TwitterEditorForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(544, 132)
Me.Controls.Add(Me.CONTAINER_MAIN)
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon)
Me.KeyPreview = True
Me.MaximizeBox = False
Me.MaximumSize = New System.Drawing.Size(560, 171)
Me.MinimizeBox = False
Me.MinimumSize = New System.Drawing.Size(560, 171)
Me.Name = "TwitterEditorForm"
Me.ShowInTaskbar = False
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
Me.Text = "Twitter"
TP_MAIN.ResumeLayout(False)
CType(Me.TXT_PATH, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_COOKIES, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_TOKEN, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_AUTH, System.ComponentModel.ISupportInitialize).EndInit()
Me.CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
Me.CONTAINER_MAIN.ResumeLayout(False)
Me.CONTAINER_MAIN.PerformLayout()
Me.ResumeLayout(False)
End Sub
Private WithEvents CONTAINER_MAIN As ToolStripContainer
Private WithEvents TXT_PATH As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents TXT_COOKIES As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents TXT_TOKEN As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents TXT_AUTH As PersonalUtilities.Forms.Controls.TextBoxExtended
End Class
End Namespace

View File

@@ -0,0 +1,238 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="TP_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="ActionButton1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
cMaRN0UdBBkAAAAASUVORK5CYII=
</value>
</data>
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton3.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
AAAASUVORK5CYII=
</value>
</data>
<data name="ActionButton4.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton5.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton6.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAEAICAAAAEAIADLAQAAFgAAAIlQTkcNChoKAAAADUlIRFIAAAAgAAAAIAgGAAAAc3p69AAAAZJJ
REFUeAFiGDZgFMguBPBazwB6BEAUx2PbttHFqmJ2sW1UsbrY6NLFrmL2sW3jbMz9z1rNqvh9wry3QnQ5
LMRdRCAez7AVDQ1+3w2lc9+UwXwP4W3wFGIiBhPQANNxDScKDhgDwWIX4XXxCWIjDekQ/EKjgkP2QJCO
DcoCRyAKbzAY07Ewd8hRSAHnUMtBeA0kQxQSIXiM6rmD9kKK+I7pKGlRYAzEhQeoX3DQWIiJJ5iFSgYF
5kCUHqFy0UHl8QViIQ6nsAjdUBujIUrXzVbncKRCFFIgSheMwtdiClaqh+odNiqwDxKSFWarX0LS16hA
SdyHBCwa5c12wk74DwnQMbszW1c8gwRksF2B2uiIdfgL8dETlLQr0CLAw3CM06vblgDCL2kur6VxAuKT
CDTT3mSUxDx8hHiQipGqcIMi3XEPopSO6V7DR+ApRCkJU9yElkEvrPVwPniLXprQgbiNLx4PwXjsQGW3
9/TTcQfpEIVf2KLa023KtMJSHMMj/IEgFf/xEhexGQNQJmMMQxmMAgBkarVAZoTAyQAAAABJRU5ErkJg
gg==
</value>
</data>
</root>

View File

@@ -0,0 +1,84 @@
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Controls
Imports PersonalUtilities.Forms.Controls.Base
Imports PersonalUtilities.Forms.Toolbars
Imports PersonalUtilities.Tools.WEB
Namespace Editors
Friend Class TwitterEditorForm : Implements IOkCancelToolbar
Private ReadOnly MyDefs As DefaultFormProps(Of FieldsChecker)
Friend Sub New()
InitializeComponent()
MyDefs = New DefaultFormProps(Of FieldsChecker)
End Sub
Private Sub TwitterEditorForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
With MyDefs
.MyViewInitialize(Me, Settings.Design, True)
.AddOkCancelToolbar()
.DelegateClosingChecker()
With Settings.Site(Sites.Twitter)
TXT_PATH.Text = .Path
With .Responser
If .Cookies Is Nothing Then .Cookies = New CookieKeeper(.CookiesDomain)
SetCookieText()
TXT_TOKEN.Text = .Headers(API.Base.SiteSettings.Header_Twitter_Token)
TXT_AUTH.Text = .Headers(API.Base.SiteSettings.Header_Twitter_Authorization)
End With
End With
.MyFieldsChecker = New FieldsChecker
With .MyFieldsChecker
.AddControl(Of String)(TXT_TOKEN, TXT_TOKEN.CaptionText)
.AddControl(Of String)(TXT_AUTH, TXT_AUTH.CaptionText)
.EndLoaderOperations()
End With
TextBoxExtended.SetFalseDetector(Me, True, AddressOf .Detector)
.EndLoaderOperations()
End With
Catch ex As Exception
MyDefs.InvokeLoaderError(ex)
End Try
End Sub
Private Sub ToolbarBttOK() Implements IOkCancelToolbar.ToolbarBttOK
If MyDefs.MyFieldsChecker.AllParamsOK Then
With Settings.Site(Sites.Twitter)
If TXT_PATH.IsEmptyString Then .Path = Nothing Else .Path = TXT_PATH.Text
With .Responser
.Headers(API.Base.SiteSettings.Header_Twitter_Token) = TXT_TOKEN.Text
.Headers(API.Base.SiteSettings.Header_Twitter_Authorization) = TXT_AUTH.Text
End With
.Update()
End With
MyDefs.CloseForm()
End If
End Sub
Private Sub ToolbarBttCancel() Implements IOkCancelToolbar.ToolbarBttCancel
MyDefs.CloseForm(DialogResult.Cancel)
End Sub
Private Sub TXT_PATH_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_PATH.ActionOnButtonClick
If Sender.DefaultButton = ActionButton.DefaultButtons.Open Then
Dim f As SFile = SFile.SelectPath(Settings.Site(Sites.Twitter).Path)
If Not f.IsEmptyString Then TXT_PATH.Text = f
End If
End Sub
Private Sub TXT_COOKIES_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_COOKIES.ActionOnButtonClick
If Sender.DefaultButton = ActionButton.DefaultButtons.Edit Then
Using f As New CookieListForm(Settings.Site(Sites.Twitter).Responser.Cookies) : f.ShowDialog() : End Using
SetCookieText()
End If
End Sub
Private Sub TXT_COOKIES_ActionOnButtonClearClick() Handles TXT_COOKIES.ActionOnButtonClearClick
With Settings.Site(Sites.Twitter).Responser
If Not .Cookies Is Nothing Then .Cookies.Dispose()
.Cookies = New CookieKeeper(.CookiesDomain)
End With
SetCookieText()
End Sub
Private Sub SetCookieText()
Dim c% = 0
With Settings.Site(Sites.Twitter).Responser
If Not .Cookies Is Nothing Then c = .Cookies.Count
End With
TXT_COOKIES.Text = $"{c} cookies"
End Sub
End Class
End Namespace

View File

@@ -0,0 +1,378 @@
Namespace Editors
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Friend Class UserCreatorForm : Inherits System.Windows.Forms.Form
<System.Diagnostics.DebuggerNonUserCode()>
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
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container()
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
Dim TP_SITE As System.Windows.Forms.TableLayoutPanel
Dim TP_PARAMS As System.Windows.Forms.TableLayoutPanel
Dim TP_OTHER As System.Windows.Forms.TableLayoutPanel
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(UserCreatorForm))
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton3 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TT_MAIN As System.Windows.Forms.ToolTip
Me.TXT_USER = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.OPT_REDDIT = New System.Windows.Forms.RadioButton()
Me.OPT_TWITTER = New System.Windows.Forms.RadioButton()
Me.CH_TEMP = New System.Windows.Forms.CheckBox()
Me.CH_FAV = New System.Windows.Forms.CheckBox()
Me.CH_PARSE_USER_MEDIA = New System.Windows.Forms.CheckBox()
Me.CH_READY_FOR_DOWN = New System.Windows.Forms.CheckBox()
Me.TXT_DESCR = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_USER_FRIENDLY = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TP_ADD_BY_LIST = New System.Windows.Forms.TableLayoutPanel()
Me.CH_ADD_BY_LIST = New System.Windows.Forms.CheckBox()
Me.CH_AUTO_DETECT_SITE = New System.Windows.Forms.CheckBox()
Me.TXT_LABELS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
TP_SITE = New System.Windows.Forms.TableLayoutPanel()
TP_PARAMS = New System.Windows.Forms.TableLayoutPanel()
TP_OTHER = New System.Windows.Forms.TableLayoutPanel()
TT_MAIN = New System.Windows.Forms.ToolTip(Me.components)
TP_MAIN.SuspendLayout()
CType(Me.TXT_USER, System.ComponentModel.ISupportInitialize).BeginInit()
TP_SITE.SuspendLayout()
TP_PARAMS.SuspendLayout()
TP_OTHER.SuspendLayout()
CType(Me.TXT_DESCR, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_USER_FRIENDLY, System.ComponentModel.ISupportInitialize).BeginInit()
Me.TP_ADD_BY_LIST.SuspendLayout()
CType(Me.TXT_LABELS, System.ComponentModel.ISupportInitialize).BeginInit()
Me.CONTAINER_MAIN.ContentPanel.SuspendLayout()
Me.CONTAINER_MAIN.SuspendLayout()
Me.SuspendLayout()
'
'TP_MAIN
'
TP_MAIN.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
TP_MAIN.ColumnCount = 1
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MAIN.Controls.Add(Me.TXT_USER, 0, 0)
TP_MAIN.Controls.Add(TP_SITE, 0, 2)
TP_MAIN.Controls.Add(TP_PARAMS, 0, 3)
TP_MAIN.Controls.Add(TP_OTHER, 0, 4)
TP_MAIN.Controls.Add(Me.TXT_DESCR, 0, 7)
TP_MAIN.Controls.Add(Me.TXT_USER_FRIENDLY, 0, 1)
TP_MAIN.Controls.Add(Me.TP_ADD_BY_LIST, 0, 5)
TP_MAIN.Controls.Add(Me.TXT_LABELS, 0, 6)
TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
TP_MAIN.Location = New System.Drawing.Point(0, 0)
TP_MAIN.Name = "TP_MAIN"
TP_MAIN.RowCount = 8
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20.0005!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20.0005!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20.0005!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 19.99851!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 20.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 150.0!))
TP_MAIN.Size = New System.Drawing.Size(454, 366)
TP_MAIN.TabIndex = 0
'
'TXT_USER
'
Me.TXT_USER.CaptionText = "User name"
Me.TXT_USER.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_USER.Location = New System.Drawing.Point(4, 4)
Me.TXT_USER.Name = "TXT_USER"
Me.TXT_USER.PlaceholderEnabled = True
Me.TXT_USER.PlaceholderText = "Enter user name or url here..."
Me.TXT_USER.Size = New System.Drawing.Size(446, 22)
Me.TXT_USER.TabIndex = 0
'
'TP_SITE
'
TP_SITE.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
TP_SITE.ColumnCount = 2
TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_SITE.Controls.Add(Me.OPT_REDDIT, 0, 0)
TP_SITE.Controls.Add(Me.OPT_TWITTER, 1, 0)
TP_SITE.Dock = System.Windows.Forms.DockStyle.Fill
TP_SITE.Location = New System.Drawing.Point(1, 59)
TP_SITE.Margin = New System.Windows.Forms.Padding(0)
TP_SITE.Name = "TP_SITE"
TP_SITE.RowCount = 1
TP_SITE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_SITE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 29.0!))
TP_SITE.Size = New System.Drawing.Size(452, 30)
TP_SITE.TabIndex = 2
'
'OPT_REDDIT
'
Me.OPT_REDDIT.AutoSize = True
Me.OPT_REDDIT.Dock = System.Windows.Forms.DockStyle.Fill
Me.OPT_REDDIT.Location = New System.Drawing.Point(4, 4)
Me.OPT_REDDIT.Name = "OPT_REDDIT"
Me.OPT_REDDIT.Size = New System.Drawing.Size(218, 22)
Me.OPT_REDDIT.TabIndex = 0
Me.OPT_REDDIT.TabStop = True
Me.OPT_REDDIT.Text = "Reddit"
Me.OPT_REDDIT.UseVisualStyleBackColor = True
'
'OPT_TWITTER
'
Me.OPT_TWITTER.AutoSize = True
Me.OPT_TWITTER.Dock = System.Windows.Forms.DockStyle.Fill
Me.OPT_TWITTER.Location = New System.Drawing.Point(229, 4)
Me.OPT_TWITTER.Name = "OPT_TWITTER"
Me.OPT_TWITTER.Size = New System.Drawing.Size(219, 22)
Me.OPT_TWITTER.TabIndex = 1
Me.OPT_TWITTER.TabStop = True
Me.OPT_TWITTER.Text = "Twitter"
Me.OPT_TWITTER.UseVisualStyleBackColor = True
'
'TP_PARAMS
'
TP_PARAMS.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
TP_PARAMS.ColumnCount = 2
TP_PARAMS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_PARAMS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_PARAMS.Controls.Add(Me.CH_TEMP, 0, 0)
TP_PARAMS.Controls.Add(Me.CH_FAV, 1, 0)
TP_PARAMS.Dock = System.Windows.Forms.DockStyle.Fill
TP_PARAMS.Location = New System.Drawing.Point(1, 90)
TP_PARAMS.Margin = New System.Windows.Forms.Padding(0)
TP_PARAMS.Name = "TP_PARAMS"
TP_PARAMS.RowCount = 1
TP_PARAMS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_PARAMS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 29.0!))
TP_PARAMS.Size = New System.Drawing.Size(452, 30)
TP_PARAMS.TabIndex = 3
'
'CH_TEMP
'
Me.CH_TEMP.AutoSize = True
Me.CH_TEMP.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_TEMP.Location = New System.Drawing.Point(4, 4)
Me.CH_TEMP.Name = "CH_TEMP"
Me.CH_TEMP.Size = New System.Drawing.Size(218, 22)
Me.CH_TEMP.TabIndex = 0
Me.CH_TEMP.Text = "Temporary"
Me.CH_TEMP.UseVisualStyleBackColor = True
'
'CH_FAV
'
Me.CH_FAV.AutoSize = True
Me.CH_FAV.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_FAV.Location = New System.Drawing.Point(229, 4)
Me.CH_FAV.Name = "CH_FAV"
Me.CH_FAV.Size = New System.Drawing.Size(219, 22)
Me.CH_FAV.TabIndex = 1
Me.CH_FAV.Text = "Favorite"
Me.CH_FAV.UseVisualStyleBackColor = True
'
'TP_OTHER
'
TP_OTHER.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
TP_OTHER.ColumnCount = 2
TP_OTHER.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_OTHER.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_OTHER.Controls.Add(Me.CH_PARSE_USER_MEDIA, 1, 0)
TP_OTHER.Controls.Add(Me.CH_READY_FOR_DOWN, 0, 0)
TP_OTHER.Dock = System.Windows.Forms.DockStyle.Fill
TP_OTHER.Location = New System.Drawing.Point(1, 121)
TP_OTHER.Margin = New System.Windows.Forms.Padding(0)
TP_OTHER.Name = "TP_OTHER"
TP_OTHER.RowCount = 1
TP_OTHER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_OTHER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 29.0!))
TP_OTHER.Size = New System.Drawing.Size(452, 30)
TP_OTHER.TabIndex = 4
'
'CH_PARSE_USER_MEDIA
'
Me.CH_PARSE_USER_MEDIA.AutoSize = True
Me.CH_PARSE_USER_MEDIA.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_PARSE_USER_MEDIA.Location = New System.Drawing.Point(229, 4)
Me.CH_PARSE_USER_MEDIA.Name = "CH_PARSE_USER_MEDIA"
Me.CH_PARSE_USER_MEDIA.Size = New System.Drawing.Size(219, 22)
Me.CH_PARSE_USER_MEDIA.TabIndex = 0
Me.CH_PARSE_USER_MEDIA.Text = "Get user media only"
TT_MAIN.SetToolTip(Me.CH_PARSE_USER_MEDIA, "For twitter only!" & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "If checked then user media only will be downloaded." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Otherwise" &
" all media (include comments and retwits) will be downloaded.")
Me.CH_PARSE_USER_MEDIA.UseVisualStyleBackColor = True
'
'CH_READY_FOR_DOWN
'
Me.CH_READY_FOR_DOWN.AutoSize = True
Me.CH_READY_FOR_DOWN.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_READY_FOR_DOWN.Location = New System.Drawing.Point(4, 4)
Me.CH_READY_FOR_DOWN.Name = "CH_READY_FOR_DOWN"
Me.CH_READY_FOR_DOWN.Size = New System.Drawing.Size(218, 22)
Me.CH_READY_FOR_DOWN.TabIndex = 1
Me.CH_READY_FOR_DOWN.Text = "Ready for download"
TT_MAIN.SetToolTip(Me.CH_READY_FOR_DOWN, "If checked then this user can be downloaded by [Download All]")
Me.CH_READY_FOR_DOWN.UseVisualStyleBackColor = True
'
'TXT_DESCR
'
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
ActionButton1.Dock = System.Windows.Forms.DockStyle.Top
ActionButton1.Index = 0
ActionButton1.Name = "BTT_CLEAR"
Me.TXT_DESCR.Buttons.Add(ActionButton1)
Me.TXT_DESCR.CaptionDock = System.Windows.Forms.DockStyle.Top
Me.TXT_DESCR.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.None
Me.TXT_DESCR.CaptionVisible = False
Me.TXT_DESCR.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_DESCR.GroupBoxed = True
Me.TXT_DESCR.GroupBoxText = "Description"
Me.TXT_DESCR.Location = New System.Drawing.Point(4, 217)
Me.TXT_DESCR.Multiline = True
Me.TXT_DESCR.Name = "TXT_DESCR"
Me.TXT_DESCR.Size = New System.Drawing.Size(446, 145)
Me.TXT_DESCR.TabIndex = 5
'
'TXT_USER_FRIENDLY
'
Me.TXT_USER_FRIENDLY.CaptionText = "Friendly name"
Me.TXT_USER_FRIENDLY.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_USER_FRIENDLY.Location = New System.Drawing.Point(4, 33)
Me.TXT_USER_FRIENDLY.Name = "TXT_USER_FRIENDLY"
Me.TXT_USER_FRIENDLY.Size = New System.Drawing.Size(446, 22)
Me.TXT_USER_FRIENDLY.TabIndex = 1
'
'TP_ADD_BY_LIST
'
Me.TP_ADD_BY_LIST.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
Me.TP_ADD_BY_LIST.ColumnCount = 2
Me.TP_ADD_BY_LIST.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
Me.TP_ADD_BY_LIST.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
Me.TP_ADD_BY_LIST.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
Me.TP_ADD_BY_LIST.Controls.Add(Me.CH_ADD_BY_LIST, 0, 0)
Me.TP_ADD_BY_LIST.Controls.Add(Me.CH_AUTO_DETECT_SITE, 1, 0)
Me.TP_ADD_BY_LIST.Dock = System.Windows.Forms.DockStyle.Fill
Me.TP_ADD_BY_LIST.Location = New System.Drawing.Point(1, 152)
Me.TP_ADD_BY_LIST.Margin = New System.Windows.Forms.Padding(0)
Me.TP_ADD_BY_LIST.Name = "TP_ADD_BY_LIST"
Me.TP_ADD_BY_LIST.RowCount = 1
Me.TP_ADD_BY_LIST.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_ADD_BY_LIST.Size = New System.Drawing.Size(452, 30)
Me.TP_ADD_BY_LIST.TabIndex = 6
'
'CH_ADD_BY_LIST
'
Me.CH_ADD_BY_LIST.AutoSize = True
Me.CH_ADD_BY_LIST.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_ADD_BY_LIST.Location = New System.Drawing.Point(4, 4)
Me.CH_ADD_BY_LIST.Name = "CH_ADD_BY_LIST"
Me.CH_ADD_BY_LIST.Size = New System.Drawing.Size(218, 22)
Me.CH_ADD_BY_LIST.TabIndex = 0
Me.CH_ADD_BY_LIST.Text = "Add by list"
Me.CH_ADD_BY_LIST.UseVisualStyleBackColor = True
'
'CH_AUTO_DETECT_SITE
'
Me.CH_AUTO_DETECT_SITE.AutoSize = True
Me.CH_AUTO_DETECT_SITE.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_AUTO_DETECT_SITE.Location = New System.Drawing.Point(229, 4)
Me.CH_AUTO_DETECT_SITE.Name = "CH_AUTO_DETECT_SITE"
Me.CH_AUTO_DETECT_SITE.Size = New System.Drawing.Size(219, 22)
Me.CH_AUTO_DETECT_SITE.TabIndex = 1
Me.CH_AUTO_DETECT_SITE.Text = "Auto detect site"
Me.CH_AUTO_DETECT_SITE.UseVisualStyleBackColor = True
'
'TXT_LABELS
'
ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image)
ActionButton2.Index = 0
ActionButton2.Name = "BTT_OPEN"
ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image)
ActionButton3.Index = 1
ActionButton3.Name = "BTT_CLEAR"
Me.TXT_LABELS.Buttons.Add(ActionButton2)
Me.TXT_LABELS.Buttons.Add(ActionButton3)
Me.TXT_LABELS.CaptionText = "Labels"
Me.TXT_LABELS.CaptionWidth = 50.0R
Me.TXT_LABELS.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_LABELS.Location = New System.Drawing.Point(4, 186)
Me.TXT_LABELS.Name = "TXT_LABELS"
Me.TXT_LABELS.Size = New System.Drawing.Size(446, 22)
Me.TXT_LABELS.TabIndex = 7
Me.TXT_LABELS.TextBoxReadOnly = True
'
'CONTAINER_MAIN
'
'
'CONTAINER_MAIN.ContentPanel
'
Me.CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
Me.CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(454, 366)
Me.CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
Me.CONTAINER_MAIN.LeftToolStripPanelVisible = False
Me.CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
Me.CONTAINER_MAIN.Name = "CONTAINER_MAIN"
Me.CONTAINER_MAIN.RightToolStripPanelVisible = False
Me.CONTAINER_MAIN.Size = New System.Drawing.Size(454, 366)
Me.CONTAINER_MAIN.TabIndex = 0
Me.CONTAINER_MAIN.TopToolStripPanelVisible = False
'
'UserCreatorForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(454, 366)
Me.Controls.Add(Me.CONTAINER_MAIN)
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon)
Me.KeyPreview = True
Me.MaximizeBox = False
Me.MaximumSize = New System.Drawing.Size(470, 405)
Me.MinimizeBox = False
Me.MinimumSize = New System.Drawing.Size(470, 405)
Me.Name = "UserCreatorForm"
Me.ShowInTaskbar = False
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
Me.Text = "Create User"
TP_MAIN.ResumeLayout(False)
CType(Me.TXT_USER, System.ComponentModel.ISupportInitialize).EndInit()
TP_SITE.ResumeLayout(False)
TP_SITE.PerformLayout()
TP_PARAMS.ResumeLayout(False)
TP_PARAMS.PerformLayout()
TP_OTHER.ResumeLayout(False)
TP_OTHER.PerformLayout()
CType(Me.TXT_DESCR, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_USER_FRIENDLY, System.ComponentModel.ISupportInitialize).EndInit()
Me.TP_ADD_BY_LIST.ResumeLayout(False)
Me.TP_ADD_BY_LIST.PerformLayout()
CType(Me.TXT_LABELS, System.ComponentModel.ISupportInitialize).EndInit()
Me.CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
Me.CONTAINER_MAIN.ResumeLayout(False)
Me.CONTAINER_MAIN.PerformLayout()
Me.ResumeLayout(False)
End Sub
Private WithEvents CONTAINER_MAIN As ToolStripContainer
Private WithEvents TXT_USER As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents OPT_REDDIT As RadioButton
Private WithEvents OPT_TWITTER As RadioButton
Private WithEvents CH_TEMP As CheckBox
Private WithEvents CH_FAV As CheckBox
Private WithEvents CH_PARSE_USER_MEDIA As CheckBox
Private WithEvents TXT_USER_FRIENDLY As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents CH_READY_FOR_DOWN As CheckBox
Private WithEvents TXT_DESCR As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents TP_ADD_BY_LIST As TableLayoutPanel
Private WithEvents CH_ADD_BY_LIST As CheckBox
Private WithEvents CH_AUTO_DETECT_SITE As CheckBox
Private WithEvents TXT_LABELS As PersonalUtilities.Forms.Controls.TextBoxExtended
End Class
End Namespace

View File

@@ -0,0 +1,591 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="TP_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="TP_SITE.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="TP_PARAMS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="TP_OTHER.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="TT_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="TT_MAIN.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="ActionButton1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
cMaRN0UdBBkAAAAASUVORK5CYII=
</value>
</data>
<data name="ActionButton3.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAkAMDAQAAAAAABoBgAAlgAAACAgEAAAAAAA6AIAAP4GAAAQEBAAAAAAACgBAADmCQAAMDAAAAEA
CACoDgAADgsAACAgAAABAAgAqAgAALYZAAAQEAAAAQAIAGgFAABeIgAAMDAAAAEAIACoJQAAxicAACAg
AAABACAAqBAAAG5NAAAQEAAAAQAgAGgEAAAWXgAAKAAAADAAAABgAAAAAQAEAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAIAAAAAAAACAgACAAAAAgACAAICAAADAwMAAgICAAAAA/wAA/wAAAP//AP8A
AAD/AP8A//8AAP///wAiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi
IiIiIiIiIiIiIiIiIiAAAyIiIiIiIiIiIiIiIiIiIiIiIiIiIgAAADIiIiIiIiIiIiIiIiIiIiIiIiIi
IAC7sAMiIiIiIiIiIiIiIiIiIiIiIiIiIAsHuwAyIiIiIiIiIiIiIiIiIiIiIiIiILuAe7ADIiIiIiIi
IiIiIiIiLMAAAAAAALO4B7sAMiIiIiIiIiIiIiLAAADMZmZmwLs7gHuwAyIiIiIiIiIiLAAAxmZmzMzM
wACzuAe7ADIiIiIiIiIsAAZmzMzMzMzMAAC7u4B7sAMzMzMzIiLABszMzMzMzMzAAAAAC7gHuwAAAAAA
MiIAbMzMzMAAAAwAAAAACzuAe7gzMzMwAyIGzMzMAAODcwAAABEAC7u4C7u7u7uzADIAzMwAODc3NzAB
GRkQAAC7uwuwi7u7MAMgDMCDc3Nzc4ARERERAAALsLsIu3i7swMiAMA3Nzc3NwABODg4AiILC7CLtxe7
swMiIABzc3NzgwODg4OAIiILuwi7cHu7swMiIgA3Nzc3OAg4ODgCIiILsIu3F7u7swMiIiADc3OAAAAA
g4AiIiILCLtwe3d3swMiIiAINzg4Nzc3CDAiIiI7i7cXswADswMiIiADg3Nzc3N3A4AiIiI7u3B7MIIg
swMiIgAACDc3Nzc3AAAAACI7txe7MIIDswMiIAAAAHNzc3ODA4ODgwI7uHu7MIA7sDIiAAAAADc4Nzc3
CDg4OAIju7u7MwO7AyIiAAAAA3ODc3NzAIODgwIiO7u7u7uwMiIgAAAIdzc3N3c3Nwg4MAIiI7u7u7sD
IiIAAAADc4Nzd3NzcwODgwIiIjMzMzMyIiIAAAAHdzc3d3c3MDg4OAAiIiIiIiIiIiIAAAADc3Nzc3Nz
cIODg4MCIiIiIiIiIiIAAAAANzg3NzA3MDg4ODgCIiIiIiIiIiIAAAAAAACDc3AAAIODg4AiIiIiIiIi
IiIAAAAAAAA4Nzc3ADg4ODAiIiIiIiIiIiIAAAAAAAADc3NzcIOAg4AiIiIiIiIiIiIAAAAAAAAANzc3
cDgwAAgiIiIiIiIiIiIAAAAAAAAAA3NzcIODgwgiIiIiIiIiIiIAAAAAAAAAADc3MDg4OAgiIiIiIiIi
IiIgAAAAAAAAAAAAAIODg4AiIiIiIiIiIiIgAAAAAAAAAAAAADg4ODAiIiIiIiIiIiIiAAAAAAAAAAAA
AACDg4ACIiIiIiIiIiIiIAAAAAAAAAAAAAAAAAACIiIiIiIiIiIiIgAAAAAAAAAAAAAAAAACIiIiIiIi
IiIiIiIAAAAAAAAAAAAAAAACIiIiIiIiIiIiIiIiIiAAAAAAAAAAAAAiIiIiIiIiIiIiIiIiIiIAAAAA
AAAAACIiIiIiIiIiIiIiIiIiIiIiAAAAAAAAIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi
IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiL///////8AAP///////wAA///+D///AAD///wH//8AAP//
+AP//wAA///4Af//AAD///gA//8AAP+AAAB//wAA/AAAAD//AADgAAAAH/8AAIAAAAAADwAAAAAAAAAH
AAAAAAAAAAMAAAAAAAAAAQAAAAAAAAAAAACAAAAAAAAAAMAAABwAAAAA4AAAPAAAAADwAAB8AAAAAPgA
APwAAAAA+AAA/AAAAAD4AAD8AGAAAPAAAAwAQAAA4AAABAABAADAAAAGAAMAAMAAAAcABwAAgAAAB4AP
AAAAAAAHwB8AAAAAAAP//wAAAAAAAf//AAAAAAAB//8AAAAAAAP//wAAAAAAA///AAAAAAAD//8AAAAA
AAP//wAAAAAAA///AAAAAAAD//8AAIAAAAP//wAAgAAAA///AADAAAAB//8AAOAAAAH//wAA8AAAAf//
AAD8AAAB//8AAP/gAAP//wAA//AAD///AAD//AA///8AAP///////wAA////////AAAoAAAAIAAAAEAA
AAABAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAICAAIAAAACAAIAAgIAAAMDA
wACAgIAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////ACIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIAAy
IiIiIiIiIiIiIiIiIgCIAyIiIiIiIiIiIiIiIiIHC4AyIiIiIiIiIiiAAAAAC3C4AyIiIiIiIoAAAAzM
zAC3C4AyIiIiIoAADMzMzMABAHC4AzMzMiIADMzAAMwAERC3C4AAAAMiDMzAA4MAARGRALC7u7uAMiDM
CDc3MAhziRALsws7uAMgAHdzeAGDhzAiCzCzC7sDIgA3N4MAOHMCIgsLMLu7AyIgA3MBAQOAIiI7swgA
iwMiIAc3g4dwMCIiOzCwggsDIgAAd3d38AAAIjt7sIC7gyAAAAd3dzE4NwIju7gLuDIgAAB3c3dwA4cC
Iju7u4MiAAAHdzd/d3A4EiIjMzMyIgAAB3d3938DgwAiIiIiIiIAAAA3d3B3CHdzAiIiIiIiAAAAADdx
AAd3MCIiIiIiIgAAAAADd3ADCHAiIiIiIiIAAAAAADf3CBADIiIiIiIiAAAAAAADdwN3CCIiIiIiIiAA
AAAAAAAIc3AiIiIiIiIgAAAAAAAAADcwAiIiIiIiIgAAAAAAAAAAAAIiIiIiIiIiAAAAAAAAAAACIiIi
IiIiIiIgAAAAAAAAIiIiIiIiIiIiIiAAAAAAIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi
IiIiIiIi///////+H////A////wH//gAA//AAAH/AAAABwAAAAMAAAABgAAAAIAAMADAAHAA4ADwAOAA
8BDAADAAgAAYAYAAHAMAAB4HAAAP/wAAB/8AAA//AAAP/wAAD/8AAA//gAAP/4AAB//AAAf/8AAH//4A
D///gD////////////8oAAAAEAAAACAAAAABAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
gAAAAAAAAICAAIAAAACAAIAAgIAAAMDAwACAgIAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////ACIi
IiIAMiIiIiIiIDsDIiIiDMRAsLAyIgzMzMwLCwAyDMAAABCwuwMAB3ARkjuzsCB3gAAiOzCwIgh3cAA7
uzMgBzdwhwMzMgB3f3cIAiIiAHd3AHOIIiIAAHfwMAIiIgAAB3CHAiIiAAAAADgAIiIgAAAAAAAiIiIg
AAAAAiIi/x/AA/4PARHAB7C7AAGAMgAACDcAQAhzgMALs8AAuAOAAXdzAB+DhwAPCzAAH7sDAB83NwAP
OHOADwsL4B+7AygAAAAwAAAAYAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////ABEM
aQAAAAAANBpLAAAAAAB/TG4AYF5eAP1lVAD8ZFMA/WZVAPljUAD9alcA/WtYAL+LhADnWD4A711GAP1y
XAD9dV4A/XhgAPFoTgDzbVMA/XxkANxRMQD4e18A/YRpANJMJwDvdlYA/IttAP2OcADNSCEA4GZCALFl
TQD+knIAwEATAKU/GQDSXDIA1WI3AOuAWQD5km8At0YbAMVXKwDMXS8At1cxAH5AJwCFRy4A6Zp6AGxV
TACMUDYA13RFAGpjXwDViFUAbUkxAP+/kQCsZSsA7riKAJpYGQD/798A/8+cAP/ZpgDf0bwAhWAaAP3j
sAD/9+gAkXkwAP//8gD///wAv9msAICrZwDP4sUAcKlfAEiQNwBtxGIAespvAEyZRgBqqWYAL5gtAAqF
CgAWihYAGpYaAB6PHgAZdxkAKa0pACOQIwAbaBsAPLc8AEO7QwBAs0AAJWYlADmaOQBKvkoAT8FPAESm
RABSwlIATbNNAFC4UABWxFYAW8VbAGPKYwBpzWkAb9FvAGfAZwBFfkUAddJ1AHHLcQB813wAj+CPAICz
gAA1WTgAn7CkADd9VwACaHYAaZquABNyogAYdqYAF2OKACBggQAsWG8AE1+IACR+rgA5n9kAOou3AD+V
wwBHn9AAV6nXAGOr0gCezOYAo9DqAA1zswAkfbYAIm6dAD2i3wBNs/IAU7n5AHq74QCEwOQAlMjnAJfK
6ACezekAFXm6ACOFxgBDqO0AUbf/AFW7/wBWvP8AWmBkABuBzQAfhdQAS7H/AE2z/wBOtP8AQnOZACeM
4gAtkuYARKn/AESq/wBHrf8ASa//ACyS8QA6oP8APKH/AD2i/wBApv8AQ6j/ADKW/AAylfsAM5n/ADWb
/wA3nf8AEliiAC+M8wAxkfkANpT3AAkSHAAXY7oAKnziAC2C6gAndNoAJnHXACl64AAod90AIWK1ACNo
zgAkatAAFlOwAB5fwgAgYMYAImXLABBCngAcVrwAI2jdAB5awAAQLFsADhksABtRtwAaTbMADSloAB1W
0gAWQZ4AGUiuAAUpgwAUP6QAFDyiABQ6oAASNZsADCV+AA8tkwAQL5UABQcOAAgdbAANJo0ABxVbAAYY
ewAuNFcAHyApAAQMcgABAhUAAQRqAKSkpACXl5cAj4+PAISEhAB+fn4AcXFxAG1tbQBmZmYAVFRUAE1N
TQBKSkoARkZGAD8/PwA4ODgANjY2AC8vLwAsLCwAKioqACgoKAAkJCQAISEhAB8fHwAcHBwAGhoaABgY
GAAXFxcAEhISAA0NDQAKCgoAAgICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQUFBQUF
BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUF
BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUF
BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUF
BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUF
BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUF4ODhMuEy4TIy4TLh4eDg
4ODgBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQXg4SMsIiMiIyIjIiMjIywsNC/h4eAFBQUFBQUF
BQUFBQUFBQUFBQUFBQUFBQUFBeAoIiIeGhcPFxALCwkQDyIiIiIjIzTg4QUFBQUFBeDg4ODg4ODg4ODg
4AUFBQUFBSsiIhoaFw8QCwgIDAwNDygiEAsPGiIjNODg4eEH4eJsWGxYbFhsWGxs4+HgBQUFBSseGhoP
DwsJDA0RERERIjcpDwoJCxcaIjRYVE1UVE1QU1NTU05OT01NTVRY4AUFBSsoGg8XCwkMERMWFhYaKz4z
HhENCAsPFyJRWVZbTU1fWltbVlZVUlJST09N4uAFBTMiFw8LCA0RFhYZGTEoOz47IhYRDQkLDyJKW11Z
TFFZYGFdXVtWVlJSUk9NbOAFBTEiDxAJDRETGRkdGSIuPj4+KxQWEQ0IDyJKYGFObUNNYmJiYF1bVlZV
UlJNWOAFBQUjFwsMERYZGR0hHio7Ozs7MxcZFhEMECJGYWJUPkFKU2hjY2JgXVZWVVJNbOAFBQUxIgsN
ExYZHSEqKTo7Ozs7MykZFhMNCyJiZF9TPz85UV5oZGNiYFtWVVJN4OAFBQUFKx4RFhkdJyYiNzU6OjU6
Lh4dGRYRFzhkZ1lrQUFBbU1oaWdjYmFbVlJU4AUFBQUFBSIXFhkdJiImNzo3NTo6LiIdGRMfIkRnZ05D
QkJCQmtRaWlkYmFdVk1m4AUFBQUFBQUrKSYbIjEOIAYGDiE3NyIdGR8iQGdpalQ/AQEBAT9TSmlnZGJg
UFTgBQUFBQUFBQUFMTEiIwTX2dfZ19kGJiIxKCNGSGdpak0/Pz8/Pz9DVF5pZGJMVOEFBQUFBQUFBQUF
4OnvwdPU0tLS0s3ZBCMjIFRcZ2lqaFQ5OTk+OTk+alRlZ0xU4AUFBQUFBQUFBQX1APf3AADTz8/Pz8/S
1wIFBQVUTmVqZVM+bXdxcXF320RNUVTgBQUFBQUFBQUF8AD29/YA0NPNzMvLy8vMz9nVBQUFTVROWU13
gJKSkpKSgHZUWOAFBQUFBQUFBQXw9/b19fatzMfHx8fHx8fHy87XBQUFBQUFZnaLk5iTmJOTmJJx4+AF
BQUFBQUFBQX39fX09ADOx8PDw8PDw8PDw8fU1QUFBQUFl5KYmZmenpmZmJiScePgBQUFBQUFBQD19PTw
9K3Dw729vb25vb29vcPSxAUFBQUFgKWmpqampqampqWeknbgBQUFBQUFBfb08PDw9MC9vbm7u7u7u7u5
ub3HyAUFBQWAnqenqKioqKiop6empot14AUFBQUFBfXw8O3t9NG6u7q3t7e3t7e3u7q6zcgFBQWAqJ+f
oaGhoaGhn5+op6V24AUFBQUFBfTt7err8cG3t7KytLS0tLSysre7yMgFBQWAoaGhoqKioqKioaGhn5+L
deAFBQUFBfDt6uvo6q2ytLSvsLCwsK+wtLKyvMgFBZeeoqObm5ycnJubo6OioaGYdeAFBQUFBfTq6+jo
5/e7r7CqqqqqqqqwsLC0vHYFBXmNm5ydnZSUlJSdnZybo6KhduAFBQUFBfTo6Ojn5vHIqqqmpqanpqal
qrCwvMgFBZebnZWVlpaOjpaWlZWdnKOigOAFBQUFBfbo6ebl5ujQtLCqqqefn6inpqWeyAUFBXmUlY6O
j5CQkJCOjo6VlJybkuAFBQUFBfDq5ubl5OTxwcvDt7exsKunpqaYyAUFBZeWjo+QkJCQkJCQkI6OlpWd
kuAFBQUFBQX15uXk4uPi6vT2rdHJvcW3t7LA8gUFBXmNkJCQkJCQkJCQkJCPjpaVi+AFBQUFBQX16OTk
5uIH4N/f5vHY08TUxK0A6AUFBZeDkJB4jIt4m5WWjo6OlpSMceAFBQUFBQUF9uTi4uLh393a2tsH6fD0
8Or3BQUFBXmMjHGLenqMcYuTmKekmItyduAFBQUFBQUF9fXiB+Hg393b2kNt3d8H5PTtBQUFBQVxcXKM
eHx8fYZ6eXFyd3dxc+AFBQUFBQUFBfX04uHf3t3d3Nra294H6/YFBQUFBQUFcXp6fHx9h4d/f399cIGA
dAUFBQUFBQUFBQX19eLe3dzb3d7f4OLt9gUFBQUFBQUFcXp8fX2Hh35/f4d8end24AUFBQUFBQUFBQUF
BfXw4t7b3eDk7vbmBQUFBQUFBQUFBXF8fYeHiYeHfXx8enGXBQUFBQUFBQUFBQUFBQUF9fUAAPXoBQUF
BQUFBQUFBQUFBQVxfYd+f4qHh318cnkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUF
cXmHf39+fHdyBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBXmXeZd5l3kFBQUF
BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUF
BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUF
BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUF
BQUFBQUFBQUFBQUFBQUFBQUF////////AAD///////8AAP///////wAA////////AAD///////8AAP//
/////wAA4AAH////AADAAAH///8AAIAAAH4AHwAAgAAAAAAHAACAAAAAAAMAAIAAAAAAAQAAgAAAAAAB
AACAAAAAAAEAAMAAAAAAAQAAwAAAAAABAADgAAAAAAMAAPAAAAAAAwAA+AAAAAAHAAD8AAAAAA8AAPwA
AAAAHwAA+AAOAAA/AADgAAcAAH8AAMAAB+AAfwAAwAAD4AA/AACAAAPgAD8AAIAAA8AAHwAAgAABwAAf
AACAAAHAAA8AAIAAAYAADwAAgAABgAAPAACAAAGAAA8AAIAAA4AADwAAgAADgAAPAADAAAOAAA8AAMAA
A4AADwAA4AAHgAAPAADgAAfAAA8AAPAAD+AAHwAA+AAf4AAfAAD+AD/wAD8AAP+B//gAfwAA/////AH/
AAD////+A/8AAP///////wAA////////AAD///////8AAP///////wAAKAAAACAAAABAAAAAAQAIAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AEQxpAAAAAAA0GksATCFPAH9MbgBgXl4A/WVUAPxk
UwD9ZlUA+WNQAP1qVwD9a1gAv4uEAOdYPgDvXUYA/XJcAP11XgD9eGAA8WhOAPNtUwD9fGQA3FExAPh7
XwD9hGkA0kwnAO92VgD8i20A/Y5wAM1IIQDgZkIAsWVNAP6ScgDAQBMApT8ZANJcMgDVYjcA64BZAPmS
bwC3RhsAxVcrAMxdLwC3VzEAfkAnAIVHLgDpmnoAbFVMAIxQNgDXdEUAamNfANWIVQBtSTEA/7+RAKxl
KwDuuIoAmlgZAP/v3wD/z5wA/9mmAN/RvACFYBoA/eOwAP/36ACReTAA///yAP///AC/2awAgKtnAM/i
xQBwqV8ASJA3AG3EYgB6ym8ATJlGAGqpZgAvmC0ACoUKABaKFgAalhoAHo8eABl3GQAprSkAI5AjABto
GwA8tzwAQ7tDAECzQAAlZiUAOZo5AEq+SgBPwU8ARKZEAFLCUgBNs00AULhQAFbEVgBbxVsAY8pjAGnN
aQBv0W8AZ8BnAEV+RQB10nUAcctxAHzXfACP4I8AgLOAADVZOACfsKQAN31XAAJodgBpmq4AE3KiABh2
pgAXY4oAIGCBACxYbwATX4gAJH6uADmf2QA6i7cAP5XDAEef0ABXqdcAY6vSAJ7M5gCj0OoADXOzACR9
tgAibp0APaLfAE2z8gBTufkAervhAITA5ACUyOcAl8roAJ7N6QAVeboAI4XGAEOo7QBRt/8AVbv/AFa8
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
GwDFVysAzF0vALdXMQB+QCcAhUcuAOmaegBsVUwAjFA2ANd0RQBqY18A1YhVAG1JMQD/v5EArGUrAO64
igCaWBkA/+/fAP/PnAD/2aYA39G8AIVgGgD947AA//foAJF5MAD///IA///8AL/ZrACAq2cAz+LFAHCp
XwBIkDcAbcRiAHrKbwBMmUYAaqlmAC+YLQAKhQoAFooWABqWGgAejx4AGXcZACmtKQAjkCMAG2gbADy3
PABDu0MAQLNAACVmJQA5mjkASr5KAE/BTwBEpkQAUsJSAE2zTQBQuFAAVsRWAFvFWwBjymMAac1pAG/R
bwBnwGcARX5FAHXSdQBxy3EAfNd8AI/gjwCAs4AANVk4AJ+wpAA3fVcAAmh2AGmargATcqIAGHamABdj
igAgYIEALFhvABNfiAAkfq4AOZ/ZADqLtwA/lcMAR5/QAFep1wBjq9IAnszmAKPQ6gANc7MAJH22ACJu
nQA9ot8ATbPyAFO5+QB6u+EAhMDkAJTI5wCXyugAns3pABV5ugAjhcYAQ6jtAFG3/wBVu/8AVrz/AFpg
ZAAbgc0AH4XUAEux/wBNs/8ATrT/AEJzmQAnjOIALZLmAESp/wBEqv8AR63/AEmv/wAskvEAOqD/ADyh
/wA9ov8AQKb/AEOo/wAylvwAMpX7ADOZ/wA1m/8AN53/ABJYogAvjPMAMZH5ADaU9wAJEhwAF2O6ACp8
4gAtguoAJ3TaACZx1wApeuAAKHfdACFitQAjaM4AJGrQABZTsAAeX8IAIGDGACJlywAQQp4AHFa8ACNo
3QAeWsAAECxbAA4ZLAAbUbcAGk2zAA0paAAdVtIAFkGeABlIrgAFKYMAFD+kABQ8ogAUOqAAEjWbAAwl
fgAPLZMAEC+VAAUHDgAIHWwADSaNAAcVWwAGGHsALjRXAB8gKQAEDHIAAQIVAAEEagCkpKQAl5eXAI+P
jwCEhIQAfn5+AHFxcQBtbW0AZmZmAFRUVABNTU0ASkpKAEZGRgA/Pz8AODg4ADY2NgAvLy8ALCwsACoq
KgAoKCgAJCQkACEhIQAfHx8AHBwcABoaGgAYGBgAFxcXABISEgANDQ0ACgoKAAICAgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA39/f4ODg4OAAAAAAAAAA4CAwMDAw
LzLf4ODg4N/f4B8XCxEUMRQabGxMR0xYbOAzCxYcMzoVDEBeS2JdVVPgAB8ZJjo6Gw1EazleZ1tH4AAA
IAXVBiBAaWo/Q2FcAAAA89DEy8/R4kuXi4Fu4wAA5vHAw73Cz+JwnqamnnXdAPTszrGysr+ReqKioqGM
4ADq6HWrpqy3kXuUlJWdmeEA4OTm5cm6dt58hISPjo3gAADn4dza4+UAfYF8fXtxcAAAAOAHB+EAAAB5
h397cAAAAAAAAAAAAAAAAHl5eQAAAAAAAAAAAAAAAAAAAAAAAAD//xcQgH8TFgAAPjMAAAkQAABbTIAA
XVrAA1JSgAPgAAABDwkAARkcAAE+NwABDAuBAWFGw4NiYf/HVVL//+AAKAAAADAAAABgAAAAAQAgAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAcAAAATAAAAHgAAACUAAAAsAAAALwAA
AC8AAAAvAAAALwAAAC8AAAAvAAAALgAAACkAAAAkAAAAHwAAABgAAAARAAAACQAAAAIAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAEAAAADEAAABVAAAAbQAA
AHwAAACJAAAAjwAAAI8AAACPAAAAjwAAAI8AAACPAAAAjAAAAIMAAAB5AAAAbgAAAGEAAABSAAAAQAAA
AC4AAAAfAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALKA0BRm0i
ArWIKgLijy0C67A3A/+wNwP/sDcD/7A3A/+wNwP/sDcD/7A3A/+wNwP/nzID944sAu2FKgLnaSEC11Qa
AckwDwGyAAAAlwAAAIcAAABwAAAAUAAAAC0AAAARAAAABAAAAAAAAAAAAAAAAQAAAAQAAAAKAAAADwAA
ABUAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAFQAAAA0AAAAGAAAAAQAAAAAAAAAAAAAAAAAA
AAB8JwJErDYD9bk8DP/AQBT/ykcf/9RNKf/dUjL/4lU4/+hYPv/uXET/9WBL//diTv/6Y1H/7lxE/+pa
QP++PxH/uTwM/8VDGf+0OQf/qDQD+4UpAulSGgHNAAAAnQAAAH0AAABPAAAAKAAAABwAAAAiAAAALAAA
ADcAAABDAAAATQAAAFkAAABfAAAAXwAAAF8AAABfAAAAXwAAAF8AAABfAAAAWQAAAEoAAAA6AAAAJwAA
ABEAAAAEAAAAAAAAAACjMwOsuj0N/8lGHv/RSyb/104s/+FUNv/lVzv/8F1G//hiT//9ZVT//WZV//1p
V//9alj//WpY/+pdQv+1Qw//tToI//hiT//4Yk//6lk//9BKJf+2Owr/nzID90UWAcwAAACYAAAAdQAA
AGgAAAB2AAwAjwAmAK0AJACzAD8AzwA+ANIAPgDTAD4A0wA+ANMAPgDTAD4A0wA+ANMAPgDTACMAuwAT
AKkAAACSAAAAegAAAEkAAAAWAAAAAQAAAACoNQPIw0IX/9BLJf/XTiz/4VQ2/+hYPv/1YEv//GVT//1o
Vv/9bVn//XBc//1zXv/9dF//+HBZ/7o+Dv/muYb/v1sn/+BYOf/9aFb//GVT//VgS//oWD7/1k4s/7M5
Bv9iLAHlADwA2ABTAOoAYgD6AGYA/wVsBf8KcQr/H4wf/yORI/8ikCL/IJAg/yCQIP8cjhz/Go0a/xaL
Fv8OgA7/CHcI/wJqAv8AXAD3ACgAzAAAAIUAAAA3AAAACAAAAACqNQPGx0Ub/9ZOK//hVDb/6Fg+//Vg
S//9ZlT//WtY//1xXP/9d2D//Xpi//18ZP/9f2b/0lUt/8RkMf//7rv/3J5r/8hKH//9cVz//WxZ//1m
VP/1YEv/6Fg+/9xRMf+wNwP/I4IY/zGhMf9DtEP/Tb9N/wVsBf8Odw7/UMFQ/0/AT/9Nv03/S75L/0e8
R/9CukL/PLc8/zSzNP8tsC3/Jawl/xynHP8SlRL/AWoB/wATAK0AAABTAAAAEgAAAACrNQO0xUQa/91S
Mv/lVzv/9WBL//1mVP/9bVr//XNe//16Yv/9f2b//YNp//2Gav/lbkv/tUIO//rbqf//6Lb/9dKf/7A3
A//9emL//XNe//1tWv/9ZlT/9WBL/+ZXPP+9PxH/ZZ06/06/Tv9Tw1P/NaE1/zCDKP8geRv/Mpwy/1nG
Wf9Yxlj/VcRV/1HBUf9Mv0z/R7xH/z+5P/81tDX/LrAu/yWsJf8cpxz/Cn4K/wA4AM0AAABcAAAAFgAA
AACpNQNkuj0O/+NVOf/wXUb//GVT//1sWf/9c17//Xpi//2CaP/9h2v//o1v//mJav+1PAr/5qt4///h
rv//4q///+Kw/79XI//qb07//Xpi//1zXv/9bVn//GVT//BdRv+9PxH/aqA//1jGWP9eyF7/HoUe/5/G
iv+/2ab/BmwG/2DGYP9ky2T/YMlg/1vHW/9WxFb/T8BP/0i9SP9BuUH/N7U3/y2wLf8kqyT/DoYO/wA+
ANEAAABVAAAAEwAAAACmNAMRrzcD8dtRMP/4Yk///WhW//1xXP/9emL//YJo//2IbP/+j3D//pR0/8RP
IP/OdED//9uo///bqP//3Kn//9yp/9N/S//XXjb//YJo//16Yv/9cl3//WlX//hiT/+8PhD/caNG/2TL
ZP9ix2L/AGYA/+/11f///+T/YJ9W/ySIJP9v0G//a85r/2XMZf9fyV//WMZY/1HBUf9JvUn/P7k//zW0
Nf8qrir/DoAO/wA6AMQAAABBAAAACgAAAAAAAAAArDYDg7w+EP/9ZVT//W5a//13YP/9f2b//Ydr//6P
cP/+lnX/12g9/79UIP/6ypf//9Sh///Uof//1qP//9aj/9yQXf/IUiX//Ydr//1/Zv/9d2D//W5a//hi
T/+wNwP/Z8xn/27Qbv9PsE//MIMs////6f///+v/7/Xc/xBwD/9TslP/dtR2/3HRcf9ozWj/Ycph/1jG
WP9PwE//R7xH/z64Pv8xsjH/BW8F/wAhAJUAAAApAAAAAgAAAAAAAAAAAAAAAK83A9HNSiL//XBc//16
Yv/9g2n//o1v//6UdP/melL/tUAM//Cwff//zpv//86b///Om///z5z//8+c/+updv/ETR///o1v//2E
af/9emL//XFc/+BWN/+eXR3/cdFx/3fUd/83mDf/gLN4////8P////L////y/6/Pp/8IbQj/cMtw/3rW
ev9y0nL/aM1o/2DJYP9YxVj/Tr9O/0K6Qv8onSj/AF4A8wAAAFQAAAATAAAAAAAAAAAAAAAAAAAAAKY0
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//
/////wAA////////AAD///////8AAP///////wAA////////AADAAAP///8AAIAAAH///wAAgAAAGAAH
AACAAAAAAAEAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAMAA
AAAAAAAA4AAAAAABAADgAAAAAAEAAPAAAAAAAwAA8AAAAAADAADAAAAAAAcAAIAAAAAADwAAgAAAAAAf
AAAAAACAAB8AAAAAAMAADwAAAAAAAAAPAAAAAAAAAAcAAAAAAAAABwAAAAAAAAAHAAAAAAAAAAMAAAAA
AAAAAwAAAAAAAAADAAAAAAAAAAMAAIAAAAAAAwAAgAAAgAADAACAAACAAAMAAMAAAIAAAwAA4AABwAAH
AADgAAHAAAcAAPAAA8AABwAA/AAH4AAPAAD+AB/wAB8AAP////gAPwAA/////AD/AAD///////8AAP//
/////wAA////////AAD///////8AACgAAAAgAAAAQAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAMAAAAFQAAABgAAAAYAAAAGAAA
ABgAAAAYAAAAFgAAABIAAAALAAAABAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAAAAJQAAAEUAAABZAAAAXwAA
AF8AAABfAAAAXwAAAF8AAABcAAAAUwAAAEYAAAA2AAAAJgAAABYAAAAJAAAAAQAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB9RGQGMbyMCy2sh
AtJrIQLTayEC02shAtNrIQLTayEC01QaAcg9EwG5EgYAoAAAAI8AAAB7AAAAXQAAADkAAAAdAAAAFgAA
ABwAAAAjAAAAKQAAAC4AAAAvAAAALwAAAC8AAAAuAAAAKAAAAB4AAAAPAAAABAAAAAAAAAAArTcG18FB
Ff/RSyb/21Ew/+hYP//zX0r/+WNQ//1lVP/9ZVT/zUgh/9JLJv/UTSn/oTYO82ggAtogCgGwAAAAiAAA
AGcAAABeAAAAagAAAHcAAACDAAAAjAAAAI8AAACPAAAAjwAAAIwAAACCAAAAbQAAAEQAAAAWAAAAAQAA
AAC7PQ7/0kwn/91SM//vXUb//GRT//1pV//9cVz//XRe/+9qTv/Ti1f/zVsw//1nVf/5Y1D/5lc8/7c+
FPtCIwHXADcAzwRPBN0IXwjqFHQU9SKRIv8fjx//H48f/x2OHf8Wihb/C24L9wNVA+kAKQDHAAAAgQAA
ADMAAAAGAAAAAMNDF//bUTD/711G//1mVf/9clz//Xdg//19ZP/9g2j/yFos//rir//ThlP/821T//1r
WP/8ZFP/7FtC/5pYGf9As0D/T8FP/y+SLP8kjiT/UsJS/1LCUv9Kvkr/QLlA/zu3O/8try3/Iakh/wqF
Cv8AFACmAAAAQwAAAAoAAAAAuT0O4uhYP//8ZFP//XJc//15Yf/9hWr//Yxu/9djOv/rt4T//+Ow//DE
kf/gZkL//Xdg//1qV//5Y1D/p2Im/1bEVv9Zw1n/cKlf/4Czbf9Ns03/ZMtk/1zHXP9Tw1P/RbxF/zy3
PP8try3/Gpka/wAlAK8AAAA9AAAABwAAAACsNgOD5Vc7//1rWP/9d2D//YZq//6Scv/rgFn/2IdU///Z
pv//2ab//9qn/9JaMf/9g2j//XVe//1mVf+wZy//Z81n/0SoRP+/2az////l/0eYQv9003T/as5q/2LK
Yv9WxFb/RbxF/zm2Of8akhr/ACEAlAAAACgAAAACAAAAAAAAAAC7Pg/R+G9X//19ZP/9i27/+ZJv/8li
MP//zpv//8+c///PnP//0J3/13ZH//2JbP/9e2P/82ZO/5F5MP921Hb/Ppo9////8v////L/z+LF/ziY
OP9713v/btBu/2LKYv9RwVH/Prk+/w9zD/IAAABPAAAAEQAAAAAAAAAAAAAAAKY0AxG+RRjT73ZW//mM
a//NWy7/6Zp6/7+Kg/+/jIT/7q2K//+/kf/XcUP//Y5w//h7X/+6TBr/espv/4HZgf9kq2P////8////
////////gLOA/2fAZ/961nr/ac1p/1vGW/8unS7/ADcAlQAAACIAAAAEAAAAAAAAAAAAAAACAAAAEC4O
AT6JKwK4tEUe/0whT/8BBGr/BA1z/wMLcf8RDGn/f0xu/9JgNP/SXjP/hWAa/23EYv961nr/jN+M/3Cm
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
5/+j0Or/lMjn/3694v9XqNb/G3mr9QA0Tl4AAAASAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAZJWDJHyp01yhxP9PmsH/M4i18gplkq4AOlg4AAAACgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA////////////////wAH//4AAP/+AAAABgAAAAIAAAACAAAAAgAAAAIAA
AADAAAABwAAAAYAAAAMAAAAHAAAABwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAOAAAADgAAAA8AA
AAPgAYAD8AfAB///4A////////////////8oAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAQAAAAkAAAATAAAAGAAAABgAAAAXAAAAEwAAAAsAAAADAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAsAAAAvAAAAUwAAAF8AAABfAAAAXgAAAFYAAABFAAAALQAAABwAAAAbAAAAIQAA
ACMAAAAiAAAAHAAAAA9mIAI3ii0Mr3wrEMyDLxvTgy8b02YiCM09EwG6AAAAmQAAAIIAAABoAAAAZwAA
AHMAAAB3AAAAdgAAAGcAAAA9tz0Pxd1SM//5Y1D//XBb//NsUv/SbkH/+GVR/8xKKfstMgfXElcS2yF5
IeothC3rIX4h7BFrEecDMAPAAAAAZ7c9D6P5Y1D//Xpi//6Mbv/chVb/9c2b/+9wUv/9alf/koc8/1Ov
T/9nrlz/Ycph/1XDVf84tTj/FnoW6QAAAGahMgMj4V0/8f2Ia//hfVH/+seU///ToP/ld1D/+HRb/5Gc
UP+GwoD/7/Xg/1WvVf9z0nP/UsJS/xh1GNkAAAA9AAAADVYbAWKhTELvQiNa/0M2eP9gSHf/u1s4+5N6
Nf+C2oL/pMaX///17P+6z6j/Y8Fj/0GjQfkAKQB3AAAAFwAAAEkEBATtAwYN/w8rcf8UOqD/EDGX/wIP
XO4AJQCvQJBAy0OIjv8Qdrn/IH27/xpxW/sAGwC0AAAAVwAAABMKCgrKGhoa/xIvaP8aTbP/HVe9/xtP
tf8NMpP/AAggrQU9XpQtk/L/M5n//zOZ//8rke//BCxEzAAAAHkAAAAlFRUV/ygoKP8YQoH/JnPZ/yZz
2f8mc9n/G1y9/wAPLLMdc7DQP6X//0Cm//9Apv//PqT//x97vvcAAACRAAAANyAgIPE1NTX/JUVr/zCQ
9v80mv//M5b6/yFz0v8AFjGtK4bG1kyy//9Ns///TbP//0mv//8xl+b/AAoQnQAAAD0UFBSiSkpK/0JC
Qv82RmX/G0WQ/yJixv8VR33/ABgxhjKQzc5MsvL/SrDs/1e9//9Qtv//QqXq/wAnO6YAAAAwAAAAES4u
LvBpaWn/jY2N/6SkpP9PT0//ER0m1wAAAC8LbJ2XKYe5/1Kk0v9hqNP/UZ/Q/xh1pP8AAABaAAAAGQAA
AAAAAAAhLCwsslxcXP9LS0vkISEhrgAAACcAAAAIAGCQIimDs/CLxOX/oc/q/1ekz/8NXomtAAAAIAAA
AAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5QhLoCqhEyRtYkAVoFfAAAADQAA
AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAB/AAAAABf/AAAw/wAARv8AAFX/AABc/wAAYP8AAGT/AABo/wAALP8AAK//AABT/wAA
U/+AAFj//4FT////Qv8=
</value>
</data>
</root>

View File

@@ -0,0 +1,358 @@
Imports System.ComponentModel
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Controls
Imports PersonalUtilities.Forms.Controls.Base
Imports PersonalUtilities.Forms.Toolbars
Imports SCrawler.API.Base
Namespace Editors
Friend Class UserCreatorForm : Implements IOkCancelToolbar
Private ReadOnly MyDef As DefaultFormProps(Of FieldsChecker)
Friend Property User As UserInfo
Friend Property UserInstance As IUserData
Friend Property StartIndex As Integer = -1
Friend ReadOnly Property UserTemporary As Boolean
Get
If CH_FAV.Checked Then
Return False
Else
Return CH_TEMP.Checked
End If
End Get
End Property
Friend ReadOnly Property UserFavorite As Boolean
Get
Return CH_FAV.Checked
End Get
End Property
Friend ReadOnly Property UserMediaOnly As Boolean
Get
If User.Site = Sites.Twitter Then
Return CH_PARSE_USER_MEDIA.Checked
Else
Return False
End If
End Get
End Property
Friend ReadOnly Property UserReady As Boolean
Get
Return CH_READY_FOR_DOWN.Checked
End Get
End Property
Friend ReadOnly Property UserDescr As String
Get
Return TXT_DESCR.Text
End Get
End Property
Friend ReadOnly Property UserFriendly As String
Get
Return TXT_USER_FRIENDLY.Text
End Get
End Property
Friend ReadOnly Property UserLabels As List(Of String)
Friend Sub New()
InitializeComponent()
UserLabels = New List(Of String)
MyDef = New DefaultFormProps(Of FieldsChecker)
End Sub
Friend Sub New(ByVal _User As UserInfo)
Me.New
User = _User
End Sub
Friend Sub New(ByVal _Instance As IUserData)
Me.New
If Not _Instance Is Nothing Then
UserInstance = _Instance
User = DirectCast(UserInstance, UserDataBase).User
End If
End Sub
Private Sub UserCreatorForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
With MyDef
.MyViewInitialize(Me, Settings.Design, True)
.AddOkCancelToolbar()
If User.Name.IsEmptyString Then
OPT_REDDIT.Checked = False
OPT_TWITTER.Checked = False
CH_PARSE_USER_MEDIA.Enabled = False
CH_READY_FOR_DOWN.Checked = True
CH_TEMP.Checked = Settings.DefaultTemporary.Value
Else
TP_ADD_BY_LIST.Enabled = False
TXT_USER.Text = User.Name
Select Case User.Site
Case Sites.Reddit : OPT_REDDIT.Checked = True : CH_PARSE_USER_MEDIA.Enabled = False
Case Sites.Twitter : OPT_TWITTER.Checked = True
End Select
OPT_REDDIT.Enabled = False
OPT_TWITTER.Enabled = False
If Not UserInstance Is Nothing Then
TXT_USER.Enabled = False
With UserInstance
TXT_USER_FRIENDLY.Text = .FriendlyName
CH_FAV.Checked = .Favorite
CH_TEMP.Checked = .Temporary
CH_PARSE_USER_MEDIA.Checked = .ParseUserMediaOnly
CH_READY_FOR_DOWN.Checked = .ReadyForDownload
TXT_DESCR.Text = .Description
UserLabels.ListAddList(.Labels)
If UserLabels.ListExists Then TXT_LABELS.Text = UserLabels.ListToString
End With
End If
End If
.MyFieldsChecker = New FieldsChecker
.MyFieldsChecker.AddControl(Of String)(TXT_USER, TXT_USER.CaptionText)
.MyFieldsChecker.EndLoaderOperations()
TextBoxExtended.SetFalseDetector(Me, True, AddressOf .Detector)
.EndLoaderOperations()
End With
Catch ex As Exception
MyDef.InvokeLoaderError(ex)
End Try
End Sub
Private Sub UserCreatorForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If e.KeyCode = Keys.F4 Then ChangeLabels() : e.Handled = True
End Sub
Private Sub UserCreatorForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
If Not BeforeCloseChecker(MyDef.ChangesDetected) Then
e.Cancel = True
Else
MyDef.Dispose()
If Not DialogResult = DialogResult.OK And Not DialogResult = DialogResult.Cancel And StartIndex >= 0 Then DialogResult = DialogResult.OK
End If
End Sub
Private Sub UserCreatorForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
UserLabels.Clear()
End Sub
Private Sub ToolbarBttOK() Implements IOkCancelToolbar.ToolbarBttOK
If Not CH_ADD_BY_LIST.Checked Then
If MyDef.MyFieldsChecker.AllParamsOK Then
If OPT_REDDIT.Checked Or OPT_TWITTER.Checked Then
Dim tmpUser As UserInfo = User.Clone
With tmpUser
.Name = TXT_USER.Text
.Site = IIf(OPT_REDDIT.Checked, Sites.Reddit, Sites.Twitter)
.UpdateUserFile()
End With
User = tmpUser
If Not UserInstance Is Nothing Then
With DirectCast(UserInstance, UserDataBase)
.User = User
.FriendlyName = TXT_USER_FRIENDLY.Text
.Favorite = CH_FAV.Checked
.Temporary = CH_TEMP.Checked
.ReadyForDownload = CH_READY_FOR_DOWN.Checked
.UserDescription = TXT_DESCR.Text
Dim l As New ListAddParams(LAP.NotContainsOnly + LAP.ClearBeforeAdd)
If .IsCollection Then
With DirectCast(UserInstance, API.UserDataBind)
If .Count > 0 Then .Collections.ForEach(Sub(c) c.Labels.ListAddList(UserLabels, l))
End With
Else
.Labels.ListAddList(UserLabels, LAP.NotContainsOnly, LAP.ClearBeforeAdd)
End If
If OPT_TWITTER.Checked Then .ParseUserMediaOnly = CH_PARSE_USER_MEDIA.Checked
.UpdateUserInformation()
End With
End If
GoTo CloseForm
Else
MsgBoxE("User site does not selected", MsgBoxStyle.Exclamation)
End If
End If
Else
If CreateUsersByList() Then GoTo CloseForm
End If
Exit Sub
CloseForm:
MyDef.CloseForm()
End Sub
Private Sub ToolbarBttCancel() Implements IOkCancelToolbar.ToolbarBttCancel
MyDef.CloseForm(IIf(StartIndex >= 0, DialogResult.OK, DialogResult.Cancel))
End Sub
Private ReadOnly TwitterRegEx As New RegexStructure("[htps:/]{7,8}.*?twitter.com/([^/]+)", 1)
Private ReadOnly RedditRegEx1 As New RegexStructure("[htps:/]{7,8}.*?reddit.com/user/([^/]+)", 1)
Private ReadOnly RedditRegEx2 As New RegexStructure(".?u/([^/]+)", 1)
Private _TextChangeInvoked As Boolean = False
Private Sub TXT_USER_ActionOnTextChange() Handles TXT_USER.ActionOnTextChange
Try
If Not _TextChangeInvoked Then
_TextChangeInvoked = True
If Not CH_ADD_BY_LIST.Checked Then
Select Case GetSiteByText(TXT_USER.Text)
Case Sites.Twitter : OPT_TWITTER.Checked = True
Case Sites.Reddit : OPT_REDDIT.Checked = True
Case Else : OPT_TWITTER.Checked = False : OPT_REDDIT.Checked = False
End Select
End If
MyDef.Detector()
_TextChangeInvoked = False
End If
Catch ex As Exception
End Try
End Sub
Private Function GetSiteByText(ByRef TXT As String) As Sites
If Not TXT.IsEmptyString AndAlso TXT.Length > 8 Then
Dim s$ = RegexReplace(TXT, TwitterRegEx)
If Not s.IsEmptyString Then
TXT = s
Return Sites.Twitter
Else
s = RegexReplace(TXT, RedditRegEx1)
If Not s.IsEmptyString Then
TXT = s
Return Sites.Reddit
Else
s = RegexReplace(TXT, RedditRegEx2)
If Not s.IsEmptyString Then
TXT = s
Return Sites.Reddit
End If
End If
End If
End If
Return Sites.Undefined
End Function
Private Sub OPT_REDDIT_CheckedChanged(sender As Object, e As EventArgs) Handles OPT_REDDIT.CheckedChanged
MyDef.Detector()
End Sub
Private Sub OPT_TWITTER_CheckedChanged(sender As Object, e As EventArgs) Handles OPT_TWITTER.CheckedChanged
MyDef.Detector()
CH_PARSE_USER_MEDIA.Enabled = OPT_TWITTER.Checked
End Sub
Private Sub CH_TEMP_CheckedChanged(sender As Object, e As EventArgs) Handles CH_TEMP.CheckedChanged
If CH_TEMP.Checked Then CH_FAV.Checked = False
MyDef.Detector()
End Sub
Private Sub CH_FAV_CheckedChanged(sender As Object, e As EventArgs) Handles CH_FAV.CheckedChanged
If CH_FAV.Checked Then CH_TEMP.Checked = False
MyDef.Detector()
End Sub
Private Sub CH_READY_FOR_DOWN_CheckedChanged(sender As Object, e As EventArgs) Handles CH_READY_FOR_DOWN.CheckedChanged
MyDef.Detector()
End Sub
Private Sub CH_PARSE_USER_MADIA_CheckedChanged(sender As Object, e As EventArgs) Handles CH_PARSE_USER_MEDIA.CheckedChanged
MyDef.Detector()
End Sub
Private Sub CH_ADD_BY_LIST_CheckedChanged(sender As Object, e As EventArgs) Handles CH_ADD_BY_LIST.CheckedChanged
If CH_ADD_BY_LIST.Checked Then
TXT_DESCR.GroupBoxText = "Users list"
Else
TXT_DESCR.GroupBoxText = "Description"
End If
TXT_USER.Enabled = Not CH_ADD_BY_LIST.Checked
TXT_USER_FRIENDLY.Enabled = Not CH_ADD_BY_LIST.Checked
End Sub
Private Sub CH_AUTO_DETECT_SITE_CheckedChanged(sender As Object, e As EventArgs) Handles CH_AUTO_DETECT_SITE.CheckedChanged
OPT_REDDIT.Enabled = Not CH_AUTO_DETECT_SITE.Checked
OPT_TWITTER.Enabled = Not CH_AUTO_DETECT_SITE.Checked
End Sub
Private Function CreateUsersByList() As Boolean
Try
If CH_ADD_BY_LIST.Checked Then
If Not TXT_DESCR.IsEmptyString Then
Dim u As List(Of String) = TXT_DESCR.Text.StringToList(Of String, List(Of String))(vbNewLine).ListForEach(Function(s, ii) s.Trim,, False)
If u.ListExists Then
Dim NonIdentified As New List(Of String)
Dim UsersForCreate As New List(Of UserInfo)
Dim BannedUsers() As String = Nothing
Dim uu$
Dim tmpUser As UserInfo
Dim s As Sites
Dim Added% = 0
Dim Skipped% = 0
Dim uid%
Select Case True
Case OPT_REDDIT.Checked : s = Sites.Reddit
Case OPT_TWITTER.Checked : s = Sites.Twitter
Case Else : s = Sites.Undefined
End Select
For i% = 0 To u.Count - 1
uu = u(i)
If CH_AUTO_DETECT_SITE.Checked Then s = GetSiteByText(uu)
If Not s = Sites.Undefined Then
tmpUser = New UserInfo(uu, s)
uid = -1
If Settings.UsersList.Count > 0 Then uid = Settings.UsersList.IndexOf(tmpUser)
If uid < 0 And Not UsersForCreate.Contains(tmpUser) Then
UsersForCreate.Add(tmpUser)
Else
Skipped += 1
End If
Else
NonIdentified.Add(u(i))
End If
Next
If UsersForCreate.Count > 0 Then
BannedUsers = UserBanned(UsersForCreate.Select(Function(uuu) uuu.Name).ToArray)
If BannedUsers.ListExists Then UsersForCreate.RemoveAll(Function(uuu) BannedUsers.Contains(uuu.Name))
If UsersForCreate.Count > 0 Then
For Each tmpUser In UsersForCreate
Settings.UpdateUsersList(tmpUser)
If StartIndex = -1 Then StartIndex = Settings.Users.Count
Settings.Users.Add(UserDataBase.GetInstance(tmpUser, False))
With Settings.Users.Last
.FriendlyName = TXT_USER_FRIENDLY.Text
.Favorite = CH_FAV.Checked
.Temporary = CH_TEMP.Checked
.ReadyForDownload = CH_READY_FOR_DOWN.Checked
.Labels.ListAddList(UserLabels)
If s = Sites.Twitter Then .ParseUserMediaOnly = CH_PARSE_USER_MEDIA.Checked
.UpdateUserInformation()
End With
Added += 1
Next
End If
End If
Dim m As New MMessage($"Added {Added} users (skipped (already exists and/or duplicated) {Skipped})")
If BannedUsers.ListExists Or NonIdentified.Count > 0 Then
Dim t$ = String.Empty
If BannedUsers.ListExists Then t.StringAppendLine($"Banned users:{vbNewLine}{BannedUsers.ListToString(, vbNewLine)}")
If NonIdentified.Count > 0 Then t.StringAppendLine($"Non-Identified users:{vbNewLine}{NonIdentified.ListToString(, vbNewLine)}", vbNewLine.StringDup(2))
m.Style = MsgBoxStyle.Exclamation
m.Text.StringAppendLine("Some of users does not recognized and/or banned")
m.Text.StringAppendLine(t, vbNewLine.StringDup(2))
TXT_DESCR.Text = t
Else
TXT_DESCR.Clear()
End If
MsgBoxE(m)
Return Added > 0 And Not BannedUsers.ListExists And NonIdentified.Count = 0
Else
MsgBoxE("No one user can not recognized", MsgBoxStyle.Exclamation)
End If
Else
MsgBoxE("[Users list] is empty", MsgBoxStyle.Critical)
End If
End If
Return False
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Error on adding users by list", False)
End Try
End Function
Private Sub TXT_LABELS_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_LABELS.ActionOnButtonClick
Select Case Sender.DefaultButton
Case ActionButton.DefaultButtons.Open : ChangeLabels()
Case ActionButton.DefaultButtons.Clear : UserLabels.Clear()
End Select
End Sub
Private Sub ChangeLabels()
Using fl As New LabelsForm(UserLabels)
fl.ShowDialog()
If fl.DialogResult = DialogResult.OK Then
UserLabels.ListAddList(fl.LabelsList, LAP.NotContainsOnly, LAP.ClearBeforeAdd)
If UserLabels.ListExists Then
TXT_LABELS.Text = UserLabels.ListToString
Else
TXT_LABELS.Clear()
End If
End If
End Using
End Sub
End Class
End Namespace

103
SCrawler/LabelsKeeper.vb Normal file
View File

@@ -0,0 +1,103 @@
Imports PersonalUtilities.Tools
Friend Class LabelsKeeper : Implements ICollection(Of String), IMyEnumerator(Of String), IDisposable
Friend Event NewLabelAdded()
Friend Const NoLabeledName As String = "No Label"
Friend Const NoParsedUser As String = "No Parsed"
Friend ReadOnly NoLabel As New ListViewGroup(NoLabeledName, NoLabeledName)
Private ReadOnly LabelsList As List(Of String)
Private ReadOnly LabelsFile As SFile = "Settings\Labels.txt"
Friend ReadOnly NewLabels As List(Of String)
Friend ReadOnly Property NewLabelsExists As Boolean
Get
Return NewLabels.Count > 0
End Get
End Property
Friend ReadOnly Property CurrentSelection As List(Of String)
Friend Sub New()
LabelsList = New List(Of String)
NewLabels = New List(Of String)
CurrentSelection = New List(Of String)
If LabelsFile.Exists Then LabelsList.ListAddList(IO.File.ReadAllLines(LabelsFile), LAP.NotContainsOnly)
End Sub
Friend ReadOnly Property ToList As List(Of String)
Get
Return LabelsList
End Get
End Property
Friend ReadOnly Property Count As Integer Implements ICollection(Of String).Count, IMyEnumerator(Of String).MyEnumeratorCount
Get
Return LabelsList.Count
End Get
End Property
Default Friend ReadOnly Property Item(ByVal Index As Integer) As String Implements IMyEnumerator(Of String).MyEnumeratorObject
Get
Return LabelsList(Index)
End Get
End Property
Friend Sub Clear() Implements ICollection(Of String).Clear
LabelsList.Clear()
NewLabels.Clear()
End Sub
Friend Sub Update()
If LabelsList.Count > 0 Then
LabelsList.Sort()
TextSaver.SaveTextToFile(LabelsList.ListToString(, vbNewLine), LabelsFile, True, False, EDP.SendInLog)
Else
If LabelsFile.Exists Then LabelsFile.Delete(,,, EDP.SendInLog)
End If
End Sub
Friend Overloads Sub Add(ByVal _Item As String) Implements ICollection(Of String).Add
Add(_Item, True)
End Sub
Friend Overloads Sub Add(ByVal _Item As String, ByVal UpdateMainFrame As Boolean)
If Not _Item.IsEmptyString And Not LabelsList.Contains(_Item) Then
LabelsList.Add(_Item)
If Not NewLabels.Contains(_Item) Then NewLabels.Add(_Item)
If UpdateMainFrame Then RaiseEvent NewLabelAdded()
End If
End Sub
Friend Sub AddRange(ByVal _Items As IEnumerable(Of String))
If _Items.ListExists Then
For Each i$ In _Items : Add(i, False) : Next
RaiseEvent NewLabelAdded()
End If
End Sub
Friend Function Contains(ByVal _Item As String) As Boolean Implements ICollection(Of String).Contains
Return LabelsList.Contains(_Item)
End Function
Friend Function Remove(ByVal _Item As String) As Boolean Implements ICollection(Of String).Remove
Return LabelsList.Remove(_Item)
End Function
Private ReadOnly Property IsReadOnly As Boolean = False Implements ICollection(Of String).IsReadOnly
Private Sub CopyTo(ByVal _Array() As String, ByVal ArrayIndex As Integer) Implements ICollection(Of String).CopyTo
Throw New NotImplementedException()
End Sub
#Region "IEnumerable Support"
Private Function GetEnumerator() As IEnumerator(Of String) Implements IEnumerable(Of String).GetEnumerator
Return New MyEnumerator(Of String)(Me)
End Function
Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Return GetEnumerator()
End Function
#End Region
#Region "IDisposable Support"
Private disposedValue As Boolean = False
Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
If Not disposedValue Then
If disposing Then
Clear()
CurrentSelection.Clear()
End If
disposedValue = True
End If
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub
Friend Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class

578
SCrawler/MainFrame.Designer.vb generated Normal file
View File

@@ -0,0 +1,578 @@
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class MainFrame
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()>
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
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container()
Dim SEP_1 As System.Windows.Forms.ToolStripSeparator
Dim SEP_2 As System.Windows.Forms.ToolStripSeparator
Dim CONTEXT_SEP_1 As System.Windows.Forms.ToolStripSeparator
Dim MENU_SETTINGS As System.Windows.Forms.ToolStripDropDownButton
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(MainFrame))
Dim MENU_SETTINGS_SEP_1 As System.Windows.Forms.ToolStripSeparator
Dim SEP_3 As System.Windows.Forms.ToolStripSeparator
Dim CONTEXT_SEP_2 As System.Windows.Forms.ToolStripSeparator
Dim CONTEXT_SEP_3 As System.Windows.Forms.ToolStripSeparator
Dim CONTEXT_SEP_4 As System.Windows.Forms.ToolStripSeparator
Dim CONTEXT_SEP_5 As System.Windows.Forms.ToolStripSeparator
Dim SEP_4 As System.Windows.Forms.ToolStripSeparator
Dim MENU_VIEW_SEP_1 As System.Windows.Forms.ToolStripSeparator
Dim MENU_VIEW_SEP_2 As System.Windows.Forms.ToolStripSeparator
Me.BTT_SETTINGS_REDDIT = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_SETTINGS_TWITTER = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_SETTINGS = New System.Windows.Forms.ToolStripMenuItem()
Me.Toolbar_TOP = New System.Windows.Forms.ToolStrip()
Me.BTT_ADD_USER = New System.Windows.Forms.ToolStripButton()
Me.BTT_EDIT_USER = New System.Windows.Forms.ToolStripButton()
Me.BTT_DELETE_USER = New System.Windows.Forms.ToolStripButton()
Me.BTT_REFRESH = New System.Windows.Forms.ToolStripButton()
Me.BTT_SHOW_INFO = New System.Windows.Forms.ToolStripButton()
Me.BTT_CHANNELS = New System.Windows.Forms.ToolStripButton()
Me.BTT_DOWN_SELECTED = New System.Windows.Forms.ToolStripButton()
Me.BTT_DOWN_ALL = New System.Windows.Forms.ToolStripButton()
Me.BTT_DOWN_VIDEO = New System.Windows.Forms.ToolStripButton()
Me.BTT_DOWN_STOP = New System.Windows.Forms.ToolStripButton()
Me.MENU_VIEW = New System.Windows.Forms.ToolStripDropDownButton()
Me.BTT_VIEW_LARGE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_VIEW_SMALL = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_VIEW_LIST = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_SHOW_ALL = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_SHOW_REGULAR = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_SHOW_TEMP = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_SHOW_FAV = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_SHOW_LABELS = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_SHOW_NO_LABELS = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_SELECT_LABELS = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_LOG = New System.Windows.Forms.ToolStripButton()
Me.BTT_VERSION_INFO = New System.Windows.Forms.ToolStripButton()
Me.Toolbar_BOTTOM = New System.Windows.Forms.StatusStrip()
Me.PR_MAIN = New System.Windows.Forms.ToolStripProgressBar()
Me.LBL_JOBS_COUNT = New System.Windows.Forms.ToolStripStatusLabel()
Me.LBL_STATUS = New System.Windows.Forms.ToolStripStatusLabel()
Me.LIST_PROFILES = New System.Windows.Forms.ListView()
Me.USER_CONTEXT = New System.Windows.Forms.ContextMenuStrip(Me.components)
Me.BTT_CONTEXT_DOWN = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_EDIT = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_DELETE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_FAV = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_TEMP = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_GROUPS = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_ADD_TO_COL = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_COL_MERGE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CHANGE_IMAGE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_OPEN_PATH = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_OPEN_SITE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_INFO = New System.Windows.Forms.ToolStripMenuItem()
SEP_1 = New System.Windows.Forms.ToolStripSeparator()
SEP_2 = New System.Windows.Forms.ToolStripSeparator()
CONTEXT_SEP_1 = New System.Windows.Forms.ToolStripSeparator()
MENU_SETTINGS = New System.Windows.Forms.ToolStripDropDownButton()
MENU_SETTINGS_SEP_1 = New System.Windows.Forms.ToolStripSeparator()
SEP_3 = New System.Windows.Forms.ToolStripSeparator()
CONTEXT_SEP_2 = New System.Windows.Forms.ToolStripSeparator()
CONTEXT_SEP_3 = New System.Windows.Forms.ToolStripSeparator()
CONTEXT_SEP_4 = New System.Windows.Forms.ToolStripSeparator()
CONTEXT_SEP_5 = New System.Windows.Forms.ToolStripSeparator()
SEP_4 = New System.Windows.Forms.ToolStripSeparator()
MENU_VIEW_SEP_1 = New System.Windows.Forms.ToolStripSeparator()
MENU_VIEW_SEP_2 = New System.Windows.Forms.ToolStripSeparator()
Me.Toolbar_TOP.SuspendLayout()
Me.Toolbar_BOTTOM.SuspendLayout()
Me.USER_CONTEXT.SuspendLayout()
Me.SuspendLayout()
'
'SEP_1
'
SEP_1.Name = "SEP_1"
SEP_1.Size = New System.Drawing.Size(6, 25)
'
'SEP_2
'
SEP_2.Name = "SEP_2"
SEP_2.Size = New System.Drawing.Size(6, 25)
'
'CONTEXT_SEP_1
'
CONTEXT_SEP_1.Name = "CONTEXT_SEP_1"
CONTEXT_SEP_1.Size = New System.Drawing.Size(192, 6)
'
'MENU_SETTINGS
'
MENU_SETTINGS.AutoToolTip = False
MENU_SETTINGS.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text
MENU_SETTINGS.DropDownItems.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_SETTINGS_REDDIT, Me.BTT_SETTINGS_TWITTER, MENU_SETTINGS_SEP_1, Me.BTT_SETTINGS})
MENU_SETTINGS.Image = CType(resources.GetObject("MENU_SETTINGS.Image"), System.Drawing.Image)
MENU_SETTINGS.ImageTransparentColor = System.Drawing.Color.Magenta
MENU_SETTINGS.Name = "MENU_SETTINGS"
MENU_SETTINGS.Size = New System.Drawing.Size(62, 22)
MENU_SETTINGS.Text = "Settings"
'
'BTT_SETTINGS_REDDIT
'
Me.BTT_SETTINGS_REDDIT.Name = "BTT_SETTINGS_REDDIT"
Me.BTT_SETTINGS_REDDIT.Size = New System.Drawing.Size(116, 22)
Me.BTT_SETTINGS_REDDIT.Text = "Reddit"
'
'BTT_SETTINGS_TWITTER
'
Me.BTT_SETTINGS_TWITTER.Name = "BTT_SETTINGS_TWITTER"
Me.BTT_SETTINGS_TWITTER.Size = New System.Drawing.Size(116, 22)
Me.BTT_SETTINGS_TWITTER.Text = "Twitter"
'
'MENU_SETTINGS_SEP_1
'
MENU_SETTINGS_SEP_1.Name = "MENU_SETTINGS_SEP_1"
MENU_SETTINGS_SEP_1.Size = New System.Drawing.Size(113, 6)
'
'BTT_SETTINGS
'
Me.BTT_SETTINGS.Name = "BTT_SETTINGS"
Me.BTT_SETTINGS.Size = New System.Drawing.Size(116, 22)
Me.BTT_SETTINGS.Text = "Settings"
'
'SEP_3
'
SEP_3.Name = "SEP_3"
SEP_3.Size = New System.Drawing.Size(6, 25)
'
'CONTEXT_SEP_2
'
CONTEXT_SEP_2.Name = "CONTEXT_SEP_2"
CONTEXT_SEP_2.Size = New System.Drawing.Size(192, 6)
'
'CONTEXT_SEP_3
'
CONTEXT_SEP_3.Name = "CONTEXT_SEP_3"
CONTEXT_SEP_3.Size = New System.Drawing.Size(192, 6)
'
'CONTEXT_SEP_4
'
CONTEXT_SEP_4.Name = "CONTEXT_SEP_4"
CONTEXT_SEP_4.Size = New System.Drawing.Size(192, 6)
'
'CONTEXT_SEP_5
'
CONTEXT_SEP_5.Name = "CONTEXT_SEP_5"
CONTEXT_SEP_5.Size = New System.Drawing.Size(192, 6)
'
'SEP_4
'
SEP_4.Name = "SEP_4"
SEP_4.Size = New System.Drawing.Size(6, 25)
'
'MENU_VIEW_SEP_1
'
MENU_VIEW_SEP_1.Name = "MENU_VIEW_SEP_1"
MENU_VIEW_SEP_1.Size = New System.Drawing.Size(141, 6)
'
'MENU_VIEW_SEP_2
'
MENU_VIEW_SEP_2.Name = "MENU_VIEW_SEP_2"
MENU_VIEW_SEP_2.Size = New System.Drawing.Size(141, 6)
'
'Toolbar_TOP
'
Me.Toolbar_TOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden
Me.Toolbar_TOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {MENU_SETTINGS, SEP_1, Me.BTT_ADD_USER, Me.BTT_EDIT_USER, Me.BTT_DELETE_USER, Me.BTT_REFRESH, Me.BTT_SHOW_INFO, Me.BTT_CHANNELS, SEP_2, Me.BTT_DOWN_SELECTED, Me.BTT_DOWN_ALL, Me.BTT_DOWN_VIDEO, Me.BTT_DOWN_STOP, SEP_3, Me.MENU_VIEW, SEP_4, Me.BTT_LOG, Me.BTT_VERSION_INFO})
Me.Toolbar_TOP.Location = New System.Drawing.Point(0, 0)
Me.Toolbar_TOP.Name = "Toolbar_TOP"
Me.Toolbar_TOP.Size = New System.Drawing.Size(934, 25)
Me.Toolbar_TOP.TabIndex = 1
'
'BTT_ADD_USER
'
Me.BTT_ADD_USER.Image = Global.SCrawler.My.Resources.Resources.PlusPIC
Me.BTT_ADD_USER.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_ADD_USER.Name = "BTT_ADD_USER"
Me.BTT_ADD_USER.Size = New System.Drawing.Size(49, 22)
Me.BTT_ADD_USER.Text = "Add"
Me.BTT_ADD_USER.ToolTipText = "Add user (Insert)"
'
'BTT_EDIT_USER
'
Me.BTT_EDIT_USER.Image = Global.SCrawler.My.Resources.Resources.PencilPic_01_16
Me.BTT_EDIT_USER.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_EDIT_USER.Name = "BTT_EDIT_USER"
Me.BTT_EDIT_USER.Size = New System.Drawing.Size(47, 22)
Me.BTT_EDIT_USER.Text = "Edit"
Me.BTT_EDIT_USER.ToolTipText = "Edit user (F3)"
'
'BTT_DELETE_USER
'
Me.BTT_DELETE_USER.Image = Global.SCrawler.My.Resources.Resources.Delete
Me.BTT_DELETE_USER.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_DELETE_USER.Name = "BTT_DELETE_USER"
Me.BTT_DELETE_USER.Size = New System.Drawing.Size(60, 22)
Me.BTT_DELETE_USER.Text = "Delete"
Me.BTT_DELETE_USER.ToolTipText = "Delete user (Del)"
'
'BTT_REFRESH
'
Me.BTT_REFRESH.AutoToolTip = False
Me.BTT_REFRESH.Image = Global.SCrawler.My.Resources.Resources.Refresh
Me.BTT_REFRESH.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_REFRESH.Name = "BTT_REFRESH"
Me.BTT_REFRESH.Size = New System.Drawing.Size(66, 22)
Me.BTT_REFRESH.Text = "Refresh"
'
'BTT_SHOW_INFO
'
Me.BTT_SHOW_INFO.Image = Global.SCrawler.My.Resources.Resources.InfoPic_32
Me.BTT_SHOW_INFO.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_SHOW_INFO.Name = "BTT_SHOW_INFO"
Me.BTT_SHOW_INFO.Size = New System.Drawing.Size(48, 22)
Me.BTT_SHOW_INFO.Text = "Info"
Me.BTT_SHOW_INFO.ToolTipText = "Show download summary"
'
'BTT_CHANNELS
'
Me.BTT_CHANNELS.Image = Global.SCrawler.My.Resources.Resources.RedditPic512
Me.BTT_CHANNELS.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_CHANNELS.Name = "BTT_CHANNELS"
Me.BTT_CHANNELS.Size = New System.Drawing.Size(76, 22)
Me.BTT_CHANNELS.Text = "Channels"
'
'BTT_DOWN_SELECTED
'
Me.BTT_DOWN_SELECTED.Image = Global.SCrawler.My.Resources.Resources.StartPic_01_Green_16
Me.BTT_DOWN_SELECTED.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_DOWN_SELECTED.Name = "BTT_DOWN_SELECTED"
Me.BTT_DOWN_SELECTED.Size = New System.Drawing.Size(150, 22)
Me.BTT_DOWN_SELECTED.Text = "Download selected (F5)"
Me.BTT_DOWN_SELECTED.ToolTipText = "Download selected user"
'
'BTT_DOWN_ALL
'
Me.BTT_DOWN_ALL.Image = Global.SCrawler.My.Resources.Resources.StartPic_01_Green_16
Me.BTT_DOWN_ALL.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_DOWN_ALL.Name = "BTT_DOWN_ALL"
Me.BTT_DOWN_ALL.Size = New System.Drawing.Size(119, 22)
Me.BTT_DOWN_ALL.Text = "Download all (F6)"
Me.BTT_DOWN_ALL.ToolTipText = "Download all users"
'
'BTT_DOWN_VIDEO
'
Me.BTT_DOWN_VIDEO.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text
Me.BTT_DOWN_VIDEO.Image = CType(resources.GetObject("BTT_DOWN_VIDEO.Image"), System.Drawing.Image)
Me.BTT_DOWN_VIDEO.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_DOWN_VIDEO.Name = "BTT_DOWN_VIDEO"
Me.BTT_DOWN_VIDEO.Size = New System.Drawing.Size(120, 22)
Me.BTT_DOWN_VIDEO.Text = "Download video (F2)"
Me.BTT_DOWN_VIDEO.ToolTipText = "Download video by URL"
'
'BTT_DOWN_STOP
'
Me.BTT_DOWN_STOP.AutoToolTip = False
Me.BTT_DOWN_STOP.Enabled = False
Me.BTT_DOWN_STOP.Image = Global.SCrawler.My.Resources.Resources.Delete
Me.BTT_DOWN_STOP.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_DOWN_STOP.Name = "BTT_DOWN_STOP"
Me.BTT_DOWN_STOP.Size = New System.Drawing.Size(51, 22)
Me.BTT_DOWN_STOP.Text = "Stop"
'
'MENU_VIEW
'
Me.MENU_VIEW.AutoToolTip = False
Me.MENU_VIEW.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text
Me.MENU_VIEW.DropDownItems.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_VIEW_LARGE, Me.BTT_VIEW_SMALL, Me.BTT_VIEW_LIST, MENU_VIEW_SEP_1, Me.BTT_SHOW_ALL, Me.BTT_SHOW_REGULAR, Me.BTT_SHOW_TEMP, Me.BTT_SHOW_FAV, Me.BTT_SHOW_LABELS, Me.BTT_SHOW_NO_LABELS, MENU_VIEW_SEP_2, Me.BTT_SELECT_LABELS})
Me.MENU_VIEW.Image = CType(resources.GetObject("MENU_VIEW.Image"), System.Drawing.Image)
Me.MENU_VIEW.ImageTransparentColor = System.Drawing.Color.Magenta
Me.MENU_VIEW.Name = "MENU_VIEW"
Me.MENU_VIEW.Size = New System.Drawing.Size(45, 22)
Me.MENU_VIEW.Text = "View"
'
'BTT_VIEW_LARGE
'
Me.BTT_VIEW_LARGE.Name = "BTT_VIEW_LARGE"
Me.BTT_VIEW_LARGE.Size = New System.Drawing.Size(144, 22)
Me.BTT_VIEW_LARGE.Text = "Large images"
'
'BTT_VIEW_SMALL
'
Me.BTT_VIEW_SMALL.Name = "BTT_VIEW_SMALL"
Me.BTT_VIEW_SMALL.Size = New System.Drawing.Size(144, 22)
Me.BTT_VIEW_SMALL.Text = "Small images"
'
'BTT_VIEW_LIST
'
Me.BTT_VIEW_LIST.Name = "BTT_VIEW_LIST"
Me.BTT_VIEW_LIST.Size = New System.Drawing.Size(144, 22)
Me.BTT_VIEW_LIST.Text = "List"
'
'BTT_SHOW_ALL
'
Me.BTT_SHOW_ALL.Name = "BTT_SHOW_ALL"
Me.BTT_SHOW_ALL.Size = New System.Drawing.Size(144, 22)
Me.BTT_SHOW_ALL.Text = "All"
'
'BTT_SHOW_REGULAR
'
Me.BTT_SHOW_REGULAR.Name = "BTT_SHOW_REGULAR"
Me.BTT_SHOW_REGULAR.Size = New System.Drawing.Size(144, 22)
Me.BTT_SHOW_REGULAR.Text = "Regular"
'
'BTT_SHOW_TEMP
'
Me.BTT_SHOW_TEMP.Name = "BTT_SHOW_TEMP"
Me.BTT_SHOW_TEMP.Size = New System.Drawing.Size(144, 22)
Me.BTT_SHOW_TEMP.Text = "Temporary"
'
'BTT_SHOW_FAV
'
Me.BTT_SHOW_FAV.Name = "BTT_SHOW_FAV"
Me.BTT_SHOW_FAV.Size = New System.Drawing.Size(144, 22)
Me.BTT_SHOW_FAV.Text = "Favorites"
'
'BTT_SHOW_LABELS
'
Me.BTT_SHOW_LABELS.Name = "BTT_SHOW_LABELS"
Me.BTT_SHOW_LABELS.Size = New System.Drawing.Size(144, 22)
Me.BTT_SHOW_LABELS.Text = "Labels"
'
'BTT_SHOW_NO_LABELS
'
Me.BTT_SHOW_NO_LABELS.Name = "BTT_SHOW_NO_LABELS"
Me.BTT_SHOW_NO_LABELS.Size = New System.Drawing.Size(144, 22)
Me.BTT_SHOW_NO_LABELS.Text = "No labels"
'
'BTT_SELECT_LABELS
'
Me.BTT_SELECT_LABELS.Name = "BTT_SELECT_LABELS"
Me.BTT_SELECT_LABELS.Size = New System.Drawing.Size(144, 22)
Me.BTT_SELECT_LABELS.Text = "Select labels"
'
'BTT_LOG
'
Me.BTT_LOG.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text
Me.BTT_LOG.Image = CType(resources.GetObject("BTT_LOG.Image"), System.Drawing.Image)
Me.BTT_LOG.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_LOG.Name = "BTT_LOG"
Me.BTT_LOG.Size = New System.Drawing.Size(34, 19)
Me.BTT_LOG.Text = "LOG"
Me.BTT_LOG.ToolTipText = "Show error log"
'
'BTT_VERSION_INFO
'
Me.BTT_VERSION_INFO.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right
Me.BTT_VERSION_INFO.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image
Me.BTT_VERSION_INFO.Image = Global.SCrawler.My.Resources.Resources.InfoPic_32
Me.BTT_VERSION_INFO.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_VERSION_INFO.Name = "BTT_VERSION_INFO"
Me.BTT_VERSION_INFO.Size = New System.Drawing.Size(23, 20)
Me.BTT_VERSION_INFO.Text = "Info"
Me.BTT_VERSION_INFO.ToolTipText = "Show program information and check for new version"
'
'Toolbar_BOTTOM
'
Me.Toolbar_BOTTOM.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.PR_MAIN, Me.LBL_JOBS_COUNT, Me.LBL_STATUS})
Me.Toolbar_BOTTOM.Location = New System.Drawing.Point(0, 439)
Me.Toolbar_BOTTOM.Name = "Toolbar_BOTTOM"
Me.Toolbar_BOTTOM.Size = New System.Drawing.Size(934, 22)
Me.Toolbar_BOTTOM.TabIndex = 2
Me.Toolbar_BOTTOM.Text = "StatusStrip1"
'
'PR_MAIN
'
Me.PR_MAIN.Name = "PR_MAIN"
Me.PR_MAIN.Size = New System.Drawing.Size(200, 16)
Me.PR_MAIN.Visible = False
'
'LBL_JOBS_COUNT
'
Me.LBL_JOBS_COUNT.Name = "LBL_JOBS_COUNT"
Me.LBL_JOBS_COUNT.Size = New System.Drawing.Size(0, 17)
'
'LBL_STATUS
'
Me.LBL_STATUS.Name = "LBL_STATUS"
Me.LBL_STATUS.Size = New System.Drawing.Size(0, 17)
'
'LIST_PROFILES
'
Me.LIST_PROFILES.Activation = System.Windows.Forms.ItemActivation.OneClick
Me.LIST_PROFILES.ContextMenuStrip = Me.USER_CONTEXT
Me.LIST_PROFILES.Dock = System.Windows.Forms.DockStyle.Fill
Me.LIST_PROFILES.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None
Me.LIST_PROFILES.HideSelection = False
Me.LIST_PROFILES.Location = New System.Drawing.Point(0, 25)
Me.LIST_PROFILES.Name = "LIST_PROFILES"
Me.LIST_PROFILES.Size = New System.Drawing.Size(934, 414)
Me.LIST_PROFILES.TabIndex = 3
Me.LIST_PROFILES.UseCompatibleStateImageBehavior = False
'
'USER_CONTEXT
'
Me.USER_CONTEXT.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_CONTEXT_DOWN, Me.BTT_CONTEXT_EDIT, Me.BTT_CONTEXT_DELETE, CONTEXT_SEP_1, Me.BTT_CONTEXT_FAV, Me.BTT_CONTEXT_TEMP, Me.BTT_CONTEXT_GROUPS, Me.BTT_CONTEXT_ADD_TO_COL, Me.BTT_CONTEXT_COL_MERGE, CONTEXT_SEP_2, Me.BTT_CHANGE_IMAGE, CONTEXT_SEP_3, Me.BTT_CONTEXT_OPEN_PATH, CONTEXT_SEP_4, Me.BTT_CONTEXT_OPEN_SITE, CONTEXT_SEP_5, Me.BTT_CONTEXT_INFO})
Me.USER_CONTEXT.Name = "USER_CONTEXT"
Me.USER_CONTEXT.Size = New System.Drawing.Size(196, 298)
'
'BTT_CONTEXT_DOWN
'
Me.BTT_CONTEXT_DOWN.Image = Global.SCrawler.My.Resources.Resources.StartPic_01_Green_16
Me.BTT_CONTEXT_DOWN.Name = "BTT_CONTEXT_DOWN"
Me.BTT_CONTEXT_DOWN.Size = New System.Drawing.Size(195, 22)
Me.BTT_CONTEXT_DOWN.Text = "Download data"
'
'BTT_CONTEXT_EDIT
'
Me.BTT_CONTEXT_EDIT.Image = Global.SCrawler.My.Resources.Resources.PencilPic_01_16
Me.BTT_CONTEXT_EDIT.Name = "BTT_CONTEXT_EDIT"
Me.BTT_CONTEXT_EDIT.Size = New System.Drawing.Size(195, 22)
Me.BTT_CONTEXT_EDIT.Text = "Edit user information"
'
'BTT_CONTEXT_DELETE
'
Me.BTT_CONTEXT_DELETE.Image = Global.SCrawler.My.Resources.Resources.Delete
Me.BTT_CONTEXT_DELETE.Name = "BTT_CONTEXT_DELETE"
Me.BTT_CONTEXT_DELETE.Size = New System.Drawing.Size(195, 22)
Me.BTT_CONTEXT_DELETE.Text = "Delete user / collection"
'
'BTT_CONTEXT_FAV
'
Me.BTT_CONTEXT_FAV.Image = Global.SCrawler.My.Resources.Resources.StarPic_24
Me.BTT_CONTEXT_FAV.Name = "BTT_CONTEXT_FAV"
Me.BTT_CONTEXT_FAV.Size = New System.Drawing.Size(195, 22)
Me.BTT_CONTEXT_FAV.Text = "Change favorite"
'
'BTT_CONTEXT_TEMP
'
Me.BTT_CONTEXT_TEMP.Image = CType(resources.GetObject("BTT_CONTEXT_TEMP.Image"), System.Drawing.Image)
Me.BTT_CONTEXT_TEMP.Name = "BTT_CONTEXT_TEMP"
Me.BTT_CONTEXT_TEMP.Size = New System.Drawing.Size(195, 22)
Me.BTT_CONTEXT_TEMP.Text = "Change temporary"
'
'BTT_CONTEXT_GROUPS
'
Me.BTT_CONTEXT_GROUPS.Name = "BTT_CONTEXT_GROUPS"
Me.BTT_CONTEXT_GROUPS.Size = New System.Drawing.Size(195, 22)
Me.BTT_CONTEXT_GROUPS.Text = "Change labels"
'
'BTT_CONTEXT_ADD_TO_COL
'
Me.BTT_CONTEXT_ADD_TO_COL.Image = Global.SCrawler.My.Resources.Resources.DBPic_32
Me.BTT_CONTEXT_ADD_TO_COL.Name = "BTT_CONTEXT_ADD_TO_COL"
Me.BTT_CONTEXT_ADD_TO_COL.Size = New System.Drawing.Size(195, 22)
Me.BTT_CONTEXT_ADD_TO_COL.Text = "Add to collection"
'
'BTT_CONTEXT_COL_MERGE
'
Me.BTT_CONTEXT_COL_MERGE.Name = "BTT_CONTEXT_COL_MERGE"
Me.BTT_CONTEXT_COL_MERGE.Size = New System.Drawing.Size(195, 22)
Me.BTT_CONTEXT_COL_MERGE.Text = "Merge collection files"
'
'BTT_CHANGE_IMAGE
'
Me.BTT_CHANGE_IMAGE.Image = Global.SCrawler.My.Resources.Resources.PicturePic_32
Me.BTT_CHANGE_IMAGE.Name = "BTT_CHANGE_IMAGE"
Me.BTT_CHANGE_IMAGE.Size = New System.Drawing.Size(195, 22)
Me.BTT_CHANGE_IMAGE.Text = "Change image"
'
'BTT_CONTEXT_OPEN_PATH
'
Me.BTT_CONTEXT_OPEN_PATH.Image = Global.SCrawler.My.Resources.Resources.Folder_32
Me.BTT_CONTEXT_OPEN_PATH.Name = "BTT_CONTEXT_OPEN_PATH"
Me.BTT_CONTEXT_OPEN_PATH.Size = New System.Drawing.Size(195, 22)
Me.BTT_CONTEXT_OPEN_PATH.Text = "Open contains folder"
'
'BTT_CONTEXT_OPEN_SITE
'
Me.BTT_CONTEXT_OPEN_SITE.Image = Global.SCrawler.My.Resources.Resources.GlobeBlue_32
Me.BTT_CONTEXT_OPEN_SITE.Name = "BTT_CONTEXT_OPEN_SITE"
Me.BTT_CONTEXT_OPEN_SITE.Size = New System.Drawing.Size(195, 22)
Me.BTT_CONTEXT_OPEN_SITE.Text = "Open site"
'
'BTT_CONTEXT_INFO
'
Me.BTT_CONTEXT_INFO.Image = Global.SCrawler.My.Resources.Resources.InfoPic_32
Me.BTT_CONTEXT_INFO.Name = "BTT_CONTEXT_INFO"
Me.BTT_CONTEXT_INFO.Size = New System.Drawing.Size(195, 22)
Me.BTT_CONTEXT_INFO.Text = "Information"
'
'MainFrame
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(934, 461)
Me.Controls.Add(Me.LIST_PROFILES)
Me.Controls.Add(Me.Toolbar_BOTTOM)
Me.Controls.Add(Me.Toolbar_TOP)
Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon)
Me.KeyPreview = True
Me.MinimumSize = New System.Drawing.Size(950, 500)
Me.Name = "MainFrame"
Me.Text = "Social networks crawler"
Me.Toolbar_TOP.ResumeLayout(False)
Me.Toolbar_TOP.PerformLayout()
Me.Toolbar_BOTTOM.ResumeLayout(False)
Me.Toolbar_BOTTOM.PerformLayout()
Me.USER_CONTEXT.ResumeLayout(False)
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Private WithEvents BTT_SETTINGS_REDDIT As ToolStripMenuItem
Private WithEvents BTT_SETTINGS_TWITTER As ToolStripMenuItem
Private WithEvents BTT_SETTINGS As ToolStripMenuItem
Private WithEvents BTT_ADD_USER As ToolStripButton
Private WithEvents BTT_DELETE_USER As ToolStripButton
Private WithEvents BTT_DOWN_SELECTED As ToolStripButton
Private WithEvents BTT_DOWN_ALL As ToolStripButton
Private WithEvents Toolbar_TOP As ToolStrip
Private WithEvents Toolbar_BOTTOM As StatusStrip
Private WithEvents PR_MAIN As ToolStripProgressBar
Private WithEvents LBL_STATUS As ToolStripStatusLabel
Private WithEvents BTT_CONTEXT_DOWN As ToolStripMenuItem
Private WithEvents BTT_CONTEXT_EDIT As ToolStripMenuItem
Private WithEvents BTT_CONTEXT_DELETE As ToolStripMenuItem
Private WithEvents BTT_CONTEXT_FAV As ToolStripMenuItem
Private WithEvents BTT_CONTEXT_TEMP As ToolStripMenuItem
Private WithEvents USER_CONTEXT As ContextMenuStrip
Private WithEvents BTT_VIEW_LARGE As ToolStripMenuItem
Private WithEvents BTT_VIEW_SMALL As ToolStripMenuItem
Private WithEvents BTT_VIEW_LIST As ToolStripMenuItem
Private WithEvents BTT_CHANGE_IMAGE As ToolStripMenuItem
Private WithEvents BTT_CONTEXT_OPEN_PATH As ToolStripMenuItem
Private WithEvents BTT_CONTEXT_INFO As ToolStripMenuItem
Private WithEvents BTT_CONTEXT_OPEN_SITE As ToolStripMenuItem
Private WithEvents BTT_DOWN_STOP As ToolStripButton
Private WithEvents BTT_CONTEXT_COL_MERGE As ToolStripMenuItem
Private WithEvents LBL_JOBS_COUNT As ToolStripStatusLabel
Private WithEvents BTT_DOWN_VIDEO As ToolStripButton
Private WithEvents BTT_SHOW_INFO As ToolStripButton
Private WithEvents BTT_LOG As ToolStripButton
Private WithEvents BTT_CHANNELS As ToolStripButton
Private WithEvents LIST_PROFILES As ListView
Private WithEvents MENU_VIEW As ToolStripDropDownButton
Private WithEvents BTT_CONTEXT_ADD_TO_COL As ToolStripMenuItem
Private WithEvents BTT_REFRESH As ToolStripButton
Private WithEvents BTT_SHOW_ALL As ToolStripMenuItem
Private WithEvents BTT_SHOW_REGULAR As ToolStripMenuItem
Private WithEvents BTT_SHOW_TEMP As ToolStripMenuItem
Private WithEvents BTT_SHOW_FAV As ToolStripMenuItem
Private WithEvents BTT_SHOW_LABELS As ToolStripMenuItem
Private WithEvents BTT_SELECT_LABELS As ToolStripMenuItem
Private WithEvents BTT_SHOW_NO_LABELS As ToolStripMenuItem
Private WithEvents BTT_EDIT_USER As ToolStripButton
Private WithEvents BTT_CONTEXT_GROUPS As ToolStripMenuItem
Private WithEvents BTT_VERSION_INFO As ToolStripButton
End Class

478
SCrawler/MainFrame.resx Normal file
View File

@@ -0,0 +1,478 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="SEP_2.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="CONTEXT_SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="MENU_SETTINGS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="MENU_SETTINGS_SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="MENU_SETTINGS.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
TgDQASA1MVpwzwAAAABJRU5ErkJggg==
</value>
</data>
<metadata name="SEP_3.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="CONTEXT_SEP_2.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="CONTEXT_SEP_3.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="CONTEXT_SEP_4.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="CONTEXT_SEP_5.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="SEP_4.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="MENU_VIEW_SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="MENU_VIEW_SEP_2.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="Toolbar_TOP.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>132, 17</value>
</metadata>
<data name="BTT_DOWN_VIDEO.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
TgDQASA1MVpwzwAAAABJRU5ErkJggg==
</value>
</data>
<data name="MENU_VIEW.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
TgDQASA1MVpwzwAAAABJRU5ErkJggg==
</value>
</data>
<data name="BTT_LOG.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
TgDQASA1MVpwzwAAAABJRU5ErkJggg==
</value>
</data>
<metadata name="Toolbar_BOTTOM.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>239, 17</value>
</metadata>
<metadata name="USER_CONTEXT.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>387, 17</value>
</metadata>
<data name="BTT_CONTEXT_TEMP.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAACH
DwAAjA8AAP1SAACBQAAAfXkAAOmLAAA85QAAGcxzPIV3AAAKOWlDQ1BQaG90b3Nob3AgSUNDIHByb2Zp
bGUAAEjHnZZ3VFTXFofPvXd6oc0wAlKG3rvAANJ7k15FYZgZYCgDDjM0sSGiAhFFRJoiSFDEgNFQJFZE
sRAUVLAHJAgoMRhFVCxvRtaLrqy89/Ly++Osb+2z97n77L3PWhcAkqcvl5cGSwGQyhPwgzyc6RGRUXTs
AIABHmCAKQBMVka6X7B7CBDJy82FniFyAl8EAfB6WLwCcNPQM4BOB/+fpFnpfIHomAARm7M5GSwRF4g4
JUuQLrbPipgalyxmGCVmvihBEcuJOWGRDT77LLKjmNmpPLaIxTmns1PZYu4V8bZMIUfEiK+ICzO5nCwR
3xKxRoowlSviN+LYVA4zAwAUSWwXcFiJIjYRMYkfEuQi4uUA4EgJX3HcVyzgZAvEl3JJS8/hcxMSBXQd
li7d1NqaQffkZKVwBALDACYrmcln013SUtOZvBwAFu/8WTLi2tJFRbY0tba0NDQzMv2qUP91829K3NtF
ehn4uWcQrf+L7a/80hoAYMyJarPziy2uCoDOLQDI3fti0zgAgKSobx3Xv7oPTTwviQJBuo2xcVZWlhGX
wzISF/QP/U+Hv6GvvmckPu6P8tBdOfFMYYqALq4bKy0lTcinZ6QzWRy64Z+H+B8H/nUeBkGceA6fwxNF
hImmjMtLELWbx+YKuGk8Opf3n5r4D8P+pMW5FonS+BFQY4yA1HUqQH7tBygKESDR+8Vd/6NvvvgwIH55
4SqTi3P/7zf9Z8Gl4iWDm/A5ziUohM4S8jMX98TPEqABAUgCKpAHykAd6ABDYAasgC1wBG7AG/iDEBAJ
VgMWSASpgA+yQB7YBApBMdgJ9oBqUAcaQTNoBcdBJzgFzoNL4Bq4AW6D+2AUTIBnYBa8BgsQBGEhMkSB
5CEVSBPSh8wgBmQPuUG+UBAUCcVCCRAPEkJ50GaoGCqDqqF6qBn6HjoJnYeuQIPQXWgMmoZ+h97BCEyC
qbASrAUbwwzYCfaBQ+BVcAK8Bs6FC+AdcCXcAB+FO+Dz8DX4NjwKP4PnEIAQERqiihgiDMQF8UeikHiE
j6xHipAKpAFpRbqRPuQmMorMIG9RGBQFRUcZomxRnqhQFAu1BrUeVYKqRh1GdaB6UTdRY6hZ1Ec0Ga2I
1kfboL3QEegEdBa6EF2BbkK3oy+ib6Mn0K8xGAwNo42xwnhiIjFJmLWYEsw+TBvmHGYQM46Zw2Kx8lh9
rB3WH8vECrCF2CrsUexZ7BB2AvsGR8Sp4Mxw7rgoHA+Xj6vAHcGdwQ3hJnELeCm8Jt4G749n43PwpfhG
fDf+On4Cv0CQJmgT7AghhCTCJkIloZVwkfCA8JJIJKoRrYmBRC5xI7GSeIx4mThGfEuSIemRXEjRJCFp
B+kQ6RzpLuklmUzWIjuSo8gC8g5yM/kC+RH5jQRFwkjCS4ItsUGiRqJDYkjiuSReUlPSSXK1ZK5kheQJ
yeuSM1J4KS0pFymm1HqpGqmTUiNSc9IUaVNpf+lU6RLpI9JXpKdksDJaMm4ybJkCmYMyF2TGKQhFneJC
YVE2UxopFykTVAxVm+pFTaIWU7+jDlBnZWVkl8mGyWbL1sielh2lITQtmhcthVZKO04bpr1borTEaQln
yfYlrUuGlszLLZVzlOPIFcm1yd2WeydPl3eTT5bfJd8p/1ABpaCnEKiQpbBf4aLCzFLqUtulrKVFS48v
vacIK+opBimuVTyo2K84p6Ss5KGUrlSldEFpRpmm7KicpFyufEZ5WoWiYq/CVSlXOavylC5Ld6Kn0Cvp
vfRZVUVVT1Whar3qgOqCmrZaqFq+WpvaQ3WCOkM9Xr1cvUd9VkNFw08jT6NF454mXpOhmai5V7NPc15L
Wytca6tWp9aUtpy2l3audov2Ax2yjoPOGp0GnVu6GF2GbrLuPt0berCehV6iXo3edX1Y31Kfq79Pf9AA
bWBtwDNoMBgxJBk6GWYathiOGdGMfI3yjTqNnhtrGEcZ7zLuM/5oYmGSYtJoct9UxtTbNN+02/R3Mz0z
llmN2S1zsrm7+QbzLvMXy/SXcZbtX3bHgmLhZ7HVosfig6WVJd+y1XLaSsMq1qrWaoRBZQQwShiXrdHW
ztYbrE9Zv7WxtBHYHLf5zdbQNtn2iO3Ucu3lnOWNy8ft1OyYdvV2o/Z0+1j7A/ajDqoOTIcGh8eO6o5s
xybHSSddpySno07PnU2c+c7tzvMuNi7rXM65Iq4erkWuA24ybqFu1W6P3NXcE9xb3Gc9LDzWepzzRHv6
eO7yHPFS8mJ5NXvNelt5r/Pu9SH5BPtU+zz21fPl+3b7wX7efrv9HqzQXMFb0ekP/L38d/s/DNAOWBPw
YyAmMCCwJvBJkGlQXlBfMCU4JvhI8OsQ55DSkPuhOqHC0J4wybDosOaw+XDX8LLw0QjjiHUR1yIVIrmR
XVHYqLCopqi5lW4r96yciLaILoweXqW9KnvVldUKq1NWn46RjGHGnIhFx4bHHol9z/RnNjDn4rziauNm
WS6svaxnbEd2OXuaY8cp40zG28WXxU8l2CXsTphOdEisSJzhunCruS+SPJPqkuaT/ZMPJX9KCU9pS8Wl
xqae5Mnwknm9acpp2WmD6frphemja2zW7Fkzy/fhN2VAGasyugRU0c9Uv1BHuEU4lmmfWZP5Jiss60S2
dDYvuz9HL2d7zmSue+63a1FrWWt78lTzNuWNrXNaV78eWh+3vmeD+oaCDRMbPTYe3kTYlLzpp3yT/LL8
V5vDN3cXKBVsLBjf4rGlpVCikF84stV2a9021DbutoHt5turtn8sYhddLTYprih+X8IqufqN6TeV33za
Eb9joNSydP9OzE7ezuFdDrsOl0mX5ZaN7/bb3VFOLy8qf7UnZs+VimUVdXsJe4V7Ryt9K7uqNKp2Vr2v
Tqy+XeNc01arWLu9dn4fe9/Qfsf9rXVKdcV17w5wD9yp96jvaNBqqDiIOZh58EljWGPft4xvm5sUmoqb
PhziHRo9HHS4t9mqufmI4pHSFrhF2DJ9NProje9cv+tqNWytb6O1FR8Dx4THnn4f+/3wcZ/jPScYJ1p/
0Pyhtp3SXtQBdeR0zHYmdo52RXYNnvQ+2dNt293+o9GPh06pnqo5LXu69AzhTMGZT2dzz86dSz83cz7h
/HhPTM/9CxEXbvUG9g5c9Ll4+ZL7pQt9Tn1nL9tdPnXF5srJq4yrndcsr3X0W/S3/2TxU/uA5UDHdavr
XTesb3QPLh88M+QwdP6m681Lt7xuXbu94vbgcOjwnZHokdE77DtTd1PuvriXeW/h/sYH6AdFD6UeVjxS
fNTws+7PbaOWo6fHXMf6Hwc/vj/OGn/2S8Yv7ycKnpCfVEyqTDZPmU2dmnafvvF05dOJZ+nPFmYKf5X+
tfa5zvMffnP8rX82YnbiBf/Fp99LXsq/PPRq2aueuYC5R69TXy/MF72Rf3P4LeNt37vwd5MLWe+x7ys/
6H7o/ujz8cGn1E+f/gUDmPP8usTo0wAAAAlwSFlzAAALEwAACxMBAJqcGAAAB6hJREFUWEe9lwlQ1PcV
x1GDF40xpo09nDZtZjo217ROmnaStlPT1KQmbTPOaIKAZlITXBeVY2HBArISWNhdVljua7mXY7mX+0aC
XCrKIQp44S0WTBWNiPv6fb+MDDtsjJi2zHx0/wv7vu/3fu99f7+1IaL/GtnZ2cEZGRntSUlJl5L1+s7k
ZL3fH97buhjMt/b3jNU35wqE7ePj4+9AmAoKCqiqqorwHqk1YaRQKO5F6HT7kcQSa4lYPDwOBoPhbZ1O
Zz569ChNTEzQjRs36MKFCzQ4OEj9/f3U2NhI+/bto2Clsg0JPA0WzPy8RbDHITExcbShoYFu3ryJRxJJ
XL58mYaGhkQCnNihQ4dIpVZT4GdBNUhgxcwkZgWcC5mZmc+qVCoaGBig0dFRunXrFo2Pj9PZs2entyE1
NZVSUlLE/87bJWY3zz2bkcAyMI9jWA38qKSnp2+KiIgQq+SSj4yMUGdnJ+Xk5JBer6e0tDTC31BWVhZh
q0ilUpObu8cwxH8MFnIMq4EfFb0+ZZNWq6XDhw/TsWPHqKamRqyaxXJzcykvL4/y8/OpsLCQiouLyWg0
0rZPPjX/ZeMnr3IVOIbVwAyXyGgsXJ9pyG5ISEwai9BFTqjVmnGNWj2gDdOGqzXa8ITERFKgwdrb26m+
vl6I8RSUlJRQWVkZVVRUUHV1NdXW1lJdXZ1AskNKkl1y3obvsYZV8XSDcZkxv7g7Ld2AVeSLQFUVlVRS
VCT2MygoiFhcn5p6W6PRfMkrKy8vF7AgJ9PU1EQtLS108OBBamtrm8bNzY1kPv47If5DsGCWuFh5oely
RWUV9fX2Ug/2t/vIEerC3rYjWDPGKio6mmqxGhZobm6mAIVClJ9FW1tbqaOjQ2wL90ZPTw/1Ig7D2+Ti
spPs/7H7Pej8CDwxK4FiU4Wx1FRBQ2iqwZMnaeD4cepFkCMI2IEVYOyoGmIdKPvVq1fxEaIw9EFcfLwQ
7u7uFuPHTTk8PEynTp0S8OvKykry37v3Cwi/AVaC+RbiKP0ig7F46vr162KcvoCpXLt2jU4jQA+yh72S
CWVmoQfivDIeOX9/f/L19RUJnDlzhs6fP08XL16kS5cuCfr7j5Ofn59ZEaQKgPAasJw1LRIoKilzKiqt
pHv37tHU1BTdv3+fJicnhbtxJ5eYTNTV1WUhzqXnUVMqlRQKT3DaspV0ukiqQi/wFvCqeSS9vOTm/bqo
FAj/DjwHFrOmRQL5haUx1bWNQnjmz507d0gbHi76wJo4mxFXh0fyU2dn2hugAAHk7bNnCg44FhUdc/Rj
qfwDiP4WPA++A8S5YJFArrEwraa2QSRgNpvx1lc/XIVEHDQPxPv6+maJsyE5ODpSIMbS28c3AwJvAt5r
FuW5/wX4AVgKpg8liwQMOXl78wqKZyXAz2wwQ2gk7uRO9EAGxENDQ4lPwKioKHJ0cqLPMRXJaNKAAEUf
RH4JuNPZ+5cDO/AEwlloWjykpGe9E5eUIvZ/Cn3ASTDcE5VotCK4WR1MJQfJhISEiImIjY0l+82bKRpJ
lJWWUg323svLaxJinIBwu4dh8YAP2Gojoie5a2/fvk13794V8Al3DeXXw4Ti4uJIjZMtISGBcAegLVu3
kkwmIzgk5cF+W1EFd3d32vTRLt6CZ2bGt4bFAz4wLzY+yWTIzhXH69jYmODKlSs0PDhEhzABySg5Lhm0
bds2cnBwgLG4kFwuJ21YGBmRwAEYk6enJ0l2+2xAvGfB196GmFlvuMoVK/0DAifPnD5NI+fOiZk+eeLE
tBHxPptQ6mDYsdzLi3x8fOizwECKjYmhYoxqE+4GbLcbt+xcB/HvzzkBfGABRJXKEBWNwoTYBY/xpQKr
b4MVf37gADXDcrMyM2kfKqEMDiYdJiAN5z2fFUU4jFCRLxGHJ2DuFWB2uXqkhKo191NT0+BiF+kIbjRd
6Pw2+HwLJ4DzoA5juB9zHxUZSfrkZMrDHaAcRhWJZ1zBDkOYx29uPcC4esjXRkbF3sVrzPM/J3CNEocS
l//gjAR4pYlowlR4QC6mgstfiilxkUrNH++QOUD8FfDkzNjWsHjYLfO22+MX8G82nmBl6NBSO7vWDz60
H9ns6GjGxVOssAniJpz3vAVcdgNuOwU4jrk5d0Dc1z8gHMKvA/YA25nxrWHxEBgc0nXu3AilZWSeZ3Hb
hYsbnn/ptXc/cnZ7Wyrd2S+TeZK3t7cofQSsmfdeBTPag0aUSqU3XFy9d0CUvZ7tlo1H3PsexvSLsPBI
SX5BEdU3NF5fstSuhcWfW73mTwjCxyZfp1dtcNj++m5Xt2jJ9u29zs7OgxKJ5ISbu3u5h0wehN+vBWy5
PwHTXv9NiH+iYhJWqDTaidq6+vHly5+ut120uOanq9ewkXwXLATzgC3g2yz7+c8BOx0L8tH6MvgZeAYs
At+48gfYvPlXp/n+iqDm2Lj4f73w4kt1S+yWJa3+1e9fQ5Bp8ZkfwPMCwN9yOBn2+KfAk+ChX8G+Dps/
r1u/xd3D6+rf/v5+9YqVq6Sv/vF9Xh2XnFf8yCt5XGzeWrdeY+/glPLrtRte+M1bG1dBlPfP4uvT/xKb
N95xYLfifeVScsnnXMZvA+8pi/7fhb+CbP4D9GPXvMEwYYwAAAAASUVORK5CYII=
</value>
</data>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAEAMDAAAAEAIACoJQAAFgAAACgAAAAwAAAAYAAAAAEAIAAAAAAAACQAAMMOAADDDgAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACOMzL/jjMy/44zMv+OMzL/jjMy/44zMv9Ts2//U7Nv/1Ozb/9Ts2//U7Nv/1Oz
b/891/H/Pdfx/z3X8f891/H/Pdfx/z3X8f8ukuD/LpLg/y6S4P8ukuD/LpLg/y6S4P8vOs7/LzrO/y86
zv8vOs7/LzrO/y86zv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI8vLx+OMzL/jjMy/44zMv+OMzL/jjMy/4w4NOJTs2//U7Nv/1Oz
b/9Ts2//U7Nv/1O0cuI91/H/Pdfx/z3X8f891/H/Pdfx/z3X8f8ukuD/LpLg/y6S4P8ukuD/LpLg/y6S
4P8vOs7/LzrO/y86zv8vOs7/LzrO/y86zv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI0yMjeOMzL/jjMy/44zMv+OMzL/jjMy/4tD
N9NTs2//U7Nv/1Ozb/9Ts2//U7Nv/1K1fNM91/H/Pdfx/z3X8f891/H/Pdfx/zzW8OkukuD/LpLg/y6S
4P8ukuD/LpLg/y6R4PcvOs7/LzrO/y86zv8vOs7/LzrO/y86zuYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIwzM0+OMzL/jjMy/44z
Mv+OMzL/jjMy/4hRPcdTs2//U7Nv/1Ozb/9Ts2//U7Nv/1G4h8c91/H/Pdfx/z3X8f891/H/Pdfx/zzV
8eIukuD/LpLg/y6S4P8ukuD/LpLg/y2R4OIvOs7/LzrO/y86zv8vOs7/LzrO/y46zd4AAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI4z
MZ6OMzL/jjMy/44zMv+OMzL/jjMy/4NiRMBTs2//U7Nv/1Ozb/9Ts2//U7Nv/067mMA91/H/Pdfx/z3X
8f891/H/Pdfx/zzR78sukuD/LpLg/y6S4P8ukuD/LpLg/y2Q39cvOs7/LzrO/y86zv8vOs7/LzrO/y86
ztYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAI0zMu6OMzL/jjMy/44zMv+OMzL/jjMy/26RXMdTs2//U7Nv/1Ozb/9Ts2//U7Nv/0vB
rr491/H/Pdfx/z3X8f891/H/Pdfx/zjI7b8ukuD/LpLg/y6S4P8ukuD/LpLg/y2J3cUvOs7/LzrO/y86
zv8vOs7/LzrO/y46zq4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAjzMzP44zMv+OMzL/jjMy/44zMv+OMzL/jjIx91SwbvZTs2//U7Nv/1Oz
b/9Ts2//U7Nv/0XM1M491/H/Pdfx/z3X8f891/H/Pdfx/za66cAukuD/LpLg/y6S4P8ukuD/LpLg/y55
2b4vOs7/LzrO/y86zv8vOs7/LzrO/y46zo4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjjIxro4zMv+OMzL/jjMy/44zMv+OMzL/iUw7y1Oz
b/9Ts2//U7Nv/1Ozb/9Ts2//U7Nv7z3X8f891/H/Pdfx/z3X8f891/H/Pdfx/zCk49cukuD/LpLg/y6S
4P8ukuD/LpLg/y1p1ccvOs7/LzrO/y86zv8vOs7/LzrO/y46zWcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPNC4vjjMy/44zMv+OMzL/jjMy/44z
Mv+OMzL/dIdXwlOzb/9Ts2//U7Nv/1Ozb/9Ts2//T7qSwj3X8f891/H/Pdfx/z3X8f891/H/PNXx4i6S
4P8ukuD/LpLg/y6S4P8ukuD/LpLg/y5N0OIvOs7/LzrO/y86zv8vOs7/LzrO/y07zDcAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNMjLOjjMy/44z
Mv+OMzL/jjMy/44zMv+NNDLvWqpr6FOzb/9Ts2//U7Nv/1Ozb/9Ts2//RsnKxz3X8f891/H/Pdfx/z3X
8f891/H/OcvtwC6S4P8ukuD/LpLg/y6S4P8ukuD/LZHg4i86zv8vOs7/LzrO/y86zv8vOs7/LzrO/y4+
zw8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI4z
MHeOMzL/jjMy/44zMv+OMzL/jjMy/44zMv95flG/U7Nv/1Ozb/9Ts2//U7Nv/1Ozb/9Ssm/3PdXt9j3X
8f891/H/Pdfx/z3X8f891/H/M63myi6S4P8ukuD/LpLg/y6S4P8ukuD/Lobcwi86zv8vOs7/LzrO/y86
zv8vOs7/LjnNzgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAjDMzT44zMv+OMzL/jjMy/44zMv+OMzL/jjMy/441MulUsG72U7Nv/1Ozb/9Ts2//U7Nv/1Oz
b/9PuI3FPdfx/z3X8f891/H/Pdfx/z3X8f881/HvLpTh9i6S4P8ukuD/LpLg/y6S4P8ukuD/LXDXwi86
zv8vOs7/LzrO/y86zv8vOs7/LjrOjgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACvhoQ4jzg39o4zMv+OMzL/jjMy/44zMv+OMzL/jjMy/3SHV8JTs2//U7Nv/1Oz
b/9Ts2//U7Nv/1Ozb/9D0NzXPdfx/z3X8f891/H/Pdfx/z3X8f87zu7FLpLg/y6S4P8ukuD/LpLg/y6S
4P8ukuD/Lk3Q4i86zv8vOs7/LzrO/y86zv8vOs7/LznMTwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAALKPjmi5mpn4roaG/485OP+OMzL/jjMy/44zMv+OMzL/i0c5zlOz
b/9Ts2//U7Nv/1Ozb/9Ts2//U7Nv/067mMA91/H/Pdfx/z3X8f891/H/Pdfx/z3X8f82uOjCLpLg/y6S
4P8ukuD/LpLg/y6S4P8ujt/ULzrO/y86zv8vOs7/LzrO/y86zv8vOs7/Lj7PDwAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtJKSkrmamv+5mpr/uZqa/66Ghv+POTj/jjMy/44z
Mv+MODTiWqpr6FOzb/9Ts2//U7Nv/1Ozb/9Ts2//UrJv9z/U5+g91/H/Pdfx/z3X8f891/H/Pdfx/zzW
8OkulOH2LpLg/y6S4P8ukuD/LpLg/y6S4P8ucdfFLzrO/y86zv8vOs7/LzrO/y86zv8uOs6+AAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALKPj1+4l5fguZqa/7mamv+5mpr/uZqa/7ma
mv+uhob/jzk4/44yMfdkoGTXU7Nv/1Ozb/9Ts2//U7Nv/1Ozb/9Ts2//Tr2dvz3X8f891/H/Pdfx/z3X
8f891/H/Pdfx/za46MIukuD/LpLg/y6S4P8ukuD/LpLg/y6R4PcvQ8/2LzrO/y86zv8vOs7/LzrO/y86
zv8uOs1nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKd+fhuzkJBxtZKS2bmamv+5mpr/uZqa/7ma
mv+5mpr/uZqa/7mamv+5mpr/roaG/3GTYMdTs2//U7Nv/1Ozb/9Ts2//U7Nv/1Ozb/9SsnHpP9Tn6D3X
8f891/H/Pdfx/z3X8f891/H/PNXw1y6S4P8ukuD/LpLg/y6S4P8ukuD/LpLg/y6C278vOs7/LzrO/y86
zv8vOs7/LzrO/y85zvYuPs8PAAAAAAAAAACzjY1Ns42NTbOQkHG0kpKSt5aWzLmamv+5mpr/uZqa/7ma
mv+5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+7nZzzssOu2ZHGnf9WtHH/U7Nv/1Ozb/9Ts2//U7Nv/1Ky
b/dFzNTOPdfx/z3X8f891/H/Pdfx/z3X8f891/H/NLDmxy6S4P8ukuD/LpLg/y6S4P8ukuD/LpHg9y5K
0OgvOs7/LzrO/y86zv8vOs7/LzrO/y46zq4AAAAAAAAAAAAAAAC5mpr/uZqa/7mamv+5mpr/uZqa/7ma
mv+5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+5mpr/uZqa/72hoOerya7mos2s/6LNrP+Rxp3/VrRx/1Oz
b/9Ts2//U7Nv/0nFusA91/H/Pdfx/z3X8f891/H/Pdfx/z3X8f880vDOLpLg/y6S4P8ukuD/LpLg/y6S
4P8ukuD/LoDbyS86zv8vOs7/LzrO/y86zv8vOs7/LzrO/y85zE8AAAAAAAAAAAAAAAC5mpr/uZqa/7ma
mv+5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+5mpr/vaml2qbMrPOizaz/os2s/6LN
rP+izaz/kcad/1a0cf9Ts2//Tr2dvz3X8f891/H/Pdfx/z3X8f891/H/Pdfx/z3X8f8wpOPXLpLg/y6S
4P8ukuD/LpLg/y6S4P8ukODpLkDP9i86zv8vOs7/LzrO/y86zv8vOs7/LjnNzgAAAAAAAAAAAAAAAAAA
AAC5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+5mpr/uZqa/72jouOyw67Zos2s/6LN
rP+izaz/os2s/6LNrP+izaz/os2s/5HGnf9VuIbLPdfx/z3X8f891/H/Pdfx/z3X8f891/H/Pdfx/zjG
7L4ukuD/LpLg/y6S4P8ukuD/LpLg/y6S4P8td9i/LzrO/y86zv8vOs7/LzrO/y86zv8vOs7/LznMTwAA
AAAAAAAAAAAAAAAAAAC5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+8np7vtr6t1KLN
rP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6vUvdeK3/H3Qtfx/z3X8f891/H/Pdfx/z3X
8f891/H/O9Dvxy6S4P8ukuD/LpLg/y6S4P8ukuD/LpLg/y6Q4OsuQM/2LzrO/y86zv8vOs7/LzrO/y86
zv8uOc3OAAAAAAAAAAAAAAAAAAAAAAAAAAC5mpr/uZqa/7mamv+5mpr/uZqa/7mamv+8oJ/qvLGp07LD
rtmizaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/rNjL0Zzk9f+c5PX/ieD0/0LX
8f891/H/Pdfx/z3X8f871O/eLpTh9i6S4P8ukuD/LpLg/y6S4P8ukuD/LpLg/y1p1ccvOs7/LzrO/y86
zv8vOs7/LzrO/y86zv8vOcxPAAAAAAAAAAAAAAAAAAAAAAAAAAC+p6Tcvqek3L2vqNS6t6vSurms0a3H
reOizaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6PNrfmp3dzVnOT1/5zk
9f+c5PX/nOT1/4ng9P9C1/H/Pdfx/zzX8fAwnuLiLpLg/y6S4P8ukuD/LpLg/y6S4P8ukuD/Lo3e0C86
zv8vOs7/LzrO/y86zv8vOs7/LzrO/y45zc4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACizaz/os2s/6LN
rP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/pc6v76Xg
5d+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+J4PT/Qdbw9zKr5dQukuD/LpLg/y6S4P8ukuD/LpLg/y6S
4P8tkeDjLkPO7y86zv8vOs7/LzrO/y86zv8vOs7/LzrO/y46zy8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AACizaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6TP
rvOr2tDRnePy+Jzk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+d4/T5j8nt2TST4P8ukuD/LpLg/y6S
4P8ukuD/LpLg/y6R4PcuVdHkLzrO/y86zv8vOs7/LzrO/y86zv8vOs7/LjnOngAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACizaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LN
rP+jza35rNjI0p/j8fOc5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5/k9e+hyu7jmbvq/4Wx
5/80k+D/LpLg/y6S4P8ukuD/LpLg/y5o1cwvOs7/LzrO/y86zv8vOs7/LzrO/y86zv8uOc3uKTTJFwAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACizaz/os2s/6LNrP+izaz/os2s/6LNrP+izaz/os2s/6LN
rP+izaz/ptCx6qvXxdOh4e3qnOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/ouP15JzD
6/SZu+r/mbvq/5m76v+Fsef/NJPg/y6S4P8ukuD/LXvZxi86zv8vOs7/LzrO/y86zv8vOs7/LzrO/y86
zv8uOM1HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACizaz/os2s/6LNrP+izaz/os2s/6LN
rP+izaz/p9Cz56vZztKk4ejjnOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk
9f+l4PTZmr3q+Jm76v+Zu+r/mbvq/5m76v+Zu+r/hbHn/zST4P8uiN3MLzrO/y86zv8vOs7/LzrO/y86
zv8vOs7/LzrO/y84zG8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACp0rjcqdK43KvW
wtSr2c7Sq9rQ0aff5Nyh4e3qnOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk
9f+c5PX/nOT1/6ba8teZu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/42z5941Rc/2LzrO/y86
zv8vOs7/LzrO/y86zv8vOs7/LznOlgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AACc5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk
9f+c5PX/nOT1/5zk9f+l4fTbncPr75m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/o73p2Zqe
3/iFiNr/NT/O/y86zv8vOs7/LzrO/y86zv8uOs6+HD2+BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACc5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk
9f+c5PX/nOT1/5zk9f+c5PX/pOL13qHK7uOZu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m7
6v+ltufVmZve/5mb3v+Zm97/hYja/zU/zv8vOs7/LzrO/y46zd4uPs8PAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACc5PX/nOT1/5zk9f+c5PX/nOT1/5zk9f+c5PX/nOT1/5zk
9f+c5PX/nOT1/5zk9f+c5PX/nOT1/6Hj9Oeiz+/fmbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m7
6v+Zu+r/nL3q86Ku5N6Zm97/mZve/5mb3v+Zm97/mZve/4WI2v81P87/LjnN7iw5zCcAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACc5PX/nOT1/5zk9f+c5PX/nOT1/5zk
9f+c5PX/nOT1/5zk9f+c5PX/nOT1/6Hj9eun3vPSoszu4Jm76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m7
6v+Zu+r/mbvq/5m76v+fvurnn6fh5pmb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Fh9n3LjjNRwAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACc5PX/nOT1/5zk
9f+c5PX/nOT1/5zk9f+c5PX/nOT1/6Tk9OCn2PHSoMfs5pm76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m7
6v+Zu+r/mbvq/5m76v+Zu+r/mbvq/6O/6tqcoN/zmZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5aY
3fJ/gtlJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AACl4/XcpeP13KXj9dyl4/Xcp93z0afY8dKjze7cnMDr85m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m7
6v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+gv+rjoq7j3Jmb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb
3v+Zm97/lJbc2X6A2SUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACZu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m7
6v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/nr7q6qWz5dWZm97/mZve/5mb3v+Zm97/mZve/5mb
3v+Zm97/mZve/5mb3v+Sld2+aXDWEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m7
6v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5y96vOmuOfSmp7f+Jmb3v+Zm97/mZve/5mb
3v+Zm97/mZve/5mb3v+Zm97/mZve/4mL2pYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZu+r/mbvq/5m76v+Zu+r/mbvq/5m7
6v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+dvervprrn0pyg3/OZm97/mZve/5mb
3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+WmN34io3aZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZu+r/mbvq/5m7
6v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+avOr5pL7q1qOw5NmZm97/mZve/5mb
3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5OW3eyEh9o4AAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AACZu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+Zu+r/mbvq/5m76v+iv+rcprrn0qKu49yZm97/mZve/5mb
3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm974i43al4SLzwgAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACiv+rcor/q3KK/6tyiv+rcpL7q16a659KksuXXoKni45mb3v+Zm97/mZve/5mb
3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5SW3cWEh9gvAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb
3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Vl93MjY/cTQAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZm97/mZve/5mb3v+Zm97/mZve/5mb
3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/kJLcy42P
3E0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZm97/mZve/5mb
3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/lZfd7I2P
26aEh9o4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AACZm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mJre7JOV
3bCHitlUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACZm97/mZve/5mb3v+Zm97/mZve/5mb3v+Zm97/mZve/5mb3v+Ymt3ylJbdvo+R
23mMj9oxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVl93MlZfdzJWX3cyVl93MlJbdxZGT25KPkdpxjY/cTYSL
zwgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//8AAAAAAAP//gAAAAAAA//+AAAAA
AAD//4AAAAAAAP//gAAAAAAA//+AAAAAAAD//wAAAAAAAP//AAAAAAAA//4AAAAAAAD//gAAAAAAAP/8
AAAAAQAA//gAAAABAAD/8AAAAAEAAP/gAAAAAQAA/8AAAAADAAD/AAAAAAMAAPgAAAAAAwAAAAAAAAAH
AAAAAAAAAAcAAAAAAAAADwAAAAAAAAAPAAAAAAAAAB8AAAAAAAAAHwAAAAAAAAA/AAAAAAAAAD8AAAAA
AAAAfwAAAAAAAAB/AAAAAAAAAP8AAAAAAAAB/wAAAAAAAAP/AAAAAAAAA/8AAAAAAAAH/wAAAAAAAA//
AAAAAAAAH/8AAAAAAAA//wAAAAAAAH//AAAAAAAA//8AAAAAAAP//wAAAAAAB///AAAAAAAP//8AAAAA
AB///wAAAAAAf///AAAAAAH///8AAAAAB////wAAAAAf////AAAAAP////8AAAAH/////wAAAH//////
AAA=
</value>
</data>
</root>

777
SCrawler/MainFrame.vb Normal file
View File

@@ -0,0 +1,777 @@
Imports System.ComponentModel
Imports System.Globalization
Imports System.Threading
Imports PersonalUtilities.Forms
Imports SCrawler.API
Imports SCrawler.API.Base
Imports SCrawler.Editors
Public Class MainFrame
Private MyView As FormsView
Private ReadOnly _VideoDownloadingMode As Boolean = False
Private MyChannels As ChannelViewForm
Private _UFinit As Boolean = True
Public Sub New()
InitializeComponent()
Dim n As DateTimeFormatInfo = CultureInfo.GetCultureInfo("en-us").DateTimeFormat.Clone
n.FullDateTimePattern = "ddd MMM dd HH:mm:ss +ffff yyyy"
n.TimeSeparator = String.Empty
Twitter.DateProvider = New ADateTime(DirectCast(n.Clone, DateTimeFormatInfo)) With {.DateTimeStyle = DateTimeStyles.AssumeUniversal}
Settings = New SettingsCLS
Dim Args() As String = Environment.GetCommandLineArgs
If Args.ListExists(2) AndAlso Args(1) = "v" Then
Using f As New VideosDownloaderForm : f.ShowDialog() : End Using
_VideoDownloadingMode = True
Else
Downloader = New TDownloader
End If
End Sub
Private Sub MainFrame_Load(sender As Object, e As EventArgs) Handles Me.Load
If _VideoDownloadingMode Then GoTo FormClosingInvoker
InfoForm = New DownloadedInfoForm
AddHandler Downloader.OnJobsChange, AddressOf Downloader_UpdateJobsCount
AddHandler Downloader.OnDownloading, AddressOf Downloader_OnDownloading
AddHandler Downloader.OnDownloadCountChange, AddressOf InfoForm.Downloader_OnDownloadCountChange
Settings.LoadUsers()
MyView = New FormsView(Me)
MyView.ImportFromXML(Settings.Design)
MyView.SetMeSize()
MainProgress = New Toolbars.MyProgress(Toolbar_BOTTOM, PR_MAIN, LBL_STATUS) With {.DropCurrentProgressOnTotalChange = False}
Dim gk$
With LIST_PROFILES.Groups
gk = GetLviGroupName(Sites.Undefined, False, False, True)
.Add(New ListViewGroup(gk, gk))
gk = GetLviGroupName(Sites.Undefined, False, True, True)
.Add(New ListViewGroup(gk, gk))
gk = GetLviGroupName(Sites.Undefined, True, False, True)
.Add(New ListViewGroup(gk, gk))
For Each s In {Sites.Reddit, Sites.Twitter}
gk = GetLviGroupName(s, False, True, False)
.Add(New ListViewGroup(gk, gk))
gk = GetLviGroupName(s, False, False, False)
.Add(New ListViewGroup(gk, gk))
gk = GetLviGroupName(s, True, False, False)
.Add(New ListViewGroup(gk, gk))
Next
If Settings.Labels.Count > 0 Then Settings.Labels.ToList.ForEach(Sub(l) .Add(New ListViewGroup(l, l)))
.Add(Settings.Labels.NoLabel)
End With
With Settings
LIST_PROFILES.View = .ViewMode
SetViewButtonsCheckers(.ViewMode.Value = View.LargeIcon, .ViewMode.Value = View.SmallIcon, .ViewMode.Value = View.List)
AddHandler .Labels.NewLabelAdded, AddressOf UpdateLabelsGroups
End With
RefillList()
UpdateLabelsGroups()
SetShowButtonsCheckers(Settings.ShowingMode.Value)
CheckForReparse()
CheckVersion(False)
_UFinit = False
GoTo EndFunction
FormClosingInvoker:
Close()
EndFunction:
End Sub
Private _CloseInvoked As Boolean = False
Private Async Sub MainFrame_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
If Not _VideoDownloadingMode Then
If _CloseInvoked Then GoTo CloseResume
Dim ChannelsWorking As Func(Of Boolean) = Function() If(MyChannels?.Working, False)
If (Not Downloader.Working And Not ChannelsWorking.Invoke) OrElse
MsgBoxE({"Program still downloading something..." & vbNewLine &
"Do you really want to stop downloading and exit of program?",
"Downloading in progress"},
MsgBoxStyle.Exclamation,,,
{"Stop downloading and close", "Cancel"}) = 0 Then
If Downloader.Working Then _CloseInvoked = True : Downloader.Stop()
If ChannelsWorking.Invoke Then _CloseInvoked = True : MyChannels.Stop(False)
If _CloseInvoked Then
e.Cancel = True
Await Task.Run(Sub()
While Downloader.Working Or ChannelsWorking.Invoke : Thread.Sleep(500) : End While
End Sub)
End If
Downloader.Dispose()
InfoForm.Dispose()
If Not MyChannels Is Nothing Then MyChannels.Dispose()
If Not VideoDownloader Is Nothing Then VideoDownloader.Dispose()
MyView.Dispose(Settings.Design)
Settings.Dispose()
Else
e.Cancel = True
Exit Sub
End If
End If
If Not MyMainLOG.IsEmptyString Then SaveLogToFile()
If _CloseInvoked Then Close()
CloseResume:
End Sub
Private Sub MainFrame_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
Dim b As Boolean = True
Select Case e.KeyCode
Case Keys.Insert : BTT_ADD_USER.PerformClick()
Case Keys.Delete : DeleteSelectedUser()
Case Keys.F1 : BTT_VERSION_INFO.PerformClick()
Case Keys.F2 : DownloadVideoByURL()
Case Keys.F3 : EditSelectedUser()
Case Keys.F5 : BTT_DOWN_SELECTED.PerformClick()
Case Keys.F6 : If Settings.ShowingMode.Value = ShowingModes.All Then BTT_DOWN_ALL.PerformClick()
Case Else : b = False
End Select
If b Then e.Handled = True
End Sub
Private Sub BTT_VERSION_INFO_Click(sender As Object, e As EventArgs) Handles BTT_VERSION_INFO.Click
CheckVersion(True)
End Sub
Friend Sub RefillList()
Dim a As Action = Sub()
With LIST_PROFILES
.Items.Clear()
If Not .LargeImageList Is Nothing Then .LargeImageList.Images.Clear()
.LargeImageList = New ImageList
If Not .SmallImageList Is Nothing Then .SmallImageList.Images.Clear()
.SmallImageList = New ImageList
.LargeImageList.ColorDepth = ColorDepth.Depth32Bit
.SmallImageList.ColorDepth = ColorDepth.Depth32Bit
.LargeImageList.ImageSize = New Size(DivideWithZeroChecking(Settings.MaxLargeImageHeigh.Value, 100) * 75, Settings.MaxLargeImageHeigh.Value)
.SmallImageList.ImageSize = New Size(DivideWithZeroChecking(Settings.MaxSmallImageHeigh.Value, 100) * 75, Settings.MaxSmallImageHeigh.Value)
End With
End Sub
If LIST_PROFILES.InvokeRequired Then LIST_PROFILES.Invoke(a) Else a.Invoke
If Settings.Users.Count > 0 Then
Settings.Users.Sort()
Dim t As New List(Of Task)
For Each User As IUserData In Settings.Users
If User.FitToAddParams Then
If Settings.ViewModeIsPicture Then
t.Add(Task.Run(Sub() UserListUpdate(User, True)))
Else
UserListUpdate(User, True)
End If
End If
Next
If t.Count > 0 Then Task.WhenAll(t.ToArray) : t.Clear()
End If
End Sub
Private Sub UserListUpdate(ByVal User As IUserData, ByVal Add As Boolean)
Try
Dim a As Action
If Add Then
a = Sub()
With LIST_PROFILES
Select Case Settings.ViewMode.Value
Case View.LargeIcon : .LargeImageList.Images.Add(User.LVIKey, User.GetPicture())
Case View.SmallIcon : .SmallImageList.Images.Add(User.LVIKey, User.GetPicture())
End Select
.Items.Add(User.GetLVI(LIST_PROFILES))
End With
End Sub
Else
a = Sub()
With LIST_PROFILES
Dim i% = .Items.IndexOfKey(User.LVIKey)
Dim ImgIndx%
If i >= 0 Then
Select Case Settings.ViewMode.Value
Case View.LargeIcon
ImgIndx = .LargeImageList.Images.IndexOfKey(User.LVIKey)
If ImgIndx >= 0 Then .LargeImageList.Images(ImgIndx) = User.GetPicture()
Case View.SmallIcon
ImgIndx = .SmallImageList.Images.IndexOfKey(User.LVIKey)
If ImgIndx >= 0 Then .SmallImageList.Images(ImgIndx) = User.GetPicture()
End Select
.Items(i).Text = User.ToString
.Items(i).Group = User.GetLVIGroup(LIST_PROFILES)
End If
End With
End Sub
End If
If LIST_PROFILES.InvokeRequired Then LIST_PROFILES.Invoke(a) Else a.Invoke
Catch ex As Exception
End Try
End Sub
Private Sub UpdateLabelsGroups()
If Settings.Labels.NewLabelsExists Then
If Settings.Labels.NewLabels.Count > 0 Then
Dim ll As ListViewGroup = Nothing
Dim a As Action = Sub() LIST_PROFILES.Groups.Add(ll)
For Each l$ In Settings.Labels.NewLabels
ll = New ListViewGroup(l, l)
If Not LIST_PROFILES.Groups.Contains(ll) Then
If LIST_PROFILES.InvokeRequired Then LIST_PROFILES.Invoke(a) Else a.Invoke
End If
Next
End If
Settings.Labels.NewLabels.Clear()
End If
End Sub
Private Sub OnUsersAddedHandler(ByVal StartIndex As Integer)
If StartIndex <= Settings.Users.Count - 1 Then
For i% = StartIndex To Settings.Users.Count - 1 : UserListUpdate(Settings.Users(i), True) : Next
End If
End Sub
#Region "Toolbar buttons"
#Region "Settings"
Private Sub BTT_SETTINGS_REDDIT_Click(sender As Object, e As EventArgs) Handles BTT_SETTINGS_REDDIT.Click
Using f As New RedditEditorForm : f.ShowDialog() : End Using
End Sub
Private Sub BTT_SETTINGS_TWITTER_Click(sender As Object, e As EventArgs) Handles BTT_SETTINGS_TWITTER.Click
Using f As New TwitterEditorForm : f.ShowDialog() : End Using
End Sub
Private Sub BTT_SETTINGS_Click(sender As Object, e As EventArgs) Handles BTT_SETTINGS.Click
Dim mhl% = Settings.MaxLargeImageHeigh.Value
Dim mhs% = Settings.MaxSmallImageHeigh.Value
Using f As New GlobalSettingsForm
f.ShowDialog()
If f.DialogResult = DialogResult.OK Then
If Not Settings.MaxLargeImageHeigh = mhl Or Not Settings.MaxSmallImageHeigh = mhs Then RefillList()
End If
End Using
End Sub
#End Region
#Region "User"
Private Sub BTT_ADD_USER_Click(sender As Object, e As EventArgs) Handles BTT_ADD_USER.Click
Using f As New UserCreatorForm
f.ShowDialog()
If f.DialogResult = DialogResult.OK Then
Dim i%
If f.StartIndex >= 0 Then
OnUsersAddedHandler(f.StartIndex)
Else
i = Settings.Users.FindIndex(Function(u) u.Site = f.User.Site And u.Name = f.User.Name)
If i < 0 Then
If Not UserBanned(f.User.Name) Then
Settings.UpdateUsersList(f.User)
Settings.Users.Add(UserDataBase.GetInstance(f.User))
With Settings.Users(Settings.Users.Count - 1)
.Favorite = f.UserFavorite
.Temporary = f.UserTemporary
.ParseUserMediaOnly = f.UserMediaOnly
.ReadyForDownload = f.UserReady
.FriendlyName = f.UserFriendly
.Description = f.UserDescr
.Labels.ListAddList(f.UserLabels, LAP.ClearBeforeAdd, LAP.NotContainsOnly)
.UpdateUserInformation()
End With
UserListUpdate(Settings.Users(Settings.Users.Count - 1), True)
i = LIST_PROFILES.Items.IndexOfKey(Settings.Users(Settings.Users.Count - 1).LVIKey)
If i >= 0 Then
LIST_PROFILES.SelectedIndices.Clear()
With LIST_PROFILES.Items(i)
.Selected = True
.Focused = True
End With
LIST_PROFILES.EnsureVisible(i)
End If
Else
MsgBoxE($"User [{f.User.Name}] was not added")
End If
Else
i = LIST_PROFILES.Items.IndexOfKey(Settings.Users(i).LVIKey)
If i >= 0 Then
LIST_PROFILES.SelectedIndices.Clear()
With LIST_PROFILES.Items(i)
.Selected = True
.Focused = True
End With
LIST_PROFILES.EnsureVisible(i)
End If
MsgBoxE($"User [{f.User.Name}] already exists", MsgBoxStyle.Exclamation)
End If
End If
End If
End Using
End Sub
Private Sub BTT_EDIT_USER_Click(sender As Object, e As EventArgs) Handles BTT_EDIT_USER.Click
EditSelectedUser()
End Sub
Private Sub BTT_DELETE_USER_Click(sender As Object, e As EventArgs) Handles BTT_DELETE_USER.Click
DeleteSelectedUser()
End Sub
Private Sub BTT_REFRESH_Click(sender As Object, e As EventArgs) Handles BTT_REFRESH.Click
RefillList()
End Sub
Private Sub BTT_SHOW_INFO_Click(sender As Object, e As EventArgs) Handles BTT_SHOW_INFO.Click
ShowInfoForm(True)
End Sub
Private Overloads Sub ShowInfoForm()
ShowInfoForm(False)
End Sub
Private Overloads Sub ShowInfoForm(ByVal BringToFrontIfOpen As Boolean)
If InfoForm.Visible Then
If BringToFrontIfOpen Then InfoForm.BringToFront()
Else
InfoForm.Show()
End If
End Sub
Private Sub BTT_CHANNELS_Click(sender As Object, e As EventArgs) Handles BTT_CHANNELS.Click
If MyChannels Is Nothing Then
MyChannels = New ChannelViewForm
AddHandler MyChannels.OnUsersAdded, AddressOf OnUsersAddedHandler
End If
If MyChannels.Visible Then MyChannels.BringToFront() Else MyChannels.Show()
End Sub
#End Region
#Region "Download"
Private Sub BTT_DOWN_SELECTED_Click(sender As Object, e As EventArgs) Handles BTT_DOWN_SELECTED.Click
DownloadSelectedUser()
End Sub
Private Sub BTT_DOWN_ALL_Click(sender As Object, e As EventArgs) Handles BTT_DOWN_ALL.Click
Downloader.AddRange(Settings.Users.Where(Function(u) u.ReadyForDownload))
End Sub
Private Sub BTT_DOWN_VIDEO_Click(sender As Object, e As EventArgs) Handles BTT_DOWN_VIDEO.Click
DownloadVideoByURL()
End Sub
Private Sub BTT_DOWN_STOP_Click(sender As Object, e As EventArgs) Handles BTT_DOWN_STOP.Click
Downloader.Stop()
End Sub
#End Region
#Region "View"
Private Sub BTT_VIEW_LARGE_Click(sender As Object, e As EventArgs) Handles BTT_VIEW_LARGE.Click
LIST_PROFILES.View = View.LargeIcon
Dim b As Boolean = Not (Settings.ViewMode.Value = View.LargeIcon)
Settings.ViewMode.Value = View.LargeIcon
SetViewButtonsCheckers(True, False, False)
If b Then RefillList()
End Sub
Private Sub BTT_VIEW_SMALL_Click(sender As Object, e As EventArgs) Handles BTT_VIEW_SMALL.Click
LIST_PROFILES.View = View.SmallIcon
Dim b As Boolean = Not (Settings.ViewMode.Value = View.SmallIcon)
Settings.ViewMode.Value = View.SmallIcon
SetViewButtonsCheckers(False, True, False)
If b Then RefillList()
End Sub
Private Sub BTT_VIEW_LIST_Click(sender As Object, e As EventArgs) Handles BTT_VIEW_LIST.Click
LIST_PROFILES.View = View.List
Dim b As Boolean = Not (Settings.ViewMode.Value = View.List)
Settings.ViewMode.Value = View.List
SetViewButtonsCheckers(False, False, True)
If b Then
With LIST_PROFILES
.LargeImageList.Images.Clear()
.SmallImageList.Images.Clear()
End With
End If
End Sub
Private Sub SetViewButtonsCheckers(ByVal Large As Boolean, ByVal Small As Boolean, ByVal List As Boolean)
BTT_VIEW_LARGE.Checked = Large
BTT_VIEW_SMALL.Checked = Small
BTT_VIEW_LIST.Checked = List
End Sub
#End Region
#Region "Labels"
Private Sub BTT_SHOW_ALL_Click(sender As Object, e As EventArgs) Handles BTT_SHOW_ALL.Click
SetShowButtonsCheckers(ShowingModes.All)
End Sub
Private Sub BTT_SHOW_REGULAR_Click(sender As Object, e As EventArgs) Handles BTT_SHOW_REGULAR.Click
SetShowButtonsCheckers(ShowingModes.Regular)
End Sub
Private Sub BTT_SHOW_TEMP_Click(sender As Object, e As EventArgs) Handles BTT_SHOW_TEMP.Click
SetShowButtonsCheckers(ShowingModes.Temporary)
End Sub
Private Sub BTT_SHOW_FAV_Click(sender As Object, e As EventArgs) Handles BTT_SHOW_FAV.Click
SetShowButtonsCheckers(ShowingModes.Favorite)
End Sub
Private Sub BTT_SHOW_LABELS_Click(sender As Object, e As EventArgs) Handles BTT_SHOW_LABELS.Click
SetShowButtonsCheckers(ShowingModes.Labels)
End Sub
Private Sub BTT_SHOW_NO_LABELS_Click(sender As Object, e As EventArgs) Handles BTT_SHOW_NO_LABELS.Click
SetShowButtonsCheckers(ShowingModes.NoLabels)
End Sub
Private Sub SetShowButtonsCheckers(ByVal m As ShowingModes)
BTT_SHOW_ALL.Checked = m = ShowingModes.All
BTT_SHOW_REGULAR.Checked = m = ShowingModes.Regular
BTT_SHOW_TEMP.Checked = m = ShowingModes.Temporary
BTT_SHOW_FAV.Checked = m = ShowingModes.Favorite
BTT_SHOW_LABELS.Checked = m = ShowingModes.Labels
BTT_SHOW_NO_LABELS.Checked = m = ShowingModes.NoLabels
BTT_SELECT_LABELS.Enabled = BTT_SHOW_LABELS.Checked
If Not Settings.ShowingMode.Value = m Then
If Not m = ShowingModes.Labels Or Settings.Labels.CurrentSelection.Count > 0 Then
Settings.ShowingMode.Value = m
RefillList()
ElseIf m = ShowingModes.Labels And Settings.Labels.CurrentSelection.Count = 0 Then
OpenLabelsForm()
If Settings.Labels.CurrentSelection.Count > 0 Then
Settings.ShowingMode.Value = m
RefillList()
Else
SetShowButtonsCheckers(Settings.ShowingMode.Value)
Exit Sub
End If
ElseIf m = ShowingModes.NoLabels Then
Settings.ShowingMode.Value = m
RefillList()
End If
End If
Settings.ShowingMode.Value = m
If Not m = ShowingModes.All Then BTT_DOWN_ALL.Enabled = False
End Sub
Private Sub BTT_SELECT_LABELS_Click(sender As Object, e As EventArgs) Handles BTT_SELECT_LABELS.Click
OpenLabelsForm()
End Sub
Private Sub OpenLabelsForm()
Using f As New LabelsForm(Settings.Labels.CurrentSelection)
f.ShowDialog()
If f.DialogResult = DialogResult.OK Then
If f.LabelsList.Count > 0 Then
Settings.Labels.CurrentSelection.ListAddList(f.LabelsList, LAP.ClearBeforeAdd, LAP.NotContainsOnly)
Settings.LatestSelectedLabels.Value = Settings.Labels.CurrentSelection.ListToString(, "|")
Else
Settings.Labels.CurrentSelection.Clear()
Settings.LatestSelectedLabels.Value = String.Empty
End If
End If
End Using
End Sub
#End Region
Private Sub BTT_LOG_Click(sender As Object, e As EventArgs) Handles BTT_LOG.Click
MyMainLOG_ShowForm(Settings.Design)
End Sub
#Region "List functions"
Private _LatestSelected As Integer = -1
Private Sub LIST_PROFILES_SelectedIndexChanged(sender As Object, e As EventArgs) Handles LIST_PROFILES.SelectedIndexChanged
Dim a As Action = Sub()
If LIST_PROFILES.SelectedIndices.Count > 0 Then
_LatestSelected = LIST_PROFILES.SelectedIndices(0)
Else
_LatestSelected = -1
End If
End Sub
If LIST_PROFILES.InvokeRequired Then LIST_PROFILES.Invoke(a) Else a.Invoke
End Sub
Private Sub LIST_PROFILES_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles LIST_PROFILES.MouseDoubleClick
OpenFolder()
End Sub
#Region "Context"
Private Sub BTT_CONTEXT_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_DOWN.Click
DownloadSelectedUser()
End Sub
Private Sub BTT_CONTEXT_EDIT_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_EDIT.Click
EditSelectedUser()
End Sub
Private Sub BTT_CONTEXT_DELETE_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_DELETE.Click
DeleteSelectedUser()
End Sub
Private Sub BTT_CONTEXT_FAV_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_FAV.Click
Dim users As List(Of IUserData) = GetSelectedUserArray()
If AskForMassReplace(users, "Favorite") Then
users.ForEach(Sub(u)
u.Favorite = Not u.Favorite
u.UpdateUserInformation()
UserListUpdate(u, False)
End Sub)
End If
End Sub
Private Sub BTT_CONTEXT_TEMP_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_TEMP.Click
Dim users As List(Of IUserData) = GetSelectedUserArray()
If AskForMassReplace(users, "Temporary") Then
users.ForEach(Sub(u)
u.Temporary = Not u.Temporary
u.UpdateUserInformation()
UserListUpdate(u, False)
End Sub)
End If
End Sub
Private Sub BTT_CONTEXT_GROUPS_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_GROUPS.Click
Try
Dim users As List(Of IUserData) = GetSelectedUserArray()
If users.ListExists Then
Dim l As List(Of String) = ListAddList(Nothing, users.SelectMany(Function(u) u.Labels), LAP.NotContainsOnly)
If l.ListExists Then
Using f As New LabelsForm(l) With {.MultiUser = True}
f.ShowDialog()
If f.DialogResult = DialogResult.OK Then
Dim _lp As LAP = LAP.NotContainsOnly
If f.MultiUserClearExists Then _lp += LAP.ClearBeforeAdd
Dim lp As New ListAddParams(_lp)
users.ForEach(Sub(ByVal u As IUserData)
If u.IsCollection Then
With DirectCast(u, UserDataBind)
If .Count > 0 Then .Collections.ForEach(Sub(uu) uu.Labels.ListAddList(f.LabelsList, lp))
End With
Else
u.Labels.ListAddList(f.LabelsList, lp)
End If
u.UpdateUserInformation()
End Sub)
End If
End Using
End If
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.ShowAllMsg, ex, "[ChangeUserGroups]")
End Try
End Sub
Private Function AskForMassReplace(ByVal users As List(Of IUserData), ByVal param As String) As Boolean
Dim u$ = users.ListIfNothing.Take(20).Select(Function(uu) uu.Name).ListToString(, vbCr)
If Not u.IsEmptyString And users.ListExists(21) Then u &= vbCr & "..."
Return users.ListExists AndAlso (users.Count = 1 OrElse MsgBox($"Do you really want to change [{param}] for {users.Count} users?{vbCr}{vbCr}{u}",
MsgBoxStyle.Exclamation + MsgBoxStyle.YesNo + MsgBoxStyle.DefaultButton1,
"Users' change parameter") = MsgBoxResult.Yes)
End Function
Private Sub BTT_CHANGE_IMAGE_Click(sender As Object, e As EventArgs) Handles BTT_CHANGE_IMAGE.Click
Dim user As IUserData = GetSelectedUser()
If Not user Is Nothing Then
Dim f As SFile = SFile.SelectFiles(user.File, False, "Select new user picture", "Pictures|*.jpeg;*.jpg;*.png").FirstOrDefault
If Not f.IsEmptyString Then
user.SetPicture(f)
UserListUpdate(user, False)
End If
End If
End Sub
Private Sub BTT_CONTEXT_ADD_TO_COL_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_ADD_TO_COL.Click
If Settings.CollectionsPath.Value.IsEmptyString Then
MsgBoxE("Collection path does not set", MsgBoxStyle.Exclamation)
Else
Dim user As IUserData = GetSelectedUser()
If Not user Is Nothing Then
If user.IsCollection Then
MsgBoxE("Collection can not be added to collection!", MsgBoxStyle.Critical)
Else
Using f As New CollectionEditorForm(user.CollectionName)
f.ShowDialog()
If f.DialogResult = DialogResult.OK Then
With Settings
Dim fCol As Predicate(Of IUserData) = Function(u) u.IsCollection And u.CollectionName = f.Collection
Dim i% = .Users.FindIndex(fCol)
Dim Added As Boolean = i < 0
If i < 0 Then
.Users.Add(New UserDataBind(f.Collection))
i = .Users.Count - 1
End If
DirectCast(.Users(i), UserDataBind).Add(user)
RemoveUserFromList(user)
i = .Users.FindIndex(fCol)
If i >= 0 Then UserListUpdate(.Users(i), Added) Else RefillList()
End With
MsgBoxE($"[{user.Name}] was added to collection [{f.Collection}]")
End If
End Using
End If
End If
End If
End Sub
Private Sub BTT_CONTEXT_COL_MERGE_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_COL_MERGE.Click
Dim user As IUserData = GetSelectedUser()
If Not user Is Nothing Then
If user.IsCollection Then
If DirectCast(user, UserDataBind).DataMerging Then
MsgBoxE("Collection files are already merged")
Else
If MsgBoxE({"Do you really want to merge collection files into one folder?" & vbNewLine &
"This action is not turnable!", "Merging files"},
MsgBoxStyle.Exclamation + MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
DirectCast(user, UserDataBind).DataMerging = True
End If
End If
Else
MsgBoxE("This is not collection!", MsgBoxStyle.Exclamation)
End If
End If
End Sub
Private Sub BTT_CONTEXT_OPEN_PATH_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_OPEN_PATH.Click
OpenFolder()
End Sub
Private Sub BTT_CONTEXT_OPEN_SITE_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_OPEN_SITE.Click
Dim user As IUserData = GetSelectedUser()
If Not user Is Nothing Then user.OpenSite()
End Sub
Private Sub BTT_CONTEXT_INFO_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_INFO.Click
Dim user As IUserData = GetSelectedUser()
If Not user Is Nothing Then MsgBoxE(DirectCast(user, UserDataBase).GetUserInformation())
End Sub
Private Sub USER_CONTEXT_VisibleChanged(sender As Object, e As EventArgs) Handles USER_CONTEXT.VisibleChanged
Try
If USER_CONTEXT.Visible Then
Dim user As IUserData = GetSelectedUser()
If Not user Is Nothing AndAlso user.IsCollection Then
With DirectCast(user, UserDataBind)
BTT_CONTEXT_DOWN.DropDownItems.AddRange(.ContextDown)
BTT_CONTEXT_EDIT.DropDownItems.AddRange(.ContextEdit)
BTT_CONTEXT_DELETE.DropDownItems.AddRange(.ContextDelete)
BTT_CONTEXT_OPEN_PATH.DropDownItems.AddRange(.ContextPath)
BTT_CONTEXT_OPEN_SITE.DropDownItems.AddRange(.ContextSite)
End With
End If
Else
BTT_CONTEXT_DOWN.DropDownItems.Clear()
BTT_CONTEXT_EDIT.DropDownItems.Clear()
BTT_CONTEXT_DELETE.DropDownItems.Clear()
BTT_CONTEXT_OPEN_PATH.DropDownItems.Clear()
BTT_CONTEXT_OPEN_SITE.DropDownItems.Clear()
End If
Catch ex As Exception
End Try
End Sub
#End Region
#End Region
Private Function GetSelectedUser() As IUserData
If _LatestSelected >= 0 And _LatestSelected <= LIST_PROFILES.Items.Count - 1 Then
Dim k$ = LIST_PROFILES.Items(_LatestSelected).Name
Dim i% = Settings.Users.FindIndex(Function(u) u.LVIKey = k)
If i >= 0 Then
Return Settings.Users(i)
Else
MsgBoxE("User not found", MsgBoxStyle.Critical)
End If
End If
Return Nothing
End Function
Private Function GetSelectedUserArray() As List(Of IUserData)
Try
With LIST_PROFILES
If .SelectedIndices.Count > 0 Then
Dim l As New List(Of IUserData)
Dim k$
Dim indx%
For i% = 0 To .SelectedIndices.Count - 1
k = .Items(.SelectedIndices(i)).Name
indx = Settings.Users.FindIndex(Function(u) u.LVIKey = k)
If i >= 0 Then l.Add(Settings.Users(indx))
Next
Return l
End If
End With
Return New List(Of IUserData)
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.SendInLog + EDP.ReturnValue, ex, "[MainFrame.GetSelectedUserArray]", New List(Of IUserData))
End Try
End Function
Private Overloads Sub RemoveUserFromList(ByVal _User As IUserData)
RemoveUserFromList(LIST_PROFILES.Items.IndexOfKey(_User.LVIKey), _User.LVIKey)
End Sub
Private Overloads Sub RemoveUserFromList(ByVal _Index As Integer, ByVal Key As String)
Dim a As Action = Sub()
With LIST_PROFILES
If _Index >= 0 Then
.Items.RemoveAt(_Index)
If Settings.ViewModeIsPicture Then
Dim ImgIndx%
Select Case Settings.ViewMode.Value
Case View.LargeIcon
ImgIndx = .LargeImageList.Images.IndexOfKey(Key)
If ImgIndx >= 0 Then .LargeImageList.Images.RemoveAt(_Index)
Case View.SmallIcon
ImgIndx = .SmallImageList.Images.IndexOfKey(Key)
If ImgIndx >= 0 Then .SmallImageList.Images.RemoveAt(_Index)
End Select
End If
End If
End With
End Sub
If LIST_PROFILES.InvokeRequired Then LIST_PROFILES.Invoke(a) Else a.Invoke
End Sub
Private Sub EditSelectedUser()
Dim user As IUserData = GetSelectedUser()
If Not user Is Nothing Then
On Error Resume Next
If user.IsCollection Then
If USER_CONTEXT.Visible Then USER_CONTEXT.Hide()
Using f As New CollectionEditorForm(user.CollectionName)
f.ShowDialog()
If f.DialogResult = DialogResult.OK Then
user.CollectionName = f.Collection
UserListUpdate(user, False)
End If
End Using
Else
Using f As New UserCreatorForm(user)
f.ShowDialog()
If f.DialogResult = DialogResult.OK Then UserListUpdate(user, False)
End Using
End If
End If
End Sub
Private Sub DeleteSelectedUser()
Try
Dim users As List(Of IUserData) = GetSelectedUserArray()
If users.ListExists Then
If USER_CONTEXT.Visible Then USER_CONTEXT.Hide()
Dim ugn As Func(Of IUserData, String) = Function(u) $"{IIf(u.IsCollection, "Collection", "User")}: {u.Name}"
Dim m As New MMessage(users.Select(ugn).ListToString(, vbNewLine), "Users deleting",
{New Messaging.MsgBoxButton("Delete and ban") With {.ToolTip = "Users will be deleted and added to the blacklist"},
New Messaging.MsgBoxButton("Delete and ban with reason") With {
.ToolTip = "Users will be deleted and added to the blacklist with set a reason to delete"},
"Delete", "Cancel"}, MsgBoxStyle.Exclamation) With {.ButtonsPerRow = 2}
m.Text = $"The following users ({users.Count}) will be deleted:{vbNewLine}{m.Text}"
Dim result% = MsgBoxE(m)
If result < 3 Then
Dim removedUsers As New List(Of String)
Dim leftUsers As New List(Of String)
Dim l As New ListAddParams(LAP.NotContainsOnly)
Dim b As Boolean = False
Dim reason$ = String.Empty
If result = 1 Then reason = InputBoxE("Enter a deletion reason:", "Deletion reason")
For Each user In users
If user.Delete > 0 Then
If result < 2 Then Settings.BlackList.ListAddValue(New UserBan(user.Name, reason), l) : b = True
RemoveUserFromList(user)
removedUsers.Add(ugn(user))
Else
leftUsers.Add(ugn(user))
End If
Next
m = New MMessage(String.Empty, "Users deleting")
If removedUsers.Count = users.Count Then
If removedUsers.Count = 1 Then
m.Text = "User deleted"
Else
m.Text = "All users were deleted"
End If
ElseIf removedUsers.Count = 0 Then
m.Text = "No one user deleted!"
m.Style = MsgBoxStyle.Critical
Else
m.Text = $"The following users were deleted:{vbNewLine}{removedUsers.ListToString(, vbNewLine)}{vbNewLine.StringDup(2)}"
m.Text &= $"The following users were NOT deleted:{vbNewLine}{leftUsers.ListToString(, vbNewLine)}"
m.Style = MsgBoxStyle.Exclamation
End If
If b Then Settings.UpdateBlackList()
MsgBoxE(m)
Else
MsgBoxE("Operation canceled")
End If
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Error on trying to delete user / collection")
End Try
End Sub
Private Sub DownloadSelectedUser()
Dim users As List(Of IUserData) = GetSelectedUserArray()
If users.ListExists Then
If USER_CONTEXT.Visible Then USER_CONTEXT.Hide()
If users.Count = 1 Then
Downloader.Add(users(0))
Else
Dim uStr$ = users.Select(Function(u) u.ToString()).ListToString(, vbNewLine)
If MsgBoxE({$"You are select {users.Count} users' profiles{vbNewLine}Do you want to download all of them?{vbNewLine.StringDup(2)}" &
$"Selected users:{vbNewLine}{uStr}", "A few users selected"},
MsgBoxStyle.Question + MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
Downloader.AddRange(users)
End If
End If
End If
End Sub
Private Sub OpenFolder()
Dim user As IUserData = GetSelectedUser()
If Not user Is Nothing Then user.OpenFolder()
End Sub
#End Region
Friend Sub User_OnPictureUpdated(ByVal User As IUserData)
UserListUpdate(User, False)
End Sub
Private _LogVisible As Boolean = False
Private Sub Downloader_UpdateJobsCount(ByVal TotalCount As Integer)
Dim a As Action = Sub() LBL_JOBS_COUNT.Text = IIf(TotalCount = 0, String.Empty, $"[Jobs {TotalCount}]")
If Toolbar_BOTTOM.InvokeRequired Then Toolbar_BOTTOM.Invoke(a) Else a.Invoke
If Not _LogVisible AndAlso Not MyMainLOG.IsEmptyString Then
a = Sub() BTT_LOG.ControlChangeColor(False)
If Toolbar_TOP.InvokeRequired Then Toolbar_TOP.Invoke(a) Else a.Invoke
_LogVisible = True
End If
End Sub
Private Sub Downloader_OnDownloading(ByVal Value As Boolean)
Dim a As Action = Sub() BTT_DOWN_STOP.Enabled = Not Value
If Toolbar_TOP.InvokeRequired Then Toolbar_TOP.Invoke(a) Else a.Invoke
End Sub
End Class

350
SCrawler/MainMod.vb Normal file
View File

@@ -0,0 +1,350 @@
Imports PersonalUtilities.Functions.XML
Imports SCrawler.API
Imports SCrawler.API.Base
Friend Module MainMod
Friend Settings As SettingsCLS
Friend Const SettingsFolderName As String = "Settings"
Friend ReadOnly LinkPattern As New RegexStructure("[htps:]{0,6}[/]{0,2}(.+)", 1)
Friend ReadOnly FilesPattern As New RegexStructure("[^\./]+?\.\w+", True, False, 1)
Friend Const LVI_TempOption As String = "Temp"
Friend Const LVI_FavOption As String = "Favorite"
Friend Const CannelsLabelName As String = "Channels"
Friend Const LVI_CollectionOption As String = "Collection"
Friend Enum ViewModes As Integer
IconLarge = 0
IconSmall = 2
List = 3
End Enum
Friend Enum ShowingModes As Integer
All = 0
Regular = 20
Temporary = 50
Favorite = 100
Labels = 500
NoLabels = 1000
End Enum
Friend Downloader As TDownloader
Friend InfoForm As DownloadedInfoForm
Friend VideoDownloader As VideosDownloaderForm
Friend ReadOnly ParsersDataDateProvider As New ADateTime(ADateTime.Formats.BaseDateTime)
Friend Property MainProgress As PersonalUtilities.Forms.Toolbars.MyProgress
Friend Function GetLviGroupName(ByVal Site As Sites, ByVal Temp As Boolean, ByVal Fav As Boolean, ByVal IsCollection As Boolean) As String
Dim Opt$ = String.Empty
If Temp Then
Opt = LVI_TempOption
ElseIf Fav Then
Opt = LVI_FavOption
End If
If Not Opt.IsEmptyString Then Opt = $" ({Opt})"
If IsCollection Then
Return $"{LVI_CollectionOption}{Opt}"
Else
Return $"{Site}{Opt}"
End If
End Function
Friend Enum Sites As Integer
Undefined = 0
Reddit = 1
Twitter = 2
End Enum
Friend Structure UserInfo : Implements IComparable(Of UserInfo), IEquatable(Of UserInfo), ICloneable
Friend Const Name_Site As String = "Site"
Friend Const Name_Collection As String = "Collection"
Friend Const Name_Merged As String = "Merged"
Friend Const Name_IsChannel As String = "IsChannel"
Friend Name As String
Friend Site As Sites
Friend File As SFile
Friend Merged As Boolean
Friend IncludedInCollection As Boolean
Friend CollectionName As String
Friend IsChannel As Boolean
Friend Sub New(ByVal _Name As String, ByVal s As Sites, Optional ByVal Collection As String = Nothing,
Optional ByVal _Merged As Boolean = False)
Name = _Name
Site = s
IncludedInCollection = Not Collection.IsEmptyString
CollectionName = Collection
Merged = _Merged
UpdateUserFile()
End Sub
Friend Sub New(ByVal x As EContainer)
Me.New(x.Value,
x.Attribute(Name_Site).Value.FromXML(Of Integer)(CInt(Sites.Undefined)),
x.Attribute(Name_Collection).Value, x.Attribute(Name_Merged).Value.FromXML(Of Boolean)(False))
IsChannel = x.Attribute(Name_IsChannel).Value.FromXML(Of Boolean)(False)
End Sub
Friend Sub New(ByVal c As API.Reddit.Channel)
Name = c.Name
Site = Sites.Reddit
File = c.File
IsChannel = True
End Sub
Public Shared Widening Operator CType(ByVal x As EContainer) As UserInfo
Return New UserInfo(x)
End Operator
Public Shared Widening Operator CType(ByVal u As UserInfo) As String
Return u.Name
End Operator
Public Shared Operator =(ByVal x As UserInfo, ByVal y As UserInfo)
Return x.Equals(y)
End Operator
Public Shared Operator <>(ByVal x As UserInfo, ByVal y As UserInfo)
Return Not x.Equals(y)
End Operator
Public Overrides Function ToString() As String
Return Name
End Function
Friend Sub UpdateUserFile()
File = New SFile With {
.Separator = "\",
.Path = GetFilePathByParams(),
.Extension = "xml",
.Name = $"{UserDataBase.UserFileAppender}_{Site}_{Name}"
}
End Sub
Private Function GetFilePathByParams() As String
If Merged And IncludedInCollection Then
Return $"{Settings.CollectionsPathF.PathNoSeparator}\{CollectionName}\{SettingsFolderName}"
Else
If IncludedInCollection Then
Return $"{Settings.CollectionsPathF.PathNoSeparator}\{CollectionName}\{Site}_{Name}\{SettingsFolderName}"
Else
Return $"{Settings.Site(Site).Path.PathNoSeparator}\{Name}\{SettingsFolderName}"
End If
End If
End Function
Friend Function GetContainer() As EContainer
Return New EContainer("User", Name, {New EAttribute(Name_Site, CInt(Site)),
New EAttribute(Name_Collection, CollectionName),
New EAttribute(Name_Merged, Merged.BoolToInteger),
New EAttribute(Name_IsChannel, IsChannel.BoolToInteger)})
End Function
Friend Function CompareTo(ByVal Other As UserInfo) As Integer Implements IComparable(Of UserInfo).CompareTo
If Site = Other.Site Then
Return Name.CompareTo(Other.Name)
Else
Return CInt(Site).CompareTo(CInt(Other.Site))
End If
End Function
Friend Overloads Function Equals(ByVal Other As UserInfo) As Boolean Implements IEquatable(Of UserInfo).Equals
Return Site = Other.Site And Name = Other.Name
End Function
Public Overloads Overrides Function Equals(ByVal Obj As Object) As Boolean
Return Equals(DirectCast(Obj, UserInfo))
End Function
Friend Function Clone() As Object Implements ICloneable.Clone
Return New UserInfo With {
.Name = Name,
.Site = Site,
.File = File,
.Merged = Merged,
.IncludedInCollection = IncludedInCollection,
.CollectionName = CollectionName
}
End Function
End Structure
Friend Sub ImageHandler(ByVal User As IUserData)
ImageHandler(User, False)
ImageHandler(User, True)
End Sub
Friend Sub ImageHandler(ByVal User As IUserData, ByVal Add As Boolean)
Try
If Add Then
AddHandler User.OnPictureUpdated, AddressOf MainFrame.User_OnPictureUpdated
Else
RemoveHandler User.OnPictureUpdated, AddressOf MainFrame.User_OnPictureUpdated
End If
Catch ex As Exception
End Try
End Sub
Friend Sub CollectionHandler(ByVal [Collection] As UserDataBind)
Try
AddHandler Collection.OnCollectionSelfRemoved, AddressOf MainFrame.RefillList
Catch ex As Exception
End Try
End Sub
Friend Function GetCurrentBuffer() As String
Dim b$ = BufferText
If Not (Not b.IsEmptyString AndAlso b.Length > 4 AndAlso b.StartsWith("http")) Then b = String.Empty
Return b
End Function
Friend Function GetNewVideoURL() As String
Dim b$ = GetCurrentBuffer()
Dim URL$ = InputBox("Enter video URL:", "Download video by URL", b)
If Not URL.IsEmptyString Then Return URL Else Return String.Empty
End Function
Friend Sub DownloadVideoByURL()
If VideoDownloader Is Nothing Then VideoDownloader = New VideosDownloaderForm
If VideoDownloader.Visible Then
VideoDownloader.BringToFront()
Else
VideoDownloader.Show()
End If
End Sub
Friend Function DownloadVideoByURL(ByVal URL As String, ByVal AskForPath As Boolean, ByVal Silent As Boolean) As Boolean
Dim e As New ErrorsDescriber(Not Silent, Not Silent, True, False)
Try
If Not URL.IsEmptyString Then
Dim u As UserMedia = Nothing
If URL.Contains("twitter") Then
u = Twitter.UserData.GetVideoInfo(URL)
ElseIf URL.Contains("redgifs") Then
u = Reddit.UserData.GetVideoInfo(URL)
Else
MsgBoxE("Site of video URL does not recognized" & vbCr & "Operation canceled", MsgBoxStyle.Exclamation, e)
Return False
End If
If Not u.URL.IsEmptyString Or Not u.URL_BASE.IsEmptyString Then
Dim f As SFile = u.File
If f.Name.IsEmptyString Then f.Name = $"video_{u.Post.ID}"
If f.Extension.IsEmptyString Then f.Extension = "mp4"
If Not Settings.LatestSavingPath.IsEmptyString And
Settings.LatestSavingPath.Value.Exists(SFO.Path, False) Then f.Path = Settings.LatestSavingPath.Value
If AskForPath OrElse Not f.Exists(SFO.Path, False) Then
#Disable Warning BC40000
f = SFile.SaveAs(f, "Video file destination", True, "mp4", "Video|*.mp4|All files|*.*", EDP.ReturnValue)
#Enable Warning
End If
If Not f.IsEmptyString Then
Settings.LatestSavingPath.Value = f.PathWithSeparator
Dim dURL$
Dim FileDownloaded As Boolean = False
Using w As New Net.WebClient
For i% = 0 To 1
If i = 0 Then dURL = u.URL Else dURL = u.URL_BASE
If Not dURL.IsEmptyString Then
Try
w.DownloadFile(dURL, f)
FileDownloaded = True
Exit For
Catch wex As Exception
ErrorsDescriber.Execute(EDP.SendInLog, wex, "DownloadVideoByURL")
End Try
End If
Next
End Using
If FileDownloaded Then
MsgBoxE($"File downloaded to [{f}]",, e)
Return True
Else
MsgBoxE("File does not downloaded", MsgBoxStyle.Critical, e)
End If
Else
MsgBoxE("File destination does not pointed" & vbCr & "Operation canceled",, e)
End If
Else
MsgBoxE("File URL does not found!", MsgBoxStyle.Critical, e)
End If
Else
MsgBoxE("URL is empty", MsgBoxStyle.Exclamation, e)
End If
Return False
Catch ex As Exception
Return ErrorsDescriber.Execute(e, ex, "Downloading video by URL error", False)
End Try
End Function
Friend Sub CheckForReparse()
Try
Dim p As Func(Of IUserData, Boolean) = Function(u) u.DataForReparseExists
With Settings.Users
If .Count > 0 AndAlso .Exists(Function(u) p.Invoke(u)) Then
If MsgBox("Some users contain not parsed data" & vbCr &
"Do you want to start trying to download?",
MsgBoxStyle.Question + MsgBoxStyle.YesNo + MsgBoxStyle.DefaultButton1,
"Not parsed data found") = MsgBoxResult.Yes Then
Downloader.AddRange(.Where(p).SelectMany(Function(u) If(u.IsCollection, DirectCast(u, UserDataBind).Collections.Where(p), {u})), True)
End If
End If
End With
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendInLog, ex, "CheckForReparse")
End Try
End Sub
Friend Structure UserBan
Friend ReadOnly Name As String
Friend ReadOnly Reason As String
Friend ReadOnly Exists As Boolean
Friend Sub New(ByVal Value As String)
If Not Value.IsEmptyString Then
Dim v$() = Value.Split("|")
If v.ListExists Then
Name = v(0)
If v.Length > 1 Then Reason = v(1)
Exists = True
End If
End If
End Sub
Friend Sub New(ByVal _Name As String, ByVal _Reason As String)
Name = _Name
Reason = _Reason
Exists = True
End Sub
Public Shared Widening Operator CType(ByVal Value As String) As UserBan
Return New UserBan(Value)
End Operator
Public Shared Widening Operator CType(ByVal b As UserBan) As String
Return b.ToString
End Operator
Public Overrides Function ToString() As String
Return $"{Name}|{Reason}"
End Function
Friend Function Info() As String
If Not Reason.IsEmptyString Then
Return $"[{Name}] ({Reason})"
Else
Return Name
End If
End Function
Public Overrides Function Equals(ByVal Obj As Object) As Boolean
If Not IsNothing(Obj) Then
If TypeOf Obj Is UserBan Then
Return Name = DirectCast(Obj, UserBan).Name
Else
Return Name = New UserBan(CStr(Obj)).Name
End If
End If
Return False
End Function
End Structure
Friend Function UserBanned(ByVal UserNames() As String) As String()
If UserNames.ListExists Then
Dim i%
Dim Found As New List(Of UserBan)
For Each user In UserNames
i = Settings.BlackList.FindIndex(Function(u) u.Name = user)
If i >= 0 Then Found.Add(Settings.BlackList(i))
Next
If Found.Count = 0 Then
Return New String() {}
Else
Dim m As New MMessage With {
.Title = "Banned user found",
.Buttons = {"Remove from ban and add", "Leave in ban and add", "Skip"},
.Style = MsgBoxStyle.Exclamation,
.Exists = True
}
If Found.Count = 1 Then
m.Text = $"This user is banned:{vbNewLine}User: {Found(0).Name}"
If Not Found(0).Reason.IsEmptyString Then m.Text.StringAppendLine($"Reason: {Found(0).Reason}")
Else
m.Text = $"These users was banned:{vbNewLine.StringDup(2)}{Found.Select(Function(u) u.Info).ListToString(, vbNewLine)}"
End If
Dim r% = MsgBoxE(m)
If r = 2 Then
Return Found.Select(Function(u) u.Name).ToArray
Else
If r = 0 Then
Settings.BlackList.ListDisposeRemove(Found, False)
Settings.UpdateBlackList()
End If
End If
End If
End If
Return New String() {}
End Function
Friend Function UserBanned(ByVal UserName As String) As Boolean
Return UserBanned({UserName}).ListExists
End Function
End Module

View File

@@ -0,0 +1,38 @@
'------------------------------------------------------------------------------
' <auto-generated>
' 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.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On
Namespace My
'NOTE: This file is auto-generated; do not modify it directly. To make changes,
' or if you encounter build errors in this file, go to the Project Designer
' (go to Project Properties or double-click the My Project node in
' Solution Explorer), and make changes on the Application tab.
'
Partial Friend Class MyApplication
<Global.System.Diagnostics.DebuggerStepThroughAttribute()> _
Public Sub New()
MyBase.New(Global.Microsoft.VisualBasic.ApplicationServices.AuthenticationMode.Windows)
Me.IsSingleInstance = true
Me.EnableVisualStyles = true
Me.SaveMySettingsOnExit = false
Me.ShutDownStyle = Global.Microsoft.VisualBasic.ApplicationServices.ShutdownMode.AfterMainFormCloses
End Sub
<Global.System.Diagnostics.DebuggerStepThroughAttribute()> _
Protected Overrides Sub OnCreateMainForm()
Me.MainForm = Global.SCrawler.MainFrame
End Sub
End Class
End Namespace

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MySubMain>true</MySubMain>
<MainForm>MainFrame</MainForm>
<SingleInstance>true</SingleInstance>
<ShutdownMode>0</ShutdownMode>
<EnableVisualStyles>true</EnableVisualStyles>
<AuthenticationMode>0</AuthenticationMode>
<SaveMySettingsOnExit>false</SaveMySettingsOnExit>
</MyApplicationData>

View File

@@ -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
<Assembly: AssemblyTitle("Socials media data Crawler")>
<Assembly: AssemblyDescription("Twitter and Reddit media crawler")>
<Assembly: AssemblyCompany("AndyProgram")>
<Assembly: AssemblyProduct("SCrawler")>
<Assembly: AssemblyCopyright("Copyright © 2022")>
<Assembly: AssemblyTrademark("AndyProgram")>
<Assembly: ComVisible(False)>
'The following GUID is for the ID of the typelib if this project is exposed to COM
<Assembly: Guid("26dd544f-bcf0-40ed-b09e-464c7d73ac49")>
' 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:
' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("1.0.0.0")>
<Assembly: AssemblyFileVersion("1.0.0.0")>
<Assembly: NeutralResourcesLanguage("en")>

243
SCrawler/My Project/Resources.Designer.vb generated Normal file
View File

@@ -0,0 +1,243 @@
'------------------------------------------------------------------------------
' <auto-generated>
' 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.
' </auto-generated>
'------------------------------------------------------------------------------
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.
'''<summary>
''' A strongly-typed resource class, for looking up localized strings, etc.
'''</summary>
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0"), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
Friend Module Resources
Private resourceMan As Global.System.Resources.ResourceManager
Private resourceCulture As Global.System.Globalization.CultureInfo
'''<summary>
''' Returns the cached ResourceManager instance used by this class.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
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("SCrawler.Resources", GetType(Resources).Assembly)
resourceMan = temp
End If
Return resourceMan
End Get
End Property
'''<summary>
''' Overrides the current thread's CurrentUICulture property for all
''' resource lookups using this strongly typed resource class.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend Property Culture() As Global.System.Globalization.CultureInfo
Get
Return resourceCulture
End Get
Set
resourceCulture = value
End Set
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property DBPic_32() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("DBPic_32", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property Delete() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("Delete", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property Folder_32() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("Folder_32", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property GlobeBlue_32() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("GlobeBlue_32", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property InfoPic_32() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("InfoPic_32", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property NextPIC2() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("NextPIC2", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property PencilPic_01_16() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("PencilPic_01_16", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property PicturePic_32() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("PicturePic_32", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property Pin_32() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("Pin_32", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property PlusPIC() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("PlusPIC", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property PrevPIC2() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("PrevPIC2", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
'''</summary>
Friend ReadOnly Property Rainbow() As System.Drawing.Icon
Get
Dim obj As Object = ResourceManager.GetObject("Rainbow", resourceCulture)
Return CType(obj,System.Drawing.Icon)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
'''</summary>
Friend ReadOnly Property RedditIcon() As System.Drawing.Icon
Get
Dim obj As Object = ResourceManager.GetObject("RedditIcon", resourceCulture)
Return CType(obj,System.Drawing.Icon)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property RedditPic512() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("RedditPic512", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property Refresh() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("Refresh", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property StarPic_24() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("StarPic_24", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property StartPic_01_Green_16() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("StartPic_01_Green_16", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
'''</summary>
Friend ReadOnly Property TwitterIcon() As System.Drawing.Icon
Get
Dim obj As Object = ResourceManager.GetObject("TwitterIcon", resourceCulture)
Return CType(obj,System.Drawing.Icon)
End Get
End Property
End Module
End Namespace

View File

@@ -0,0 +1,175 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="GlobeBlue_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\GlobeBlue_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="StarPic_24" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\StarPic_24.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="PrevPIC2" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\PrevPIC2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="PicturePic_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\PicturePic_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="NextPIC2" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\NextPIC2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Folder_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\Folder_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="PencilPic_01_16" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\PencilPic_01_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="PlusPIC" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\PlusPIC.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Delete" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\Delete.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="InfoPic_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\InfoPic_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Refresh" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\Refresh.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="DBPic_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\DBPic_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="RedditIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Icons\RedditIcon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Rainbow" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Icons\Rainbow.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Pin_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\Pin_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="StartPic_01_Green_16" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\StartPic_01_Green_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="RedditPic512" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\RedditPic512.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="TwitterIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Icons\TwitterIcon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

73
SCrawler/My Project/Settings.Designer.vb generated Normal file
View File

@@ -0,0 +1,73 @@
'------------------------------------------------------------------------------
' <auto-generated>
' 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.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On
Namespace My
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0"), _
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
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
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
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
<Global.Microsoft.VisualBasic.HideModuleNameAttribute(), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute()> _
Friend Module MySettingsProperty
<Global.System.ComponentModel.Design.HelpKeywordAttribute("My.Settings")> _
Friend ReadOnly Property Settings() As Global.SCrawler.My.MySettings
Get
Return Global.SCrawler.My.MySettings.Default
End Get
End Property
End Module
End Namespace

View File

@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" UseMySettingsClassName="true">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level replace the
requestedExecutionLevel node with one of the following.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
Specifying requestedExecutionLevel element will disable file and registry virtualization.
Remove this element if your application requires this virtualization for backwards
compatibility.
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows Vista -->
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
<!-- Windows 7 -->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
<!-- Windows 8 -->
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
<!-- Windows 8.1 -->
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
<!-- Windows 10 -->
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
</application>
</compatibility>
<!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need
to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should
also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config.
Makes the application long-path aware. See https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation -->
<!--
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
-->
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
<!--
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
-->
</assembly>

BIN
SCrawler/RedditIcon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

307
SCrawler/SCrawler.vbproj Normal file
View File

@@ -0,0 +1,307 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{4A016FAD-9F07-4957-8BB2-AE86C88BA342}</ProjectGuid>
<OutputType>WinExe</OutputType>
<StartupObject>SCrawler.My.MyApplication</StartupObject>
<RootNamespace>SCrawler</RootNamespace>
<AssemblyName>SCrawler</AssemblyName>
<FileAlignment>512</FileAlignment>
<MyType>WindowsForms</MyType>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<DefineDebug>true</DefineDebug>
<DefineTrace>true</DefineTrace>
<OutputPath>bin\Debug\</OutputPath>
<DocumentationFile>
</DocumentationFile>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<DefineDebug>false</DefineDebug>
<DefineTrace>true</DefineTrace>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DocumentationFile>
</DocumentationFile>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<OptionExplicit>On</OptionExplicit>
</PropertyGroup>
<PropertyGroup>
<OptionCompare>Binary</OptionCompare>
</PropertyGroup>
<PropertyGroup>
<OptionStrict>Off</OptionStrict>
</PropertyGroup>
<PropertyGroup>
<OptionInfer>On</OptionInfer>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>Content\Icons\Rainbow.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<DefineDebug>true</DefineDebug>
<DefineTrace>true</DefineTrace>
<OutputPath>bin\x86\Debug\</OutputPath>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<DefineTrace>true</DefineTrace>
<OutputPath>bin\x86\Release\</OutputPath>
<Optimize>true</Optimize>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<DefineDebug>true</DefineDebug>
<DefineTrace>true</DefineTrace>
<OutputPath>bin\x64\Debug\</OutputPath>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<DefineTrace>true</DefineTrace>
<OutputPath>bin\x64\Release\</OutputPath>
<Optimize>true</Optimize>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>My Project\app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup>
<Import Include="Microsoft.VisualBasic" />
<Import Include="PersonalUtilities.Functions" />
<Import Include="System" />
<Import Include="System.Collections" />
<Import Include="System.Collections.Generic" />
<Import Include="System.Data" />
<Import Include="System.Drawing" />
<Import Include="System.Diagnostics" />
<Import Include="System.Windows.Forms" />
<Import Include="System.Linq" />
<Import Include="System.Xml.Linq" />
<Import Include="System.Threading.Tasks" />
</ItemGroup>
<ItemGroup>
<Compile Include="API\Base\SiteSettings.vb" />
<Compile Include="API\Base\Structures.vb" />
<Compile Include="API\Base\UserDataBase.vb" />
<Compile Include="API\Reddit\Channel.vb" />
<Compile Include="API\Reddit\ChannelsCollection.vb" />
<Compile Include="API\Reddit\Declarations.vb" />
<Compile Include="API\Reddit\M3U8.vb" />
<Compile Include="API\Reddit\UserData.vb" />
<Compile Include="API\Twitter\Declarations.vb" />
<Compile Include="API\Twitter\UserData.vb" />
<Compile Include="API\UserDataBind.vb" />
<Compile Include="Channels\ChannelViewForm.Designer.vb">
<DependentUpon>ChannelViewForm.vb</DependentUpon>
</Compile>
<Compile Include="Channels\ChannelViewForm.vb">
<SubType>Form</SubType>
</Compile>
<Compile Include="DownloadedInfoForm.Designer.vb">
<DependentUpon>DownloadedInfoForm.vb</DependentUpon>
</Compile>
<Compile Include="DownloadedInfoForm.vb">
<SubType>Form</SubType>
</Compile>
<Compile Include="Editors\CollectionEditorForm.Designer.vb">
<DependentUpon>CollectionEditorForm.vb</DependentUpon>
</Compile>
<Compile Include="Editors\CollectionEditorForm.vb">
<SubType>Form</SubType>
</Compile>
<Compile Include="Editors\GlobalSettingsForm.Designer.vb">
<DependentUpon>GlobalSettingsForm.vb</DependentUpon>
</Compile>
<Compile Include="Editors\GlobalSettingsForm.vb">
<SubType>Form</SubType>
</Compile>
<Compile Include="Editors\LabelsForm.Designer.vb">
<DependentUpon>LabelsForm.vb</DependentUpon>
</Compile>
<Compile Include="Editors\LabelsForm.vb">
<SubType>Form</SubType>
</Compile>
<Compile Include="Editors\RedditEditorForm.Designer.vb">
<DependentUpon>RedditEditorForm.vb</DependentUpon>
</Compile>
<Compile Include="Editors\RedditEditorForm.vb">
<SubType>Form</SubType>
</Compile>
<Compile Include="Editors\TwitterEditorForm.Designer.vb">
<DependentUpon>TwitterEditorForm.vb</DependentUpon>
</Compile>
<Compile Include="Editors\TwitterEditorForm.vb">
<SubType>Form</SubType>
</Compile>
<Compile Include="Editors\UserCreatorForm.Designer.vb">
<DependentUpon>UserCreatorForm.vb</DependentUpon>
</Compile>
<Compile Include="Editors\UserCreatorForm.vb">
<SubType>Form</SubType>
</Compile>
<Compile Include="Info\InfoMod.vb" />
<Compile Include="LabelsKeeper.vb" />
<Compile Include="MainFrame.vb">
<SubType>Form</SubType>
</Compile>
<Compile Include="MainFrame.Designer.vb">
<DependentUpon>MainFrame.vb</DependentUpon>
<SubType>Form</SubType>
</Compile>
<Compile Include="MainMod.vb" />
<Compile Include="My Project\AssemblyInfo.vb" />
<Compile Include="My Project\Application.Designer.vb">
<AutoGen>True</AutoGen>
<DependentUpon>Application.myapp</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="My Project\Resources.Designer.vb">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="My Project\Settings.Designer.vb">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<Compile Include="SettingsCLS.vb" />
<Compile Include="TDownloader.vb" />
<Compile Include="UserImage.vb" />
<Compile Include="VideosDownloaderForm.Designer.vb">
<DependentUpon>VideosDownloaderForm.vb</DependentUpon>
</Compile>
<Compile Include="VideosDownloaderForm.vb">
<SubType>Form</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Channels\ChannelViewForm.resx">
<DependentUpon>ChannelViewForm.vb</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="DownloadedInfoForm.resx">
<DependentUpon>DownloadedInfoForm.vb</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Editors\CollectionEditorForm.resx">
<DependentUpon>CollectionEditorForm.vb</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Editors\GlobalSettingsForm.resx">
<DependentUpon>GlobalSettingsForm.vb</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Editors\LabelsForm.resx">
<DependentUpon>LabelsForm.vb</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Editors\RedditEditorForm.resx">
<DependentUpon>RedditEditorForm.vb</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Editors\TwitterEditorForm.resx">
<DependentUpon>TwitterEditorForm.vb</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Editors\UserCreatorForm.resx">
<DependentUpon>UserCreatorForm.vb</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="MainFrame.resx">
<DependentUpon>MainFrame.vb</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="My Project\Resources.resx">
<Generator>VbMyResourcesResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.vb</LastGenOutput>
<CustomToolNamespace>My.Resources</CustomToolNamespace>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="VideosDownloaderForm.resx">
<DependentUpon>VideosDownloaderForm.vb</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="My Project\app.manifest" />
<None Include="My Project\Application.myapp">
<Generator>MyApplicationCodeGenerator</Generator>
<LastGenOutput>Application.Designer.vb</LastGenOutput>
</None>
<None Include="My Project\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<CustomToolNamespace>My</CustomToolNamespace>
<LastGenOutput>Settings.Designer.vb</LastGenOutput>
</None>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\MyUtilities\PersonalUtilities\PersonalUtilities.vbproj">
<Project>{8405896b-2685-4916-bc93-1fb514c323a9}</Project>
<Name>PersonalUtilities</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="ffmpeg.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="RedditIcon.ico" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.6.1">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.6.1 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
</Project>

243
SCrawler/SettingsCLS.vb Normal file
View File

@@ -0,0 +1,243 @@
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.XML.Base
Imports SCrawler.API
Imports SCrawler.API.Base
Friend Class SettingsCLS : Implements IDisposable
Friend ReadOnly Design As XmlFile
Private ReadOnly MyXML As XmlFile
Private ReadOnly MySites As Dictionary(Of Sites, SiteSettings)
Friend ReadOnly Property Users As List(Of IUserData)
Friend ReadOnly Property UsersList As List(Of UserInfo)
Friend Property Channels As Reddit.ChannelsCollection
Friend ReadOnly Property Labels As LabelsKeeper
Friend ReadOnly Property BlackList As List(Of UserBan)
Private ReadOnly BlackListFile As SFile = $"{SettingsFolderName}\BlackList.txt"
Private ReadOnly UsersSettingsFile As SFile = $"{SettingsFolderName}\Users.xml"
Friend Sub New()
Design = New XmlFile("Settings\Design.xml")
Design.DefaultsLoading(False)
MyXML = New XmlFile(Nothing) With {.AutoUpdateFile = True}
Users = New List(Of IUserData)
UsersList = New List(Of UserInfo)
BlackList = New List(Of UserBan)
GlobalPath = New XMLValue(Of SFile)("GlobalPath", New SFile($"{SFile.GetPath(Application.StartupPath).PathWithSeparator}Data\"), MyXML,,
XMLValue(Of SFile).ToFilePath)
MySites = New Dictionary(Of Sites, SiteSettings) From {
{Sites.Reddit, New SiteSettings(Sites.Reddit, MyXML, GlobalPath.Value)},
{Sites.Twitter, New SiteSettings(Sites.Twitter, MyXML, GlobalPath.Value)}
}
MySites(Sites.Reddit).Responser.Decoders.Add(SymbolsConverter.Converters.Unicode)
MaxLargeImageHeigh = New XMLValue(Of Integer)("MaxLargeImageHeigh", 150, MyXML)
MaxSmallImageHeigh = New XMLValue(Of Integer)("MaxSmallImageHeigh", 15, MyXML)
ViewMode = New XMLValue(Of Integer)("ViewMode", ViewModes.IconLarge, MyXML)
ShowingMode = New XMLValue(Of Integer)("ShowingMode", ShowingModes.All, MyXML)
SeparateVideoFolder = New XMLValue(Of Boolean)("SeparateVideoFolder", True, MyXML)
CollectionsPath = New XMLValue(Of String)("CollectionsPath", "Collections", MyXML)
DefaultTemporary = New XMLValue(Of Boolean)("DefaultTemporary", False, MyXML)
LatestSavingPath = New XMLValue(Of SFile)("LatestSavingPath", Nothing, MyXML,, XMLValue(Of SFile).ToFilePath)
LatestSelectedLabels = New XMLValue(Of String)("LatestSelectedLabels",, MyXML)
LatestSelectedChannel = New XMLValue(Of String)("LatestSelectedChannel",, MyXML)
ChannelsHideExistsUser = New XMLValue(Of Boolean)("ChannelsHideExistsUser", True, MyXML)
InfoViewMode = New XMLValue(Of Integer)("InfoViewMode", DownloadedInfoForm.ViewModes.Session, MyXML)
ChannelsImagesRows = New XMLValue(Of Integer)("ChannelsImagesRows", 2, MyXML)
ChannelsImagesColumns = New XMLValue(Of Integer)("ChannelsImagesColumns", 5, MyXML)
CheckUpdatesAtStart = New XMLValue(Of Boolean)("CheckUpdatesAtStart", True, MyXML)
ShowNewVersionNotification = New XMLValue(Of Boolean)("ShowNewVersionNotification", True, MyXML)
LatestVersion = New XMLValue(Of String)("LatestVersion", String.Empty, MyXML)
MyXML.DefaultsLoading(False)
If MyXML.ChangesDetected Then MyXML.UpdateData()
Labels = New LabelsKeeper
If Not LatestSelectedLabels.IsEmptyString Then Labels.CurrentSelection.ListAddList(LatestSelectedLabels.Value.StringToList(Of String, List(Of String))("|"))
If BlackListFile.Exists Then
BlackList.ListAddList(IO.File.ReadAllLines(BlackListFile), LAP.NotContainsOnly)
If BlackList.Count > 0 Then BlackList.RemoveAll(Function(b) Not b.Exists)
End If
End Sub
Friend Sub LoadUsers()
Try
Users.Clear()
If UsersSettingsFile.Exists Then
Using x As New XmlFile(UsersSettingsFile, ProtectionLevels.All, False) With {.AllowSameNames = True}
x.LoadData()
x.DefaultsLoading(False)
If x.Count > 0 Then x.ForEach(Sub(xx) UsersList.Add(xx))
End Using
Dim PNC As Func(Of UserInfo, Boolean) = Function(u) Not u.IncludedInCollection
If UsersList.Count > 0 Then
Dim cUsers As List(Of UserInfo) = UsersList.Where(Function(u) u.IncludedInCollection).ToList
If cUsers.ListExists Then
Dim d As New Dictionary(Of SFile, List(Of UserInfo))
cUsers = cUsers.ListForEachCopy(Of List(Of UserInfo))(Function(ByVal f As UserInfo, ByVal f_indx As Integer) As UserInfo
If Not d.ContainsKey(f.File.CutPath(2).Path) Then
d.Add(f.File.CutPath(2).Path, New List(Of UserInfo) From {f})
Else
d(f.File.CutPath(2).Path).Add(f)
End If
Return f
End Function, True)
Dim v%
If d.Count > 0 Then
For Each kv In d
Users.Add(New UserDataBind(kv.Value(0).CollectionName))
CollectionHandler(DirectCast(Users(Users.Count - 1), UserDataBind))
For v = 0 To kv.Value.Count - 1 : DirectCast(Users(Users.Count - 1), UserDataBind).Add(kv.Value(v), False) : Next
Next
d.Clear()
End If
End If
If UsersList.LongCount(PNC) > 0 Then UsersList.Where(PNC).ToList.ForEach(Sub(u) Users.Add(UserDataBase.GetInstance(u, False)))
End If
If Users.Count > 0 Then
Dim t As New List(Of Task)
For Each user As IUserData In Users : t.Add(Task.Run(AddressOf user.LoadUserInformation)) : Next
Task.WaitAll(t.ToArray)
t.Clear()
Dim du As List(Of UserInfo) = (From u As IUserData In Users
Where Not u.IsCollection AndAlso Not u.FileExists
Select DirectCast(u, UserDataBase).User).ToList
If Not du Is Nothing AndAlso du.Count > 0 Then du.ForEach(Sub(u) UsersList.Remove(u)) : du.Clear()
Users.ListDisposeRemoveAll(Function(ByVal u As IUserData) As Boolean
If u.IsCollection Then
With DirectCast(u, UserDataBind)
If .Count > 0 Then
For i% = .Count - 1 To 0 Step -1
If Not .Item(i).FileExists Then
.Item(i).Delete()
.Collections.RemoveAt(i)
End If
Next
End If
Return Not .FileExists
End With
Else
Return Not u.FileExists
End If
End Function)
End If
End If
If Users.Count > 0 Then
Labels.ToList.ListAddList(Users.SelectMany(Function(u) u.Labels), LAP.NotContainsOnly)
If Labels.NewLabelsExists Then Labels.Update() : Labels.NewLabels.Clear()
End If
Catch ex As Exception
End Try
End Sub
Friend Overloads Sub UpdateUsersList(ByVal u As UserInfo)
Dim i% = UsersList.IndexOf(u)
If i >= 0 Then
UsersList(i) = u
Else
UsersList.Add(u)
End If
UpdateUsersList()
End Sub
Friend Overloads Sub UpdateUsersList()
If UsersList.Count > 0 Then
Using x As New XmlFile With {.AllowSameNames = True, .Name = "Users"}
x.DefaultsLoading(False)
UsersList.ForEach(Sub(u) x.Add(u.GetContainer()))
x.Save(UsersSettingsFile)
End Using
End If
End Sub
Friend Sub UpdateBlackList()
If BlackList.Count > 0 Then
TextSaver.SaveTextToFile(BlackList.ListToString(, vbNewLine), BlackListFile, True, False, EDP.None)
Else
If BlackListFile.Exists Then BlackListFile.Delete()
End If
End Sub
Friend Overloads Function UserExists(ByVal s As Sites, ByVal UserID As String) As Boolean
Dim UserFinderBase As Predicate(Of IUserData) = Function(user) user.Site = s And user.Name = UserID
Dim UserFinder As Predicate(Of IUserData) = Function(ByVal user As IUserData) As Boolean
If user.IsCollection Then
With DirectCast(user, UserDataBind)
Return .Count > 0 AndAlso .Collections.Exists(UserFinderBase)
End With
Else
Return UserFinderBase.Invoke(user)
End If
End Function
Return Users.Count > 0 AndAlso Users.Exists(UserFinder)
End Function
Friend Overloads Function UserExists(ByVal _User As IUserData) As Boolean
Return UserExists(_User.Site, _User.Name)
End Function
Friend Overloads Function UserExists(ByVal _User As UserInfo) As Boolean
Return UserExists(_User.Site, _User.Name)
End Function
Friend ReadOnly Property Site(ByVal s As Sites) As SiteSettings
Get
Return MySites(s)
End Get
End Property
Friend ReadOnly Property GlobalPath As XMLValue(Of SFile)
Friend ReadOnly Property MaxLargeImageHeigh As XMLValue(Of Integer)
Friend ReadOnly Property MaxSmallImageHeigh As XMLValue(Of Integer)
Friend ReadOnly Property ViewMode As XMLValue(Of Integer)
Friend ReadOnly Property ViewModeIsPicture As Boolean
Get
Select Case ViewMode.Value
Case View.LargeIcon, View.SmallIcon : Return True
Case Else : Return False
End Select
End Get
End Property
Friend ReadOnly Property ShowingMode As XMLValue(Of Integer)
Friend ReadOnly Property SeparateVideoFolder As XMLValue(Of Boolean)
Friend ReadOnly Property CollectionsPath As XMLValue(Of String)
Friend ReadOnly Property CollectionsPathF As SFile
Get
If GlobalPath.IsEmptyString Then
Throw New ArgumentNullException("GlobalPath", "GlobalPath does not set")
Else
Return SFile.GetPath($"{GlobalPath.Value.PathWithSeparator}{CollectionsPath.Value}")
End If
End Get
End Property
Friend ReadOnly Property DefaultTemporary As XMLValue(Of Boolean)
Friend ReadOnly Property LatestSavingPath As XMLValue(Of SFile)
Friend ReadOnly Property LatestSelectedLabels As XMLValue(Of String)
Friend ReadOnly Property LatestSelectedChannel As XMLValue(Of String)
Friend ReadOnly Property InfoViewMode As XMLValue(Of Integer)
Friend ReadOnly Property ChannelsImagesRows As XMLValue(Of Integer)
Friend ReadOnly Property ChannelsImagesColumns As XMLValue(Of Integer)
Friend ReadOnly Property ChannelsHideExistsUser As XMLValue(Of Boolean)
Friend ReadOnly Property CheckUpdatesAtStart As XMLValue(Of Boolean)
Friend ReadOnly Property ShowNewVersionNotification As XMLValue(Of Boolean)
Friend ReadOnly Property LatestVersion As XMLValue(Of String)
#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 Channels Is Nothing Then
Channels.Dispose()
If Reddit.ChannelsCollection.ChannelsPathCache.Exists(SFO.Path, False) Then _
Reddit.ChannelsCollection.ChannelsPathCache.Delete(SFO.Path, False, False, EDP.None)
End If
For Each kv In MySites : kv.Value.Dispose() : Next
MySites.Clear()
Users.ListClearDispose
UsersList.Clear()
Design.Dispose()
MyXML.Dispose()
End If
disposedValue = True
End If
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub
Friend Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class

191
SCrawler/TDownloader.vb Normal file
View File

@@ -0,0 +1,191 @@
Imports System.Threading
Imports EOptions = PersonalUtilities.Forms.Toolbars.MyProgress.EnableOptions
Imports SCrawler.API
Imports SCrawler.API.Base
Friend Class TDownloader : Implements IDisposable
Friend Event OnJobsChange(ByVal JobsCount As Integer)
Friend Event OnDownloadCountChange()
Friend Event OnDownloading(ByVal Value As Boolean)
Private TokenSource As CancellationTokenSource
Private ReadOnly Items As List(Of IUserData)
Friend ReadOnly Property Downloaded As List(Of IUserData)
Private ReadOnly NProv As IFormatProvider
Private _Working As Boolean = False
Friend ReadOnly Property Working As Boolean
Get
Return _Working
End Get
End Property
Private DThread As Thread
Friend ReadOnly Property Count As Integer
Get
Return Items.Count
End Get
End Property
Friend Sub New()
Items = New List(Of IUserData)
Downloaded = New List(Of IUserData)
NProv = New ANumbers(ANumbers.Modes.USA) With {
.FormatMode = ANumbers.Formats.Number,
.GroupSize = 3,
.GroupSeparator = ANumbers.DefaultGroupSeparator,
.DecimalDigits = 0
}
End Sub
Friend Sub [Start]()
If Not _Working AndAlso Count > 0 AndAlso Not If(DThread?.IsAlive, False) Then
DThread = New Thread(New ThreadStart(AddressOf StartDownloading))
DThread.SetApartmentState(ApartmentState.MTA)
DThread.Start()
End If
End Sub
Private Sub StartDownloading()
Dim Token As CancellationToken
RaiseEvent OnDownloading(True)
Try
_Working = True
TokenSource = New CancellationTokenSource
Token = TokenSource.Token
MainProgress.TotalCount = 0
MainProgress.CurrentCounter = 0
Do While Count > 0
Token.ThrowIfCancellationRequested()
UpdateJobsLabel()
DownloadData(Token)
Token.ThrowIfCancellationRequested()
Thread.Sleep(500)
Loop
MainProgress.InformationTemporary = "All data downloaded"
Catch oex As OperationCanceledException When Token.IsCancellationRequested
MainProgress.InformationTemporary = "Downloading canceled"
Catch ex As Exception
MainProgress.InformationTemporary = "Downloading error"
ErrorsDescriber.Execute(EDP.SendInLog, ex, "TDownloader.Start")
Finally
_Working = False
TokenSource = Nothing
UpdateJobsLabel()
RaiseEvent OnDownloading(False)
End Try
End Sub
Friend Sub [Stop]()
If _Working Then TokenSource.Cancel()
End Sub
Private Sub UpdateJobsLabel()
RaiseEvent OnJobsChange(Count)
End Sub
Private _CurrentDownloadingTasks As Integer = 0
Private Sub DownloadData(ByVal Token As CancellationToken)
Try
If Items.Count > 0 Then
Const nf As ANumbers.Formats = ANumbers.Formats.Number
Dim t As New List(Of Task)
Dim i% = -1
For Each _Item As IUserData In Items
i += 1
If i > 4 Then Exit For
Token.ThrowIfCancellationRequested()
t.Add(Task.Run(Sub() _Item.DownloadData(Token)))
Next
If t.Count > 0 Then
_CurrentDownloadingTasks = t.Count
With MainProgress
.Enabled(EOptions.All) = True
.Information = $"Downloading {_CurrentDownloadingTasks.NumToString(nf, NProv)}/{Items.Count.NumToString(nf, NProv)} profiles' data"
.InformationTemporary = .Information
End With
Token.ThrowIfCancellationRequested()
Task.WaitAll(t.ToArray)
Dim dcc As Boolean = False
If Count > 0 And Count >= t.Count Then
For i = t.Count - 1 To 0 Step -1
With Items(i)
If Not .IsCollection AndAlso .DownloadedTotal(False) > 0 Then
If Not Downloaded.Contains(.Self) Then Downloaded.Add(GetUserFromMainCollection(.Self))
dcc = True
End If
Items.RemoveAt(i)
End With
Next
End If
If dcc Then Downloaded.RemoveAll(Function(u) u Is Nothing)
If dcc And Downloaded.Count > 0 Then RaiseEvent OnDownloadCountChange()
t.Clear()
End If
End If
Catch aoex As ArgumentOutOfRangeException
ErrorsDescriber.Execute(EDP.SendInLog, aoex, $"TDownloader.DownloadData: index out of range ({Count})")
Catch oex As OperationCanceledException When Token.IsCancellationRequested
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendInLog, ex, "TDownloader.DownloadData")
Finally
MainProgress.Enabled(EOptions.ProgressBar) = False
End Try
End Sub
Private Function GetUserFromMainCollection(ByVal User As IUserData) As IUserData
Dim uSimple As Predicate(Of IUserData) = Function(u) u.Equals(DirectCast(User, UserDataBase))
Dim uCol As Predicate(Of IUserData) = Function(ByVal u As IUserData) As Boolean
If u.IsCollection Then
Return DirectCast(u, UserDataBind).Collections.Exists(uSimple)
Else
Return False
End If
End Function
Dim uu As Predicate(Of IUserData)
If User.IncludedInCollection Then uu = uCol Else uu = uSimple
Dim i% = Settings.Users.FindIndex(uu)
If i >= 0 Then
If Settings.Users(i).IsCollection Then
With DirectCast(Settings.Users(i), UserDataBind)
i = .Collections.FindIndex(uSimple)
If i >= 0 Then Return .Collections(i)
End With
Else
Return Settings.Users(i)
End If
End If
Return Nothing
End Function
Friend Sub Add(ByVal Item As IUserData)
If Not Items.Contains(Item) Then
If Item.IsCollection Then Item.DownloadData(Nothing) Else Items.Add(Item)
UpdateJobsLabel()
If Not _Working Then Start()
End If
End Sub
Friend Sub AddRange(ByVal _Items As IEnumerable(Of IUserData), Optional ByVal ReparseOnly As Boolean = False)
If _Items.ListExists Then
For i% = 0 To _Items.Count - 1
'If i = 5 Then UpdateJobsLabel() : Start()
If ReparseOnly Then _Items(i).DownloadReparseOnly = True
If _Items(i).IsCollection Then _Items(i).DownloadData(Nothing) Else Items.Add(_Items(i))
Next
UpdateJobsLabel()
Start()
End If
End Sub
Friend Sub UserRemove(ByVal _Item As IUserData)
If Downloaded.Count > 0 AndAlso Downloaded.Contains(_Item) Then Downloaded.Remove(_Item) : RaiseEvent OnDownloadCountChange()
End Sub
#Region "IDisposable Support"
Private disposedValue As Boolean = False
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not disposedValue Then
If disposing Then
[Stop]()
Items.Clear()
Downloaded.Clear()
End If
disposedValue = True
End If
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub
Friend Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class

82
SCrawler/UserImage.vb Normal file
View File

@@ -0,0 +1,82 @@
Imports PersonalUtilities.Tools
Friend Class UserImage : Inherits ImageRenderer
Friend Const ImagePrefix As String = "UserPicture"
Friend Const ImagePostfix_Large As String = "_Large"
Friend Const ImagePostfix_Small As String = "_Small"
Private _LargeAddress As SFile
Private _SmallAddress As SFile
Friend Sub New(ByVal _ImgOriginal As SFile, ByVal Destination As SFile, Optional ByVal GenerateLargeSmallPictures As Boolean = True)
MyBase.New(_ImgOriginal)
Dim f As SFile = Destination
f.Path = f.PathWithSeparator & "Pictures"
f.Name = ImagePrefix
f.Extension = "jpg"
Address = f
_LargeAddress = Address
_LargeAddress.Name &= ImagePostfix_Large
_SmallAddress = Address
_SmallAddress.Name &= ImagePostfix_Small
If GenerateLargeSmallPictures Then
GetImage(Settings.MaxSmallImageHeigh.Value, True)
GetImage(Settings.MaxLargeImageHeigh.Value, False)
End If
End Sub
Friend Sub New(ByVal _ImgOriginal As SFile, ByVal _ImgLarge As SFile, ByVal _ImgSmall As SFile, ByVal Destination As SFile)
Me.New(_ImgOriginal, Destination, False)
Dim i As New ImageRenderer(_ImgLarge)
ResizedImages.Add(i.Size, i)
i = New ImageRenderer(_ImgSmall)
ResizedImages.Add(i.Size, i)
_LargeAddress = _ImgLarge
_SmallAddress = _ImgSmall
End Sub
''' <inheritdoc cref="GetImage(Integer, Boolean)"/>
Friend ReadOnly Property SmallSize As Size
Get
Return GetImage(Settings.MaxSmallImageHeigh.Value, True).Size
End Get
End Property
''' <inheritdoc cref="GetImage(Integer, Boolean)"/>
Friend ReadOnly Property Small As ImageRenderer
Get
Return GetImage(Settings.MaxSmallImageHeigh.Value, True)
End Get
End Property
''' <inheritdoc cref="GetImage(Integer, Boolean)"/>
Friend ReadOnly Property LargeSize As Size
Get
Return GetImage(Settings.MaxLargeImageHeigh.Value, False).Size
End Get
End Property
''' <inheritdoc cref="GetImage(Integer, Boolean)"/>
Friend ReadOnly Property Large As ImageRenderer
Get
Return GetImage(Settings.MaxLargeImageHeigh.Value, False)
End Get
End Property
''' <exception cref="ArgumentNullException"></exception>
''' <exception cref="ArgumentOutOfRangeException"></exception>
Private Shadows Function GetImage(ByVal h As Integer, ByVal IsSmall As Boolean) As ImageRenderer
With ResizedImages
If .Count > 0 Then
Dim ki% = .Keys.ToList.FindIndex(Function(s) s.Height = h)
If ki >= 0 Then Return .Item(.Keys(ki))
End If
FitToHeight(h)
If .Count = 0 Then
Throw New ArgumentOutOfRangeException("ResizedImages", "No resized images found")
Else
With .Item(.Keys(.Keys.Count - 1))
.Address = IIf(IsSmall, _SmallAddress, _LargeAddress)
.Save()
End With
Return .Item(.Keys(.Keys.Count - 1))
End If
End With
End Function
Public Overrides Sub Save()
MyBase.Save()
Small.Save(_SmallAddress)
Large.Save(_LargeAddress)
End Sub
End Class

158
SCrawler/VideosDownloaderForm.Designer.vb generated Normal file
View File

@@ -0,0 +1,158 @@
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Friend Class VideosDownloaderForm : Inherits System.Windows.Forms.Form
<System.Diagnostics.DebuggerNonUserCode()>
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
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Dim SEP_1 As System.Windows.Forms.ToolStripSeparator
Dim SEP_2 As System.Windows.Forms.ToolStripSeparator
Me.ToolbarTOP = New System.Windows.Forms.ToolStrip()
Me.BTT_ADD = New System.Windows.Forms.ToolStripButton()
Me.BTT_ADD_LIST = New System.Windows.Forms.ToolStripButton()
Me.BTT_DELETE = New System.Windows.Forms.ToolStripButton()
Me.BTT_DOWN = New System.Windows.Forms.ToolStripButton()
Me.BTT_OPEN_PATH = New System.Windows.Forms.ToolStripButton()
Me.ToolbarBOTTOM = New System.Windows.Forms.StatusStrip()
Me.PR_V = New System.Windows.Forms.ToolStripProgressBar()
Me.LBL_STATUS = New System.Windows.Forms.ToolStripStatusLabel()
Me.LIST_VIDEOS = New System.Windows.Forms.ListBox()
SEP_1 = New System.Windows.Forms.ToolStripSeparator()
SEP_2 = New System.Windows.Forms.ToolStripSeparator()
Me.ToolbarTOP.SuspendLayout()
Me.ToolbarBOTTOM.SuspendLayout()
Me.SuspendLayout()
'
'SEP_1
'
SEP_1.Name = "SEP_1"
SEP_1.Size = New System.Drawing.Size(6, 25)
'
'SEP_2
'
SEP_2.Name = "SEP_2"
SEP_2.Size = New System.Drawing.Size(6, 25)
'
'ToolbarTOP
'
Me.ToolbarTOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden
Me.ToolbarTOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_ADD, Me.BTT_ADD_LIST, Me.BTT_DELETE, SEP_1, Me.BTT_DOWN, SEP_2, Me.BTT_OPEN_PATH})
Me.ToolbarTOP.Location = New System.Drawing.Point(0, 0)
Me.ToolbarTOP.Name = "ToolbarTOP"
Me.ToolbarTOP.Size = New System.Drawing.Size(524, 25)
Me.ToolbarTOP.TabIndex = 0
'
'BTT_ADD
'
Me.BTT_ADD.AutoToolTip = False
Me.BTT_ADD.Image = Global.SCrawler.My.Resources.Resources.PlusPIC
Me.BTT_ADD.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_ADD.Name = "BTT_ADD"
Me.BTT_ADD.Size = New System.Drawing.Size(75, 22)
Me.BTT_ADD.Text = "Add (Ins)"
'
'BTT_ADD_LIST
'
Me.BTT_ADD_LIST.AutoToolTip = False
Me.BTT_ADD_LIST.Image = Global.SCrawler.My.Resources.Resources.PlusPIC
Me.BTT_ADD_LIST.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_ADD_LIST.Name = "BTT_ADD_LIST"
Me.BTT_ADD_LIST.Size = New System.Drawing.Size(67, 22)
Me.BTT_ADD_LIST.Text = "Add list"
'
'BTT_DELETE
'
Me.BTT_DELETE.AutoToolTip = False
Me.BTT_DELETE.Image = Global.SCrawler.My.Resources.Resources.Delete
Me.BTT_DELETE.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_DELETE.Name = "BTT_DELETE"
Me.BTT_DELETE.Size = New System.Drawing.Size(83, 22)
Me.BTT_DELETE.Text = "Delete (F8)"
'
'BTT_DOWN
'
Me.BTT_DOWN.AutoToolTip = False
Me.BTT_DOWN.Image = Global.SCrawler.My.Resources.Resources.StartPic_01_Green_16
Me.BTT_DOWN.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_DOWN.Name = "BTT_DOWN"
Me.BTT_DOWN.Size = New System.Drawing.Size(104, 22)
Me.BTT_DOWN.Text = "Download (F5)"
'
'BTT_OPEN_PATH
'
Me.BTT_OPEN_PATH.AutoToolTip = False
Me.BTT_OPEN_PATH.Image = Global.SCrawler.My.Resources.Resources.Folder_32
Me.BTT_OPEN_PATH.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_OPEN_PATH.Name = "BTT_OPEN_PATH"
Me.BTT_OPEN_PATH.Size = New System.Drawing.Size(120, 22)
Me.BTT_OPEN_PATH.Text = "Open saving path"
'
'ToolbarBOTTOM
'
Me.ToolbarBOTTOM.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.PR_V, Me.LBL_STATUS})
Me.ToolbarBOTTOM.Location = New System.Drawing.Point(0, 339)
Me.ToolbarBOTTOM.Name = "ToolbarBOTTOM"
Me.ToolbarBOTTOM.Size = New System.Drawing.Size(524, 22)
Me.ToolbarBOTTOM.TabIndex = 1
'
'PR_V
'
Me.PR_V.Name = "PR_V"
Me.PR_V.Size = New System.Drawing.Size(200, 16)
Me.PR_V.Visible = False
'
'LBL_STATUS
'
Me.LBL_STATUS.Name = "LBL_STATUS"
Me.LBL_STATUS.Size = New System.Drawing.Size(0, 17)
'
'LIST_VIDEOS
'
Me.LIST_VIDEOS.Dock = System.Windows.Forms.DockStyle.Fill
Me.LIST_VIDEOS.FormattingEnabled = True
Me.LIST_VIDEOS.Location = New System.Drawing.Point(0, 25)
Me.LIST_VIDEOS.Name = "LIST_VIDEOS"
Me.LIST_VIDEOS.Size = New System.Drawing.Size(524, 314)
Me.LIST_VIDEOS.TabIndex = 2
'
'VideosDownloaderForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(524, 361)
Me.Controls.Add(Me.LIST_VIDEOS)
Me.Controls.Add(Me.ToolbarBOTTOM)
Me.Controls.Add(Me.ToolbarTOP)
Me.KeyPreview = True
Me.MinimumSize = New System.Drawing.Size(540, 400)
Me.Name = "VideosDownloaderForm"
Me.ShowIcon = False
Me.Text = "Download Videos"
Me.ToolbarTOP.ResumeLayout(False)
Me.ToolbarTOP.PerformLayout()
Me.ToolbarBOTTOM.ResumeLayout(False)
Me.ToolbarBOTTOM.PerformLayout()
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Private WithEvents ToolbarTOP As ToolStrip
Private WithEvents BTT_ADD As ToolStripButton
Private WithEvents BTT_ADD_LIST As ToolStripButton
Private WithEvents BTT_DELETE As ToolStripButton
Private WithEvents ToolbarBOTTOM As StatusStrip
Private WithEvents PR_V As ToolStripProgressBar
Private WithEvents LBL_STATUS As ToolStripStatusLabel
Private WithEvents LIST_VIDEOS As ListBox
Private WithEvents BTT_DOWN As ToolStripButton
Private WithEvents BTT_OPEN_PATH As ToolStripButton
End Class

View File

@@ -0,0 +1,132 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="SEP_2.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="ToolbarTOP.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="ToolbarBOTTOM.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>124, 17</value>
</metadata>
</root>

View File

@@ -0,0 +1,127 @@
Imports System.ComponentModel
Imports PersonalUtilities.Forms
Friend Class VideosDownloaderForm
Private MyView As FormsView
Private ReadOnly MyPR As Toolbars.MyProgress
Private ReadOnly UrlList As List(Of String)
Private ReadOnly DownloadingUrlsFile As SFile = $"{SettingsFolderName}\VideosUrls.txt"
Friend Sub New()
InitializeComponent()
UrlList = New List(Of String)
MyPR = New Toolbars.MyProgress(ToolbarBOTTOM, PR_V, LBL_STATUS, "Downloading video")
If DownloadingUrlsFile.Exists Then
UrlList.ListAddList(DownloadingUrlsFile.GetText.StringToList(Of String, List(Of String))(Environment.NewLine), LAP.NotContainsOnly)
End If
End Sub
Private Sub VideosDownloaderForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
MyView = New FormsView(Me)
MyView.ImportFromXML(Settings.Design)
MyView.SetMeSize()
RefillList()
Catch ex As Exception
End Try
End Sub
Private Sub VideosDownloaderForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
e.Cancel = True
Hide()
End Sub
Private Sub VideosDownloaderForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
If Not MyView Is Nothing Then MyView.Dispose(Settings.Design)
If UrlList.Count > 0 Then
TextSaver.SaveTextToFile(UrlList.ListToString(, Environment.NewLine), DownloadingUrlsFile, True,, EDP.SendInLog)
End If
UrlList.Clear()
End Sub
Private Sub VideosDownloaderForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
Dim b As Boolean = True
Select Case e.KeyCode
Case Keys.Insert : AddVideo()
Case Keys.F5 : DownloadVideos()
Case Keys.F8 : BTT_DELETE_Click(Nothing, EventArgs.Empty)
Case Else : b = False
End Select
If b Then e.Handled = True
End Sub
Private Sub RefillList()
Try
With LIST_VIDEOS
.Items.Clear()
If UrlList.Count > 0 Then UrlList.ForEach(Sub(u) .Items.Add(u))
If .Items.Count > 0 And _LatestSelected >= 0 And _LatestSelected <= .Items.Count - 1 Then .SelectedIndex = _LatestSelected
End With
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Error on list refill")
End Try
End Sub
Private Sub BTT_ADD_Click(sender As Object, e As EventArgs) Handles BTT_ADD.Click
AddVideo()
End Sub
Private Sub AddVideo()
Dim URL$ = GetNewVideoURL()
If Not URL.IsEmptyString Then
If Not UrlList.Contains(URL) Then
UrlList.Add(URL)
RefillList()
Else
MsgBoxE("This URL already added to list")
End If
End If
End Sub
Private Sub BTT_ADD_LIST_Click(sender As Object, e As EventArgs) Handles BTT_ADD_LIST.Click
Dim l$ = InputBoxE("Enter URLs (new line as delimiter):", "URLs list", GetCurrentBuffer(),,,,,, True)
If Not l.IsEmptyString Then
Dim ub% = UrlList.Count
UrlList.ListAddList(l.StringToList(Of String, List(Of String))(Environment.NewLine))
If Not UrlList.Count = ub Then RefillList()
End If
End Sub
Private Sub BTT_DELETE_Click(sender As Object, e As EventArgs) Handles BTT_DELETE.Click
If _LatestSelected >= 0 And _LatestSelected <= UrlList.Count - 1 Then
If MsgBoxE({$"Do you really want to delete video URL:{vbCr}{UrlList(_LatestSelected)}", "Deleting URL..."},
MsgBoxStyle.Exclamation + MsgBoxStyle.YesNo).DialogResult = MsgBoxResult.Yes Then
UrlList.RemoveAt(_LatestSelected)
RefillList()
End If
Else
MsgBoxE("URL does not selected", MsgBoxStyle.Exclamation)
End If
End Sub
Private Sub BTT_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_DOWN.Click
DownloadVideos()
End Sub
Private Sub DownloadVideos()
If UrlList.Count > 0 Then
MyPR.TotalCount = UrlList.Count
MyPR.Enabled = True
Dim IsFirst As Boolean = True
For i% = UrlList.Count - 1 To 0 Step -1
If DownloadVideoByURL(UrlList(i), IsFirst, True) Then UrlList.RemoveAt(i)
MyPR.Perform()
IsFirst = False
Next
MyPR.Done()
RefillList()
MyPR.Enabled = False
Else
MsgBoxE("No one video added", MsgBoxStyle.Exclamation)
End If
End Sub
Private _LatestSelected As Integer = -1
Private Sub LIST_VIDEOS_SelectedIndexChanged(sender As Object, e As EventArgs) Handles LIST_VIDEOS.SelectedIndexChanged
_LatestSelected = LIST_VIDEOS.SelectedIndex
End Sub
Private Sub BTT_OPEN_PATH_Click(sender As Object, e As EventArgs) Handles BTT_OPEN_PATH.Click
With Settings.LatestSavingPath
If Not .Value.IsEmptyString Then
If .Value.Exists(SFO.Path, False) Then
.Value.Open(SFO.Path, EDP.ShowMainMsg)
Else
MsgBoxE($"Path [{ .Value}] does not exists!", MsgBoxStyle.Exclamation)
End If
Else
MsgBoxE("Saving path does not set!", MsgBoxStyle.Exclamation)
End If
End With
End Sub
End Class