From 1791b24f37b822c258758e371e99fbdfd14a8636 Mon Sep 17 00:00:00 2001
From: Andy <88590076+AAndyProgram@users.noreply.github.com>
Date: Tue, 7 Dec 2021 09:52:01 +0300
Subject: [PATCH] Initial commit
---
.gitattributes | 2 +
.gitignore | 392 +++++
README.md | 57 +
SCrawler.sln | 60 +
SCrawler/API/Base/SiteSettings.vb | 78 +
SCrawler/API/Base/Structures.vb | 81 +
SCrawler/API/Base/UserDataBase.vb | 961 ++++++++++++
SCrawler/API/Reddit/Channel.vb | 304 ++++
SCrawler/API/Reddit/ChannelsCollection.vb | 141 ++
SCrawler/API/Reddit/Declarations.vb | 33 +
SCrawler/API/Reddit/M3U8.vb | 100 ++
SCrawler/API/Reddit/UserData.vb | 468 ++++++
SCrawler/API/Twitter/Declarations.vb | 9 +
SCrawler/API/Twitter/UserData.vb | 264 ++++
SCrawler/API/UserDataBind.vb | 471 ++++++
SCrawler/App.config | 6 +
SCrawler/Channels/ChannelViewForm.Designer.vb | 225 +++
SCrawler/Channels/ChannelViewForm.resx | 1280 ++++++++++++++++
SCrawler/Channels/ChannelViewForm.vb | 704 +++++++++
SCrawler/Content/Icons/Rainbow.ico | Bin 0 -> 9662 bytes
SCrawler/Content/Icons/RedditIcon.ico | Bin 0 -> 67646 bytes
SCrawler/Content/Icons/TwitterIcon.ico | Bin 0 -> 481 bytes
SCrawler/Content/Icons/UsersIcon.ico | Bin 0 -> 25214 bytes
SCrawler/Content/Pictures/Cloud_01_16.png | Bin 0 -> 384 bytes
SCrawler/Content/Pictures/DBPic_32.png | Bin 0 -> 3006 bytes
SCrawler/Content/Pictures/Delete.png | Bin 0 -> 1558 bytes
SCrawler/Content/Pictures/Folder_32.png | Bin 0 -> 3831 bytes
SCrawler/Content/Pictures/GlobeBlue_32.png | Bin 0 -> 929 bytes
SCrawler/Content/Pictures/InfoPic_32.png | Bin 0 -> 368 bytes
SCrawler/Content/Pictures/NextPIC2.png | Bin 0 -> 434 bytes
SCrawler/Content/Pictures/Ok.png | Bin 0 -> 1383 bytes
SCrawler/Content/Pictures/PencilPic_01_16.png | Bin 0 -> 3233 bytes
SCrawler/Content/Pictures/PicturePic_32.png | Bin 0 -> 4102 bytes
SCrawler/Content/Pictures/Pin_32.png | Bin 0 -> 4758 bytes
SCrawler/Content/Pictures/PlusPIC.png | Bin 0 -> 888 bytes
SCrawler/Content/Pictures/PrevPIC2.png | Bin 0 -> 423 bytes
SCrawler/Content/Pictures/RedditPic512.png | Bin 0 -> 22323 bytes
SCrawler/Content/Pictures/Refresh.png | Bin 0 -> 1139 bytes
SCrawler/Content/Pictures/StarPic_24.png | Bin 0 -> 1164 bytes
.../Content/Pictures/StartPic_01_Green_16.png | Bin 0 -> 373 bytes
SCrawler/DownloadedInfoForm.Designer.vb | 115 ++
SCrawler/DownloadedInfoForm.resx | 142 ++
SCrawler/DownloadedInfoForm.vb | 124 ++
.../Editors/CollectionEditorForm.Designer.vb | 87 ++
SCrawler/Editors/CollectionEditorForm.resx | 233 +++
SCrawler/Editors/CollectionEditorForm.vb | 81 +
.../Editors/GlobalSettingsForm.Designer.vb | 290 ++++
SCrawler/Editors/GlobalSettingsForm.resx | 168 +++
SCrawler/Editors/GlobalSettingsForm.vb | 65 +
SCrawler/Editors/LabelsForm.Designer.vb | 92 ++
SCrawler/Editors/LabelsForm.resx | 241 +++
SCrawler/Editors/LabelsForm.vb | 97 ++
SCrawler/Editors/RedditEditorForm.Designer.vb | 134 ++
SCrawler/Editors/RedditEditorForm.resx | 1341 +++++++++++++++++
SCrawler/Editors/RedditEditorForm.vb | 68 +
.../Editors/TwitterEditorForm.Designer.vb | 180 +++
SCrawler/Editors/TwitterEditorForm.resx | 238 +++
SCrawler/Editors/TwitterEditorForm.vb | 84 ++
SCrawler/Editors/UserCreatorForm.Designer.vb | 378 +++++
SCrawler/Editors/UserCreatorForm.resx | 591 ++++++++
SCrawler/Editors/UserCreatorForm.vb | 358 +++++
SCrawler/LabelsKeeper.vb | 103 ++
SCrawler/MainFrame.Designer.vb | 578 +++++++
SCrawler/MainFrame.resx | 478 ++++++
SCrawler/MainFrame.vb | 777 ++++++++++
SCrawler/MainMod.vb | 350 +++++
SCrawler/My Project/Application.Designer.vb | 38 +
SCrawler/My Project/Application.myapp | 10 +
SCrawler/My Project/AssemblyInfo.vb | 37 +
SCrawler/My Project/Resources.Designer.vb | 243 +++
SCrawler/My Project/Resources.resx | 175 +++
SCrawler/My Project/Settings.Designer.vb | 73 +
SCrawler/My Project/Settings.settings | 7 +
SCrawler/My Project/app.manifest | 79 +
SCrawler/RedditIcon.ico | Bin 0 -> 67646 bytes
SCrawler/SCrawler.vbproj | 307 ++++
SCrawler/SettingsCLS.vb | 243 +++
SCrawler/TDownloader.vb | 191 +++
SCrawler/UserImage.vb | 82 +
SCrawler/VideosDownloaderForm.Designer.vb | 158 ++
SCrawler/VideosDownloaderForm.resx | 132 ++
SCrawler/VideosDownloaderForm.vb | 127 ++
82 files changed, 14931 insertions(+)
create mode 100644 .gitattributes
create mode 100644 .gitignore
create mode 100644 README.md
create mode 100644 SCrawler.sln
create mode 100644 SCrawler/API/Base/SiteSettings.vb
create mode 100644 SCrawler/API/Base/Structures.vb
create mode 100644 SCrawler/API/Base/UserDataBase.vb
create mode 100644 SCrawler/API/Reddit/Channel.vb
create mode 100644 SCrawler/API/Reddit/ChannelsCollection.vb
create mode 100644 SCrawler/API/Reddit/Declarations.vb
create mode 100644 SCrawler/API/Reddit/M3U8.vb
create mode 100644 SCrawler/API/Reddit/UserData.vb
create mode 100644 SCrawler/API/Twitter/Declarations.vb
create mode 100644 SCrawler/API/Twitter/UserData.vb
create mode 100644 SCrawler/API/UserDataBind.vb
create mode 100644 SCrawler/App.config
create mode 100644 SCrawler/Channels/ChannelViewForm.Designer.vb
create mode 100644 SCrawler/Channels/ChannelViewForm.resx
create mode 100644 SCrawler/Channels/ChannelViewForm.vb
create mode 100644 SCrawler/Content/Icons/Rainbow.ico
create mode 100644 SCrawler/Content/Icons/RedditIcon.ico
create mode 100644 SCrawler/Content/Icons/TwitterIcon.ico
create mode 100644 SCrawler/Content/Icons/UsersIcon.ico
create mode 100644 SCrawler/Content/Pictures/Cloud_01_16.png
create mode 100644 SCrawler/Content/Pictures/DBPic_32.png
create mode 100644 SCrawler/Content/Pictures/Delete.png
create mode 100644 SCrawler/Content/Pictures/Folder_32.png
create mode 100644 SCrawler/Content/Pictures/GlobeBlue_32.png
create mode 100644 SCrawler/Content/Pictures/InfoPic_32.png
create mode 100644 SCrawler/Content/Pictures/NextPIC2.png
create mode 100644 SCrawler/Content/Pictures/Ok.png
create mode 100644 SCrawler/Content/Pictures/PencilPic_01_16.png
create mode 100644 SCrawler/Content/Pictures/PicturePic_32.png
create mode 100644 SCrawler/Content/Pictures/Pin_32.png
create mode 100644 SCrawler/Content/Pictures/PlusPIC.png
create mode 100644 SCrawler/Content/Pictures/PrevPIC2.png
create mode 100644 SCrawler/Content/Pictures/RedditPic512.png
create mode 100644 SCrawler/Content/Pictures/Refresh.png
create mode 100644 SCrawler/Content/Pictures/StarPic_24.png
create mode 100644 SCrawler/Content/Pictures/StartPic_01_Green_16.png
create mode 100644 SCrawler/DownloadedInfoForm.Designer.vb
create mode 100644 SCrawler/DownloadedInfoForm.resx
create mode 100644 SCrawler/DownloadedInfoForm.vb
create mode 100644 SCrawler/Editors/CollectionEditorForm.Designer.vb
create mode 100644 SCrawler/Editors/CollectionEditorForm.resx
create mode 100644 SCrawler/Editors/CollectionEditorForm.vb
create mode 100644 SCrawler/Editors/GlobalSettingsForm.Designer.vb
create mode 100644 SCrawler/Editors/GlobalSettingsForm.resx
create mode 100644 SCrawler/Editors/GlobalSettingsForm.vb
create mode 100644 SCrawler/Editors/LabelsForm.Designer.vb
create mode 100644 SCrawler/Editors/LabelsForm.resx
create mode 100644 SCrawler/Editors/LabelsForm.vb
create mode 100644 SCrawler/Editors/RedditEditorForm.Designer.vb
create mode 100644 SCrawler/Editors/RedditEditorForm.resx
create mode 100644 SCrawler/Editors/RedditEditorForm.vb
create mode 100644 SCrawler/Editors/TwitterEditorForm.Designer.vb
create mode 100644 SCrawler/Editors/TwitterEditorForm.resx
create mode 100644 SCrawler/Editors/TwitterEditorForm.vb
create mode 100644 SCrawler/Editors/UserCreatorForm.Designer.vb
create mode 100644 SCrawler/Editors/UserCreatorForm.resx
create mode 100644 SCrawler/Editors/UserCreatorForm.vb
create mode 100644 SCrawler/LabelsKeeper.vb
create mode 100644 SCrawler/MainFrame.Designer.vb
create mode 100644 SCrawler/MainFrame.resx
create mode 100644 SCrawler/MainFrame.vb
create mode 100644 SCrawler/MainMod.vb
create mode 100644 SCrawler/My Project/Application.Designer.vb
create mode 100644 SCrawler/My Project/Application.myapp
create mode 100644 SCrawler/My Project/AssemblyInfo.vb
create mode 100644 SCrawler/My Project/Resources.Designer.vb
create mode 100644 SCrawler/My Project/Resources.resx
create mode 100644 SCrawler/My Project/Settings.Designer.vb
create mode 100644 SCrawler/My Project/Settings.settings
create mode 100644 SCrawler/My Project/app.manifest
create mode 100644 SCrawler/RedditIcon.ico
create mode 100644 SCrawler/SCrawler.vbproj
create mode 100644 SCrawler/SettingsCLS.vb
create mode 100644 SCrawler/TDownloader.vb
create mode 100644 SCrawler/UserImage.vb
create mode 100644 SCrawler/VideosDownloaderForm.Designer.vb
create mode 100644 SCrawler/VideosDownloaderForm.resx
create mode 100644 SCrawler/VideosDownloaderForm.vb
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..dfe0770
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7ea61cf
--- /dev/null
+++ b/.gitignore
@@ -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
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8f43622
--- /dev/null
+++ b/README.md
@@ -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 :)
+
+[](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```
\ No newline at end of file
diff --git a/SCrawler.sln b/SCrawler.sln
new file mode 100644
index 0000000..6271746
--- /dev/null
+++ b/SCrawler.sln
@@ -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
diff --git a/SCrawler/API/Base/SiteSettings.vb b/SCrawler/API/Base/SiteSettings.vb
new file mode 100644
index 0000000..90d3435
--- /dev/null
+++ b/SCrawler/API/Base/SiteSettings.vb
@@ -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
\ No newline at end of file
diff --git a/SCrawler/API/Base/Structures.vb b/SCrawler/API/Base/Structures.vb
new file mode 100644
index 0000000..63e77cb
--- /dev/null
+++ b/SCrawler/API/Base/Structures.vb
@@ -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)
+ ''' Post ID
+ 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
\ No newline at end of file
diff --git a/SCrawler/API/Base/UserDataBase.vb b/SCrawler/API/Base/UserDataBase.vb
new file mode 100644
index 0000000..84e3e26
--- /dev/null
+++ b/SCrawler/API/Base/UserDataBase.vb
@@ -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
+ ''' By using this constructor you must set UserName and MyFile manually
+ 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
+ '''
+ 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()
+ '''
+ ''' 0 - Nothing removed
+ ''' 1 - User removed
+ ''' 2 - Collection removed
+ ''' 3 - Collection splitted
+ '''
+ 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
\ No newline at end of file
diff --git a/SCrawler/API/Reddit/Channel.vb b/SCrawler/API/Reddit/Channel.vb
new file mode 100644
index 0000000..7d66fce
--- /dev/null
+++ b/SCrawler/API/Reddit/Channel.vb
@@ -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
\ No newline at end of file
diff --git a/SCrawler/API/Reddit/ChannelsCollection.vb b/SCrawler/API/Reddit/ChannelsCollection.vb
new file mode 100644
index 0000000..d2fe219
--- /dev/null
+++ b/SCrawler/API/Reddit/ChannelsCollection.vb
@@ -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
+ 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
+ '''
+ 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
\ No newline at end of file
diff --git a/SCrawler/API/Reddit/Declarations.vb b/SCrawler/API/Reddit/Declarations.vb
new file mode 100644
index 0000000..7016975
--- /dev/null
+++ b/SCrawler/API/Reddit/Declarations.vb
@@ -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
+ '''
+ 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
+ '''
+ 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
\ No newline at end of file
diff --git a/SCrawler/API/Reddit/M3U8.vb b/SCrawler/API/Reddit/M3U8.vb
new file mode 100644
index 0000000..71d60d8
--- /dev/null
+++ b/SCrawler/API/Reddit/M3U8.vb
@@ -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
\ No newline at end of file
diff --git a/SCrawler/API/Reddit/UserData.vb b/SCrawler/API/Reddit/UserData.vb
new file mode 100644
index 0000000..1bba813
--- /dev/null
+++ b/SCrawler/API/Reddit/UserData.vb
@@ -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"
+ ''' Video downloader initializer
+ Private Sub New()
+ End Sub
+ ''' Default initializer
+ 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
\ No newline at end of file
diff --git a/SCrawler/API/Twitter/Declarations.vb b/SCrawler/API/Twitter/Declarations.vb
new file mode 100644
index 0000000..b254f7c
--- /dev/null
+++ b/SCrawler/API/Twitter/Declarations.vb
@@ -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
\ No newline at end of file
diff --git a/SCrawler/API/Twitter/UserData.vb b/SCrawler/API/Twitter/UserData.vb
new file mode 100644
index 0000000..5d5e3f9
--- /dev/null
+++ b/SCrawler/API/Twitter/UserData.vb
@@ -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
\ No newline at end of file
diff --git a/SCrawler/API/UserDataBind.vb b/SCrawler/API/UserDataBind.vb
new file mode 100644
index 0000000..3efbd3f
--- /dev/null
+++ b/SCrawler/API/UserDataBind.vb
@@ -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
+ ''' FOR SETTINGS START LOADING ONLY
+ Friend Overloads Sub Add(ByVal u As UserInfo, Optional ByVal _LoadData As Boolean = True)
+ Select Case u.Site
+ Case Sites.Reddit : Collections.Add(New Reddit.UserData(u, _LoadData))
+ Case Sites.Twitter : Collections.Add(New Twitter.UserData(u, _LoadData))
+ Case Else : Exit Sub
+ End Select
+ With DirectCast(Collections(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
\ No newline at end of file
diff --git a/SCrawler/App.config b/SCrawler/App.config
new file mode 100644
index 0000000..5534e28
--- /dev/null
+++ b/SCrawler/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SCrawler/Channels/ChannelViewForm.Designer.vb b/SCrawler/Channels/ChannelViewForm.Designer.vb
new file mode 100644
index 0000000..f2a31ba
--- /dev/null
+++ b/SCrawler/Channels/ChannelViewForm.Designer.vb
@@ -0,0 +1,225 @@
+
+Partial Friend Class ChannelViewForm : Inherits System.Windows.Forms.Form
+
+ Protected Overrides Sub Dispose(ByVal disposing As Boolean)
+ Try
+ If disposing AndAlso components IsNot Nothing Then
+ components.Dispose()
+ End If
+ Finally
+ MyBase.Dispose(disposing)
+ End Try
+ End Sub
+ Private components As System.ComponentModel.IContainer
+
+ Private Sub InitializeComponent()
+ Me.components = New System.ComponentModel.Container()
+ Dim 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
\ No newline at end of file
diff --git a/SCrawler/Channels/ChannelViewForm.resx b/SCrawler/Channels/ChannelViewForm.resx
new file mode 100644
index 0000000..0eaaeec
--- /dev/null
+++ b/SCrawler/Channels/ChannelViewForm.resx
@@ -0,0 +1,1280 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ 241, 17
+
+
+ 17, 17
+
+
+ 124, 17
+
+
+ 342, 17
+
+
+ False
+
+
+
+
+ AAABAAEAgIAAAAEAIAAoCAEAFgAAACgAAACAAAAAAAEAAAEAIAAAAAAAAAABAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAEb/AABG/wMARv8PAEX/IgBF/0AARf9fAEX/fQBF/5wARf+6AEX/zQBF
+ /90ARf/rAEX/8wBF//gARf/8AEX//ABF//gARf/zAEX/6wBF/90ARf/NAEX/ugBF/5wARf99AEX/XwBF
+ /0AARf8iAEb/DwBG/wMARv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH/wAAR/8DAEb/FABG/zQARf9dAEX/iwBF
+ /7MARf/RAEX/5wBF//QARf/6AEX//gBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//gBF//oARf/0AEX/5wBF/9EARf+zAEX/iwBF/10ARv80AEb/FABH
+ /wMAR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASf8AAD//AABG
+ /wYARv8iAEX/UwBF/4sARf/AAEX/5QBF//cARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX/9wBF/+UARf/AAEX/iwBF/1MARv8iAEb/BgA//wAASf8AAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAARv8AAEb/AwBF/x4ARv9WAEX/mQBF/9MARf/0AEX//gBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf/+AEX/9ABF/9MARf+ZAEb/VgBF/x4ARv8DAEb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH/wAAJv8AAEb/DABF/zsARf+FAEX/zABF
+ //QARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/0AEX/zABF
+ /4UARf87AEb/DAAm/wAAR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH
+ /wAASv8AAEb/EwBF/1AARf+nAEX/5gBF//0ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//QBF/+YARf+nAEX/UABG/xMASv8AAEf/AAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH/wAAT/8AAEb/FABF/1oARf+3AEX/8ABF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf/wAEX/twBF/1oARv8UAE//AABH/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABI/wAAQ/8AAEX/DgBF
+ /1QARf+2AEX/8gBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/8gBF
+ /7YARf9UAEX/DgBD/wAASP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAARv8AAEb/BgBG/z4ARf+mAEX/8ABF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//AARf+mAEb/PgBG/wYARv8AAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR/8AAFP/AABG/yAARf+FAEX/4wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf/jAEX/hQBG/yAAU/8AAEf/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAEb/AABG/wkARf9SAEX/wwBF//sARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/7AEX/wwBF
+ /1IARv8JAEb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEf/AAA8/wAARv8eAEX/igBF/+sARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/6wBF/4oARv8eADz/AABH/wAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG
+ /wAARv8DAEX/QABF/7sARf/7AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX/+wBF/7sARf9AAEf/AwBG/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARv8AAEb/CgBF/2MARf/cAEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/9wARf9jAEb/CgBG
+ /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARf8AAEX/AABF
+ /xUARf+HAEX/7wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF/+8ARf+HAEX/FQBF/wAARf8AAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAEf/AABD/wAARf8hAEX/oQBF//gARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //gARf+hAEX/IQBD/wAAR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH/wAAQv8AAEb/LQBF
+ /7UARf/8AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//wARf+1AEX/LQBB/wAAR/8AAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAR/8AAD3/AABG/zMARf/AAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf/AAEb/MwA9/wAAR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEf/AAA8/wAARf83AEX/xgBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/GAEX/NwA8
+ /wAAR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAABG/wAAQ/8AAEb/MwBF/8YARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/GAEb/MwBD/wAARv8AAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR/8AAET/AABF/ywARf/AAEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf/AAEX/LABE/wAAR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAEX/AABF/wAARf8hAEX/tQBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf+1AEX/IQBF/wAARf8AAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARf8AAEX/FQBF/6EARf/9AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//0ARf+hAEX/FQBF/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAEX/AABG/woARf+HAEX/+QBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//kARf+HAEb/CgBF
+ /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG/wAASP8CAEX/YwBF/+4ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF/+4ARf9jAEj/AgBG/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAARv8AAEP/AABF/0AARf/cAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AET//wBE//8AQ///AEP//wBC//8AQv//AEP//wBD//8AQ///AEP//wBC//8AQv//AEP//wBD
+ //8ARP//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ /9wARf9AAEP/AABG/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABF/wAARf8eAEX/uwBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AET//wBD//8AQ///AUT//wZJ//8QUP//HFn//yxk//87b///SHj//1F/
+ //9Xhf//W4f//1uH//9Xhf//UX///0h4//87b///K2T//xxZ//8QUP//Bkn//wFE//8AQ///AEP//wBE
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/7sARf8eAEX/AAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAARv8AAEf/CABF/4oARf/7AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8AQ///AEP//wNG//8RUf//L2f//1WC
+ //97n///n7j//7vN///Q3f//4en//+rw///x9f//9ff///b5///3+f//9/n///b5///19///8fX//+rw
+ ///g6f//0N3//7rM//+euP//e57//1SB//8uZv//EVH//wNG//8AQ///AEP//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX/+wBF/4oAR/8IAEb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEb/AABC/wAARf9TAEX/6wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE
+ //8AQ///Bkn//yNe//9Wg///i6r//7vO///h6f//9fj///7+////////////////////////////////
+ ///////////////////////////////////////////////////////////////////9/v//9fj//+Hp
+ //+6zf//iqn//1WC//8iXf//Bkn//wBD//8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/6wBF/1MAQv8AAEb/AAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAARf8AAEX/IABF/8MARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBD//8CRf//HVn//1eE//+atf//1N////X3////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////9Pf//9Pf//+ZtP//VoP//xxZ
+ //8CRf//AEP//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX/wwBF/yAARf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEb/AABH/wUARf+FAEX//ABF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD//8GSP//MGf//3uf
+ ///J1///9Pf/////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////09///x9b//3qd//8uZv//Bkj//wBD//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/8AEX/hQBG
+ /wUARv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABI
+ /wAARP8AAEb/PgBF/+IARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBD//8FR///MWj//42s///d5v///P3/////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////+/z//9zl//+Lqv//L2f//wRH//8AQ///AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/iAEX/PgBE/wAASP8AAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEX/AABG/w4ARf+lAEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8BRP//JmD//4Sl///b5f///f7/////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////39///a5P//gqT//yRf
+ //8BRP//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf+lAEb/DgBF/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH
+ /wAAQv8AAEX/VABF/+8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8AQ///DU3//1+K///M2v///P3/////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////7/P//ytn//1yI//8MTf//AEP//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/+8ARf9UAEL/AABH/wAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEb/AABG/xQARf+1AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AET//yZf//+ZtP//8fX/////////////////////
+ //////////////////////////////////////////////////////////////////////////////39
+ ///09///6O7//9vl///O2///xNT//77Q//++0P//w9P//87b///b5f//6O7///T3///9/f//////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////8PT//5ez//8kXv//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF/7UARv8UAEb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG
+ /wAARP8AAEX/WgBF//MARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AET//wJF
+ //9Cdf//xNP///39////////////////////////////////////////////////////////////////
+ ///////////////////9/v//7fL//8nX//+dt///dZr//1KA//84bP//JV///xtY//8VVP//ElL//xFS
+ //8VVP//Glj//yVf//83bP//UoD//3SZ//+dt///yNf//+zx///9/v//////////////////////////
+ /////////////////////////////////////////////////////////f3//8HS//9Ac///AkX//wBE
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/8wBF/1oARP8AAEb/AAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEX/AABF/xMARf+3AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBE//8FR///WYb//9zl////////////////////////////////
+ ///////////////////////////////////////////////////4+v//y9n//4Sl//9Ddf//GVf//wZJ
+ //8ARP//AEP//wBD//8AQ///AEP//wBD//8ARP//AET//wBD//8AQ///AEP//wBD//8AQv//AET//wZJ
+ //8ZVv//QnT//4Ok///K2P//9/n/////////////////////////////////////////////////////
+ /////////////////////////////9rk//9Wg///BEf//wBE//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX/twBF/xMARf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH
+ /wAARP8AAEX/UABF//AARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//Bkj//2SN
+ ///m7f//////////////////////////////////////////////////////////////////////////
+ ///8/f//zNn//2qS//8fW///A0b//wBD//8ARP//AET//wBD//8AQv//AEP//wFF//8ER///CEr//wlL
+ //8JS///CEn//wRH//8BRf//AEP//wBC//8AQ///AET//wBE//8AQ///A0b//x5a//9okf//ytj///v8
+ /////////////////////////////////////////////////////////////////////////////+Tr
+ //9hi///BUf//wBE//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/wAEX/UABE
+ /wAAR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEX/AABG/wwARf+nAEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wNG//9gi///6O7/////////////////////////////////////
+ ////////////////////////////////////////8vX//5Sw//8lX///AUT//wBD//8ARP//AEP//wJF
+ //8PT///KGL//0l5//9nkP//gqT//5ay//+kvP//q8H//6vB//+kvP//lrL//4Ok//9nkf//Snr//yli
+ //8PT///AkX//wBD//8ARP//AEP//wFE//8kXv//ka7///H1////////////////////////////////
+ /////////////////////////////////////////////+bt//9diP//A0b//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf+nAEb/DABF/wAAAAAAAAAAAAAAAAAAAAAAAAAAAABI
+ /wAARf8AAEX/OwBF/+YARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//Tn3//+Hp
+ //////////////////////////////////////////////////////////////////////////////H1
+ //93m///DE3//wBD//8ARP//AEP//w1O//88cP//faD//7bJ///c5f//8fX///r7////////////////
+ //////////////////////////////r8///x9f//3Ob//7bK//9+of//PXH//w5O//8AQ///AET//wBD
+ //8LTP//dJn///D0////////////////////////////////////////////////////////////////
+ /////////////+Do//9Le///AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ /+YARf87AEX/AABG/wAAAAAAAAAAAAAAAAAAAAAAAEb/AABH/wMARf+FAEX//gBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEP//zBn///P3P//////////////////////////////////////////
+ ////////////////////////////////////////uMv//xFQ//8AQ///AET//wpL//9MfP//qsH//+fu
+ ///9/f//////////////////////////////////////////////////////////////////////////
+ //////////////3+///o7v//rML//059//8KS///AET//wBD//8QTv//tMj/////////////////////
+ /////////////////////////////////////////////////////////////8za//8tZf//AEP//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//gBF/4UASP8DAEb/AAAAAAAAAAAAAAAAAAAA
+ AAAARf8AAEX/HgBF/8wARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8SUf//pr7/////
+ ////////////////////////////////////////////////////////////////////////////////
+ //++z///F1T//wBB//8ZVv//i6r//+vw////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////7PH//46s
+ //8aV///AEL//xVT//+7zf//////////////////////////////////////////////////////////
+ /////////////////////////////6O8//8QUP//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX/zABG/x4ARv8AAAAAAAAAAAAAAAAAAEb/AABF/wAARf9WAEX/9ABF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AUX//2eQ///19///////////////////////////////////////////
+ //////////////////////////////////////////////X4//+euP//aZH//7DF///5+///////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////+vv//7LH//9pkf//m7b///X3////////////////
+ ////////////////////////////////////////////////////////////////////////8/b//2ON
+ //8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/0AEX/VgBF/wAARv8AAAAAAAAA
+ AAAARv8AAEb/BgBF/5kARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD//8kXv//zdr/////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////7+///7/P///v//////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////v8///+/v//////////////////////////////////////////////////////////
+ ////////////////////////////////////////ytj//yFd//8ARP//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf+ZAEb/BgBG/wAAAAAAAAAAAABF/wAARv8iAEX/0wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AUX//3ab///7/P//////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///6/P//cpj//wFF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/9MARv8iAEX/AAAA
+ AAAAR/8AAEX/AABF/1MARf/0AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8bWP//yNf/////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////E1P//GVf//wBE//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX/9ABF/1MARf8AAEf/AABG/wAASP8DAEX/iwBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEP//1SB///z9v//////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////L1//9Qfv//AEP//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/iwBI
+ /wMARv8AAEb/AABG/xQARf/AAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ER///k6//////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////46s//8DR///AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/AAEb/FABG/wAARf8AAEb/NABF/+UARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AET//xVU///D0///////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////v9D//xNS//8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ /+UARv80AEX/AABF/wAARf9cAEX/+ABF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8AQ///LmX//+Hp
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////f5///KmP//wBD
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/+ABF/1wARf8AAEj/AwBF/4sARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBC//9Gd///8PT/////////////////////////////////////
+ //////////////////////////////////////////////////////////////X3///Q3f//r8T//6a+
+ //+4y///3uf///v8////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////+/z//97n//+3y///pr3//67E
+ ///Q3f//9ff/////////////////////////////////////////////////////////////////////
+ /////////////////////////////+/z//9DdP//AEL//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX/iwBI/wMARv8PAEX/swBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEP//1WD
+ ///2+P//////////////////////////////////////////////////////////////////////////
+ //////////////3+///H1v//YIv//x9b//8LTP//CEr//w5P//8uZv//gaP//+Lq////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////+Lq//+Bo///Lmb//w5P//8ISv//C0z//x9b//9giv//x9b///39////////////////
+ ////////////////////////////////////////////////////////////////////////9ff//1GA
+ //8AQv//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf+zAEb/DwBF/yIARf/RAEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8AQ///XIj///j6////////////////////////////////
+ ///////////////////////////////////////////////////9/v//rcP//ydh//8AQ///AEP//wBE
+ //8ARP//AET//wBD//8ER///S3z//9bh////////////////////////////////////////////////
+ ///////////////////////////////////////////////////W4f//S3v//wRH//8AQ///AET//wBE
+ //8ARP//AEP//wBD//8mYP//rcL///3+////////////////////////////////////////////////
+ ///////////////////////////////////3+f//WIX//wBD//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF/9EARf8iAEX/QABF/+cARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD
+ //9Yhf//9/n/////////////////////////////////////////////////////////////////////
+ /////////////8fW//8nYf//AEP//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8ARP//VoP//+vx
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////6/H//1aD//8ARP//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD//8nYP//x9b/////
+ //////////////////////////////////////////////////////////////////////////////b4
+ //9Ugv//AEL//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/5wBF/0AARf9fAEX/8wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEH//0p5///y9v//////////////////////////
+ ///////////////////////////////////////////////////1+P//YIv//wBD//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBE//8LTP//oLn/////////////////////////////////////
+ //////////////////////////////////////////////////+guf//C0z//wBE//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBD//9gi///9fj/////////////////////////////////////
+ ////////////////////////////////////////8fX//0d2//8AQf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf/zAEX/XwBF/30ARf/6AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD
+ //8PT///dZr///X4////////////////////////////////////////////////////////////////
+ /////////////9Dd//8fW///AEP//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD
+ //9Ugf//9Pf/////////////////////////////////////////////////////////////////////
+ ////////9Pf//1SB//8AQ///AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEP//x9b
+ ///Q3f//////////////////////////////////////////////////////////////////////////
+ ///09///dZr//xFQ//8AQ///AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//oARf99AEX/nABF
+ //4ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//K2T//6W9///y9v//////////////////////////
+ ////////////////////////////////////////////////////////r8T//wtM//8ARP//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEP//y9m///j6///////////////////////////
+ ///////////////////////////////////////////////////j6///L2b//wBD//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//C0z//6/E////////////////////////////////
+ ///////////////////////////////////////////////////z9v//qL///y1l//8ARP//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//gBF/5wARf+6AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AET//zBn
+ ///C0v//////////////////////////////////////////////////////////////////////////
+ //////////////////+mvv//CEr//wBE//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8AQ///JmD//97n////////////////////////////////////////////////////////////////
+ /////////////97n//8mYP//AEP//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE
+ //8ISv//pr7/////////////////////////////////////////////////////////////////////
+ ////////////////////////xNT//zNp//8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/ugBF
+ /84ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBE//8aV///s8f/////////////////////////////////////
+ /////////////////////////////////////////////////////////////7jL//8PT///AET//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD//84bf//6O7/////////////////////
+ ////////////////////////////////////////////////////////6O7//zht//8AQ///AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AET//w9P//+4y///////////////////////////
+ ////////////////////////////////////////////////////////////////////////tsr//xxY
+ //8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/OAEX/3QBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//Akb//3Wa
+ ///6+///////////////////////////////////////////////////////////////////////////
+ ////////////////////////3uf//y9m//8AQ///AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEP//2mR///5+///////////////////////////////////////////////////////////
+ ///////////////////5+///aZH//wBD//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8AQ///L2b//97n////////////////////////////////////////////////////////////////
+ ///////////////////////////////////6/P//eZ3//wJG//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ /90ARf/rAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBE//8fW///zdr/////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////8/f//gqP//wRH
+ //8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD//8aVv//vc//////////////////////
+ //////////////////////////////////////////////////////////////////+9z///Glb//wBD
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AET//wRH//+Co////P3/////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///Q3P//Il3//wBD//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/6wBF//MARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEP//1KA
+ ///09///////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////i6v//THz//wBE//8ARP//AEX//wBF//8ARf//AEX//wBF
+ //8AQ///Ckv//4Kk///5+v//////////////////////////////////////////////////////////
+ //////////////////////////////n6//+CpP//Ckv//wBD//8ARf//AEX//wBF//8ARf//AEX//wBE
+ //8ARP//THz//+Lq////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////X4//9Wg///AEP//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf/zAEX/+ABF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//faD/////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///X4f//VoP//wpM//8AQv//AEP//wBD//8AQ///AEP//xlW//+CpP//7/T/////////////////////
+ /////////////////////////////////////////////////////////////////////////////+/0
+ //+CpP//GVb//wBD//8AQ///AEP//wBD//8AQ///Ckz//1aD///X4f//////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////4Kj//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//gARf/8AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wRH
+ //+UsP//////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////s8f//oLn//1SB//8vZv//JmD//zht
+ //9okf//vc////j6////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////j6//+9z///aJH//zht//8mYP//L2b//1SB
+ //+guf//6/H/////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////mLP//wVH//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//ABF//wARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//BEf//5ay////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////9Pf//+Pr///e5///6O7///n7////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////5+///6O7//97n///j6///9Pf/////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////+atf//BUj//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/8AEX/+ABF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARP//f6L/////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////4Ol//8BRf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//gARf/zAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD//9Ugv//9Pf/////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////2+P//WIT//wBD//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/8wBF/+sARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEP//yBc///O2///////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////9Hd//8jXv//AEP//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf/rAEX/3QBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//Akb//3ic///6+///////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////7/P//e5///wNG//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/90ARf/OAEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARP//G1j//7XJ////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////7jL//8dWf//AET//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX/zgBF/7oARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//Mmn//8TU
+ /////////////////////////////////////////////////////////////+vw///a5P///P3/////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////+/z//9jj///q7///////////////////////////////////////////
+ ///////////////////H1v//NWv//wBE//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf+6AEX/nABF
+ //4ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//LmX//6i////z9///////////////////////////
+ //////////////z9///Q3P//Wob//y1l//+Usf//7fL/////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////+zx//+Sr///K2T//1eE
+ ///O2////P3////////////////////////////////////////09///q8H//zBn//8ARP//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//gBF/5wARf99AEX/+gBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8AQ///ElH//12I//+wxf//4On///P2///3+f//9fj//+rw///H1v//gKL//yli//8BRf//AEP//wtM
+ //9Ugv//vc7///f5////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////b4//+7zf//UoH//wpL//8AQ///AUX//yhh//9+of//x9b//+rw///1+P//9/n///P2
+ ///h6f//ssb//1+K//8TUv//AEP//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/6AEX/fQBF
+ /18ARf/0AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//AET//w5P//8uZv//THz//1mG
+ //9Tgf//O2///xlX//8DRv//AEP//wBF//8ARf//AET//wBE//8YVv//aZH//8jX///3+f//////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////f5///H1v//Z5D//xdV//8ARP//AET//wBF
+ //8ARf//AEP//wNG//8YVv//O2///1OB//9Zhv//TXz//y9m//8PT///AET//wBE//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//MARf9fAEX/QABF/+cARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AET//wBD//8AQv//AEP//wBC//8AQ///AET//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBE//8BRP//Hlr//2WO//+6zP//8PT/////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////+/0
+ //+5zP//ZI3//x1Z//8BRP//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8AQ///AEL//wBD
+ //8AQv//AEP//wBE//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/5wBF
+ /0AARf8iAEX/0QBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//AET//xRT
+ //9Nff//lbH//9Pf///2+P//////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////9vj//9Le//+TsP//THz//xRT//8ARP//AET//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/RAEX/IgBG/w8ARf+zAEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AET//wBD//8FSP//I17//1qG//+Usf//x9b//+rw
+ ///6/P//////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////r7///r8P//x9b//5Sw//9Zhf//I13//wVI
+ //8AQ///AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ /7MARv8PAEb/AwBF/4sARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8AQ///AEP//wVH//8YVv//PnH//2iR//+Sr///uMv//9fi///p7///9Pf///r7
+ ///+/v/////////////////////////////////////////////+/v//+vv///P2///n7v//1uH//7nM
+ //+Sr///Z5D//z5x//8YVv//BUf//wBD//8AQ///AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/iwBI/wMARf8AAEX/XABF//gARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE
+ //8AQ///AEP//wRH//8PUP//Il3//zlu//9Qf///ZY///3id//+IqP//kq///8fW///+/v///////+7y
+ //+guf//iKj//3qd//9mj///Tn3//zZr//8hXP//EFD//wRH//8AQ///AEP//wBE//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //gARf9cAEX/AABF/wAARv80AEX/5QBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8AQ///AEP//wBC
+ //8AQ///AET//wFF//8BRf//YIr///j6////////4+v//zNp//8AQ///AET//wBD//8AQv//AEP//wBD
+ //8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/5QBG/zQARf8AAEb/AABG/xQARf/AAEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBC//84bf//6O7/////
+ ///1+P//VYL//wBC//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf/AAEb/FABG/wAARv8AAEj/AwBF/4sARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AET//xpY///M2f////////////9/of//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/4sASP8DAEb/AABH/wAARf8AAEX/UwBF
+ //QARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//CUv//6e+
+ /////////////6rA//8KS///AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf/0AEX/UwBF/wAAR/8AAAAAAABF/wAARv8iAEX/0wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//fJ////7+////////ztv//xxZ//8ARP//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/9MARv8iAEX/AAAAAAAAAAAAAEb/AABH
+ /wYARf+ZAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBD
+ //9SgP//9Pf////////p7///Om///wBD//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX/mQBH/wYARv8AAAAAAAAAAAAAR/8AAEX/AABG/1YARf/0AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEP//y5m///h6f////////j6//9hi///AEP//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//QARv9WAEX/AABH/wAAAAAAAAAAAAAA
+ AAAARf8AAEX/HgBF/8wARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARP//FFP//8LS/////////////4yr//8CRv//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX/zABG/x4ARv8AAAAAAAAAAAAAAAAAAAAAAABG/wAAR/8DAEX/hQBF//4ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8GSP//m7b/////////////tcn//w5P
+ //8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//4ARf+FAEj/AwBG/wAAAAAAAAAAAAAA
+ AAAAAAAAAEj/AABF/wAARf87AEX/5gBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBD//9vlv///P3////////X4v//JF7//wBD//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8AQ///Akb//wZI
+ //8ER///AEP//wBD//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX/5gBF/zsARf8AAEb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEX/AABG/wwARf+nAEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEL//0d4///w9P///////+/z
+ //9Fdv//AEL//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARP//F1X//1KA//+IqP//nrj//5Sw//9qkv//KmP//wNG//8ARP//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf+nAEb/DABF/wAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAR/8AAET/AABF/1EARf/wAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8AQ///JV///9nj////////+/z//22U//8AQ///AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//A0b//0V3//+6zP//8/b/////
+ //////////////r8///V4P//b5X//w5O//8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX/8ABF/1EARP8AAEf/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARf8AAEb/EwBF
+ /7cARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8PT///t8r/////
+ ////////mbT//wVI//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//9Nff//3eb////////////////////////////////////////09///haX//wtM
+ //8ARP//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf+3AEb/EwBF/wAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH/wAAQv8AAEX/WgBF//MARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wNG//+Prf/////////////A0f//E1L//wBE//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8AQ///JWD//8rZ////////////////
+ ///////////////////////////////////v8///Wob//wBE//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX/8wBF/1oAQv8AAEf/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG
+ /wAARv8UAEX/tQBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEP//2ON
+ ///5+////////+Do//8sZf//AEP//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//92m////P3/////////////////////////////////////////////////////
+ //+7zf//FFP//wBE//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf+1AEb/FABG/wAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEf/AABC/wAARf9UAEX/7wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8AQ///PHD//+vw////////9Pf//1B///8AQ///AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8AQv//Dk3//7XJ////////////////
+ /////////////////////////////////////////////+rw//88cP//AEP//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX/7wBF/1QAQv8AAEf/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAEX/AABG/w4ARf+lAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE
+ //8dWv//0N3////////+/v//ep3//wBE//8ARf//AEX//wBF//8ARf//AEX//wBE//8ARP//AEP//wBD
+ //8DRv//Dk///yNe//9Xg///3+f/////////////////////////////////////////////////////
+ ////////9vj//1aD//8AQ///AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf+lAEb/DgBF/wAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASP8AAET/AABF/z4ARf/iAEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AET//wpM//+swv////////////+lvf//CEr//wBE
+ //8ARP//AEP//wBC//8BRf//Ckz//xxZ//87b///Yoz//42s//+2yv//2OP///D0///+/v//////////
+ ///////////////////////////////////////////////////2+P//VoP//wBD//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX/4gBF/z4ARP8AAEj/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAARv8AAEb/BQBF/4UARf/8AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AUX//4Kj/////////////8rY//8ZVv//BUj//xZV//8xaP//VoP//4Ci//+rwf//z9z//+rv
+ ///5+v//////////////////////////////////////////////////////////////////////////
+ /////////////+rw//88cP//AEP//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//wARf+FAEb/BQBG/wAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARf8AAEb/IABF
+ /8MARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8AQv//V4T///b4////////7fL//5Cu
+ //+dt///xdX//+Tr///1+P///v7///////////////////////////////////v8///u8///5+3///z9
+ ////////////////////////////////////////////////////////u83//xRT//8ARP//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX/wwBG/yAARf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH/wAAP/8AAEX/UwBF/+sARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBD//8yaf//5Ov//////////////v7///////////////////////////////////3+
+ ///09///4On//8HR//+atf//bpX//0R2//9Bc///y9n/////////////////////////////////////
+ /////////////+/z//9ahv//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/+sARf9TAD//AABH/wAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG
+ /wAAR/8IAEX/igBF//sARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AET//xZV///F1f//////////
+ ///////////////////3+f//5+7//8vZ//+mvv//e57//1F///8tZf//FFP//wVI//8AQ///AEL//wBD
+ //9Nff//3eb////////////////////////////////////////09///haX//wtM//8ARP//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf/7AEX/igBH/wgARv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABF/wAARf8eAEX/uwBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//BEf//3ic///t8v//7fL//9Xg//+xxv//iKj//12I//83bP//Glf//wlK
+ //8BRP//AEP//wBD//8ARP//AEX//wBF//8ARf//AEX//wNG//9Gd///us3///P3////////////////
+ ///6/P//1eD//2+V//8OTv//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF/7sARf8eAEX/AAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAEb/AABD/wAARf9AAEX/3ABF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//Dk7//0J0
+ //9Bc///IVz//wxN//8CRv//AEP//wBD//8ARP//AET//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBE//8YVf//VIL//4io//+dt///lLD//2qS//8qY///A0b//wBE//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf/cAEX/QABD/wAARv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEb/AABI/wIARf9jAEX/7gBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARP//AEP//wBD//8AQ///AET//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBE//8AQ///AkX//wZI
+ //8ER///AEP//wBD//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/7gBF/2MASP8CAEb/AAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAEX/AABG/woARf+HAEX/+QBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //kARf+HAEb/CgBF/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEX/AABF
+ /xUARf+hAEX//QBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/9AEX/oQBF/xUARf8AAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARf8AAEX/AABF/yEARf+1AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ /7UARf8hAEX/AABF/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAR/8AAET/AABG/ywARf/AAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/AAEX/LABE/wAAR/8AAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARv8AAEP/AABG/zMARf/GAEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/xgBG
+ /zMAQ/8AAEb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAR/8AADz/AABF/zcARf/GAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF/8YARf83ADz/AABH/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR/8AAD3/AABG
+ /zMARf/AAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/AAEb/MwA9
+ /wAAR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR/8AAEH/AABF/y0ARf+1AEX//ABF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf/8AEX/tQBF/y0AQf8AAEf/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAR/8AAEP/AABF/yEARf+hAEX/+ABF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/+ABF/6EARf8hAEP/AABH
+ /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARf8AAEX/AABF/xUARf+HAEX/7wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF/+8ARf+HAEX/FQBF/wAARf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAEb/AABG/woARf9jAEX/3ABF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf/cAEX/YwBG/woARv8AAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEb/AABH
+ /wMARf9AAEX/uwBF//sARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf/7AEX/uwBF/0AAR/8DAEb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEf/AAA8/wAARv8eAEX/igBF/+sARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/6wBF/4oARv8eAD//AABH/wAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAABG/wAARv8JAEX/UgBF/8MARf/7AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/+wBF
+ /8MARf9SAEb/CQBG/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG/wAASP8AAEX/IABF
+ /4UARf/jAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF/+MARf+FAEX/IABI/wAARv8AAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARv8AAEb/BgBG/z4ARf+mAEX/8ABF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//AARf+mAEb/PgBG
+ /wYARv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAASP8AAEP/AABF/w4ARf9UAEX/tQBF//IARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//IARf+1AEX/VABF/w4AQ/8AAEj/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEf/AABP/wAARv8UAEX/WgBF
+ /7cARf/wAEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//AARf+3AEX/WgBG/xQAT/8AAEf/AAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABF/wAARP8AAEX/EwBF/1AARf+nAEX/5gBF//0ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//QBF
+ /+YARf+nAEX/UABF/xMARP8AAEX/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAR/8AACf/AABG/wwARf87AEX/hQBF/8wARf/0AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX/9ABF/8wARf+FAEX/OwBG/wwAJ/8AAEf/AAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG/wAAR/8DAEb/HgBF
+ /1YARf+YAEX/0wBF//QARf/+AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//4ARf/0AEX/0wBF/5gARf9WAEb/HgBH
+ /wMARv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASf8AAD//AABG/wYARv8iAEX/UwBF/4sARf/AAEX/5QBF
+ //cARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX/9wBF
+ /+UARf/AAEX/iwBF/1MARv8iAEb/BgA//wAASf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAR/8AAEf/AwBG/xQARv80AEX/XQBF/4sARf+zAEX/0QBF/+cARf/0AEX/+gBF
+ //4ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF//8ARf//AEX//wBF
+ //4ARf/6AEX/9ABF/+cARf/RAEX/swBF/4sARf9dAEb/NABG/xQAR/8DAEf/AAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAR/8AAEf/AwBG/w8ARf8iAEX/QABF/18ARf99AEX/nABF/7oARf/NAEX/3QBF/+sARf/zAEX/+ABF
+ //wARf/8AEX/+ABF//MARf/rAEX/3QBF/80ARf+6AEX/nABF/30ARf9fAEX/QABF/yIARv8PAEf/AwBH
+ /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA////////wAAAA////////////////AAAAAA//////////////+AAAAAA
+ B/////////////8AAAAAAAD////////////8AAAAAAAAP///////////8AAAAAAAAA///////////8AA
+ AAAAAAAD//////////8AAAAAAAAAAP/////////8AAAAAAAAAAA/////////+AAAAAAAAAAAH///////
+ /+AAAAAAAAAAAAf////////AAAAAAAAAAAAD////////AAAAAAAAAAAAAP///////gAAAAAAAAAAAAB/
+ //////wAAAAAAAAAAAAAP//////4AAAAAAAAAAAAAB//////8AAAAAAAAAAAAAAP/////+AAAAAAAAAA
+ AAAAB//////AAAAAAAAAAAAAAAP/////gAAAAAAAAAAAAAAB/////wAAAAAAAAAAAAAAAP////4AAAAA
+ AAAAAAAAAAB////8AAAAAAAAAAAAAAAAP///+AAAAAAAAAAAAAAAAB////AAAAAAAAAAAAAAAAAP///w
+ AAAAAAAAAAAAAAAAD///4AAAAAAAAAAAAAAAAAf//8AAAAAAAAAAAAAAAAAD///AAAAAAAAAAAAAAAAA
+ A///gAAAAAAAAAAAAAAAAAH//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP/+AAAAAAAAAAAA
+ AAAAAAB//gAAAAAAAAAAAAAAAAAAf/wAAAAAAAAAAAAAAAAAAD/8AAAAAAAAAAAAAAAAAAA/+AAAAAAA
+ AAAAAAAAAAAAH/gAAAAAAAAAAAAAAAAAAB/wAAAAAAAAAAAAAAAAAAAP8AAAAAAAAAAAAAAAAAAAD+AA
+ AAAAAAAAAAAAAAAAAAfgAAAAAAAAAAAAAAAAAAAH4AAAAAAAAAAAAAAAAAAAB8AAAAAAAAAAAAAAAAAA
+ AAPAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAA
+ AAAAAAABgAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAgAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAABgAAAAAAA
+ AAAAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAA+AA
+ AAAAAAAAAAAAAAAAAAfgAAAAAAAAAAAAAAAAAAAH4AAAAAAAAAAAAAAAAAAAB/AAAAAAAAAAAAAAAAAA
+ AA/wAAAAAAAAAAAAAAAAAAAP+AAAAAAAAAAAAAAAAAAAH/gAAAAAAAAAAAAAAAAAAB/8AAAAAAAAAAAA
+ AAAAAAA//AAAAAAAAAAAAAAAAAAAP/4AAAAAAAAAAAAAAAAAAH/+AAAAAAAAAAAAAAAAAAB//wAAAAAA
+ AAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//gAAAAAAAAAAAAAAAAAH//8AAAAAAAAAAAAAAAAAD///A
+ AAAAAAAAAAAAAAAAA///4AAAAAAAAAAAAAAAAAf///AAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAA
+ D///+AAAAAAAAAAAAAAAAB////wAAAAAAAAAAAAAAAA////+AAAAAAAAAAAAAAAAf////wAAAAAAAAAA
+ AAAAAP////+AAAAAAAAAAAAAAAH/////wAAAAAAAAAAAAAAD/////+AAAAAAAAAAAAAAB//////wAAAA
+ AAAAAAAAAA//////+AAAAAAAAAAAAAAf//////wAAAAAAAAAAAAAP//////+AAAAAAAAAAAAAH//////
+ /wAAAAAAAAAAAAD////////AAAAAAAAAAAAD////////4AAAAAAAAAAAB/////////gAAAAAAAAAAB//
+ ///////8AAAAAAAAAAA//////////wAAAAAAAAAA///////////AAAAAAAAAA///////////8AAAAAAA
+ AA////////////wAAAAAAAA/////////////AAAAAAAA/////////////+AAAAAAB//////////////8
+ AAAAAD///////////////8AAAAP///////8=
+
+
+
\ No newline at end of file
diff --git a/SCrawler/Channels/ChannelViewForm.vb b/SCrawler/Channels/ChannelViewForm.vb
new file mode 100644
index 0000000..7673c11
--- /dev/null
+++ b/SCrawler/Channels/ChannelViewForm.vb
@@ -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
\ No newline at end of file
diff --git a/SCrawler/Content/Icons/Rainbow.ico b/SCrawler/Content/Icons/Rainbow.ico
new file mode 100644
index 0000000000000000000000000000000000000000..47e29f85d181d3a8c672d95c989b1540b687c101
GIT binary patch
literal 9662
zcmchddrVVT9LH!~He)*Y?MjxIeaROGd#KwdFCkIcMCa#@CiCOJ)|cX_lxgON`kf
z#wn;+3Plk+p5-M2s)7$hTNnlrDW%jxY3U1ED3nLR@-kU=cTc&;++BaCy{%};uitZi
z=ahbazy8j-=N1Hl74%PBoPd6QTX6YZf#7w4K=3|ov`es;HslXJ-Vq4yy}D#ej^%sK
z5{oFvb~PNLAWJsSP>=}~E()^P1U&`Wazr4Hja>t=pOeH7LF~J(|1t!zBOk<$d=NYG
zEeF3$B-#M+XKvi^2;$#)HNv3NVge|kr9JH)@EF{2&i
z@0}Tf_+xThLlD0(q06xx{8{3)MG*fVKYZ2#@o&46-vaXY_&Y)VY^NFGr+t0P!7mew
zrXc=g_+t+Aw!{2gKRpk>JYE|C9X+K=U_8x1xy#Gk02YJ=EA)qbp0w>{GQ*UPi^-&S5)RHvs?a;fB*^IGO+sUE5uo=)&A=eHsIOt=d
z^@c)WVe>+56hmt6UhtfN;@MfBI!4TW?=*P53f9tzfo6z3R;r(8@0$%W+18-Zyr@QQ
z<>l!hPRMtsupm%>Pi@J$Ur2p@J@uLU6jV2)vjWO}{MC_muEZB5`g6R{^5r}ZE^y8k*p&;hXreVl!V4=Z<$rnE%e&Qq8mpnF
z(EWIk%gpWmhx$yT=LbTWK>G2TRrTQW+GrLdXBl%IS)b>9x7Q1HxY)+_M
z?3weIKAdu2y5plxUGq|44EuX^WcIG958^xCVDoa@Bu=is(s0dJV{Us?IymWrSh+rx
zd(KmEZ+sT9W8=mU^PA;9i5>ZclCI5MUT&Yu$?jJf8oV_Yy|H|7)Xn7!)vs{PT9g{!
zBIai6(-=vO@i8W1|gOO<$`Cv7(x;a(Zlh^URH-()!rU=7rj_2Crk?
zCiof~WS8pmAXdo7egA0t6@#+_h4;q&5HH(TrWvy+i=2z6PFtyUDbIeVOrOuRZzXG2
zL9CE3T3-CR@}W5gUZZSIs9kZ>+k5Fx2ZfCr1NuIbeKv-8xjxJhsg}BDy{c}%6XN9h
z3N*feO6_rAZnokW=xfx}hf>{pT)uGqNVrSgbK_NxfKjEJa&Z|+{bH@pTU<3b!e-{S
zPi0sZ`0O=MEaCXeJ+rQ={uyIQ`@{%|k>oFH_E`%`oB=K`yPubDf1Gy0vISz}GP
zS146A`)nxBeAXlo%VMU?dhujt_bYsOBAtWS*hc5pj9AO-hs`C`LvDcQ>Gd<**!etr
z+sTZ6;=M$4AG2VxM1&
zwZ=BIXXNA#DC9ZTR8-3^YTx6_7j7O!wFIY7)N!5~oF<@{|6HN|W%^kEq5CTY0&0=b
zX+~X)w$Qqg9;XEuUv)|HH|Vstg5YZy&i(iPN_($j*kr-y?|3sU4pnzp3>0WG+y+yDRo
literal 0
HcmV?d00001
diff --git a/SCrawler/Content/Icons/RedditIcon.ico b/SCrawler/Content/Icons/RedditIcon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..c9ee6a3dd345caaddd87daa550e15164540a35be
GIT binary patch
literal 67646
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
XWNNiQW`w}W00000NkvXXu0mjf-vh@i
literal 0
HcmV?d00001
diff --git a/SCrawler/Content/Icons/UsersIcon.ico b/SCrawler/Content/Icons/UsersIcon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..e00c1ebac42c6d91b72ab6883fb4fce92a230738
GIT binary patch
literal 25214
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
Z1fqay0M;3VvkHKLLYOB6VYq3+{|90sYEl3I
literal 0
HcmV?d00001
diff --git a/SCrawler/Content/Pictures/Cloud_01_16.png b/SCrawler/Content/Pictures/Cloud_01_16.png
new file mode 100644
index 0000000000000000000000000000000000000000..18509207670f651c9eb263715c34880b49c97c50
GIT binary patch
literal 384
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
A&j0`b
literal 0
HcmV?d00001
diff --git a/SCrawler/Content/Pictures/Delete.png b/SCrawler/Content/Pictures/Delete.png
new file mode 100644
index 0000000000000000000000000000000000000000..e241f3c4a6780ecf00c0e92541f4d6fe70651052
GIT binary patch
literal 1558
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
literal 0
HcmV?d00001
diff --git a/SCrawler/Content/Pictures/PencilPic_01_16.png b/SCrawler/Content/Pictures/PencilPic_01_16.png
new file mode 100644
index 0000000000000000000000000000000000000000..041e23f453dc41b209a245f6e0047e4055ce5ee6
GIT binary patch
literal 3233
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
Ef(vV(ivR!s
literal 0
HcmV?d00001
diff --git a/SCrawler/Content/Pictures/Pin_32.png b/SCrawler/Content/Pictures/Pin_32.png
new file mode 100644
index 0000000000000000000000000000000000000000..1e36e474e4d182b609c5d039b044412d406794a3
GIT binary patch
literal 4758
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