Compare commits

...

12 Commits

Author SHA1 Message Date
Andy
129558c262 2022.9.24.0
Fixed wrong image opening in Autodownloader
Fixed incorrect feed grid resizing when removing media
Fixed incorrect removal of users from the collection
Fixed Instagram function displaying number of requests: wrong value type.
Fixed XVIDEOS cycle bug
Collection: add multiple users
Collection: new collections at the top
Copying user data
Feed: 'Season' and 'Date' to the post title.
2022-09-24 20:26:40 +03:00
Andy
a3e79eb4bc Update UserDataBase.vb
Fixed typo
2022-09-17 20:28:27 +03:00
Andy
eb28255de3 2022.9.17.0
Extended filters by date
Added download by dates for multiple users
Changed validation of dates ranges in UserDataBase
Add user filters by dates
Add disabling site downloading
Fixed Twitter date validator
2022-09-17 19:59:55 +03:00
Andy
92be0994ae 2022.9.16.0
Removed some compatible functions
Fixed Settings.GetUser bug
Design improvements
Changed UserMediD comparer
FeedVideo design updated, incorrect time position fixed, bugs fixed
Fixed getting Reddit channel video thumbnail
2022-09-16 19:41:24 +03:00
Andy
9567b0a367 2022.9.13.0
Added video duration to the feed
Added skipping of pinned Instagram posts if they are already downloaded
2022-09-13 16:20:07 +03:00
Andy
c28c0e1ba3 2022.9.10.0
Fixed: missed posts are not saved
Fixed memory leaking because of the video
2022-09-10 12:28:40 +03:00
Andy
86771eee94 2022.9.8.1
Fixed unexpected memory leak when using the 'Feed' form
2022-09-08 22:24:36 +03:00
Andy
02e8a15ae3 2022.9.8.0
Temporary disabled RedGifs downloading
Added 'missing posts', 'feed'
Fixed minor bugs
2022-09-08 12:36:25 +03:00
Andy
443ab329d5 2022.8.28.0
Changed target platforms
Added RedGifs pics
Fixed Switcher limit bug
2022-08-28 04:08:54 +03:00
Andy
a16bb8de90 Update CONTRIBUTING.md 2022-08-26 20:38:33 +03:00
Andy
0af5e6f8d4 Update README.md 2022-08-26 20:37:54 +03:00
Andy
54ffe10f71 2022.8.22.0
Cleaned up the code
Replace some old functions with new ones
Adapted to the new library environment
Enable/Disable display user/downloaded image
Autodownloader option 'Show notification' not saved
Separate thread for standalone video downloader
Expanded the description of some errors with additional information
Fixed date/time renaming issue
Fixed internal library bugs
Fixed minor bugs
2022-08-22 02:42:36 +03:00
134 changed files with 5343 additions and 1513 deletions

View File

@@ -11,10 +11,14 @@ I welcome requests! Follow these steps to contribute:
1. Delete the "PersonalUtilities" project from the solution.
1. Delete the "PersonalUtilities.Notifications" project from the solution.
1. Add the latest versions of the ```PersonalUtilities.dll``` and ```PersonalUtilities.Notifications.dll``` libraries (from the [latest release](https://github.com/AAndyProgram/SCrawler/releases/latest)).
1. The following libraries must be added to project references with the '**Copy to output folder**' option:
- ```PersonalUtilities.dll```
- ```PersonalUtilities.Notifications.dll```
- ```Microsoft.Toolkit.Uwp.Notifications.dll```
- ```System.ValueTuple.dll```
1. Import PersonalUtilities.Functions for the whole project.
**Always use the correct "PersonalUtilities.dll" library. You must download this library from the release of the code you downloaded.**
**Always use the correct libraries. You must download libraries from the same release date as the code commit date.**
# How to request a new site
@@ -45,3 +49,5 @@ If I'm interested in a site you want to add, it may be added in future releases.
# Contact me
[![matrix](https://img.shields.io/badge/Matrix-%40andyprogram%3Amatrix.org-informational)](https://matrix.to/#/@andyprogram:matrix.org)
[![discord](https://img.shields.io/badge/discord-AndyProgram%233804-yellowgreen)](https://discordapp.com/users/1012768226679206009) AndyProgram#3804

View File

@@ -1,5 +1,108 @@
# 2022.9.24.0
*2022-09-24*
- Added
- Ability to copy user data to another destination
- Ability to add 'Session' and 'Date' values to the post title in the feed
- Minor feed improvements
- The newly created collection will now appear at the top of the list (after reopening the form)
- Ability to add multiple users at a time to the collection.
- Fixed
- Autodownloader opens a compressed image instead of a full one
- Incorrect resizing of the feed grid after deleting a media file
- Incorrect behavior when deleting/removing a user from a collection.
- An incorrect function that displayed the number of spent Instagram requests.
- Bug in the XVIDEOS downloader
- Minor bugs
# 2022.9.17.0
*2022-09-17*
- Added
- Added two date filters to filter users (in range, not in range)
- (Request #71) Download data for a specific date range
- The ability to disable site downloading (in the site settings form)
- Updated
- Plugins
- Fixed
- (Issue #71) ```Download data to the date``` doesn't work for Twitter
- Download data for a specific date range doesn't work for multiple users
- Incorrect feed sorting algorithm
- Minor bugs
# 2022.9.16.0
*2022-09-16*
- Fixed
- Failed to get video thumbnail for channel video post
- Incorrect rendering of the 'Feed' table when the number of columns is more than one
- Minor design bugs
# 2022.9.13.0
*2022-09-13*
- Added
- Video duration to the feed
- Fixed
- (Issue #70) Instagram posts not downloading if there are pinned posts that have already been downloaded
- Minor bugs
# 2022.9.10.0
*2022-09-10*
- Fixed
- The memory is still leaking. This time because of the video. *Using WMP was not the best choice.*
# 2022.9.8.1
*2022-09-08*
- Fixed
- Unexpected memory leak when using the 'Feed' form
# 2022.9.8.0
*2022-09-08*
- Added
- **Feed** (feed of downloaded media files)
- Missing posts tracking and management
- Simple scheduler notifications
- Fixed
- (Issue #67) Saved Instagram posts not downloading
# 2022.8.28.0
*2022-08-28*
- Added
- RedGifs icon
- Fixed
- Incorrect number of posts displayed in the Reddit channels downloader.
# 2022.8.22.0
*2022-08-22*
- Added
- Ability to enable/disable the display of the downloaded image in toast notifications (AutoDownloader)
- Ability to enable/disable the display of the user icon in toast notifications (AutoDownloader)
- Downloading with standalone video downloader has been moved to a separate thread
- Fixed
- (Issue #35) The file name does not change only by date
- (Issue #62) Internal library error
- AutoDownloader option ```Show notifications``` not saved
- Minor bugs
# 2022.7.7.0
*2022-07-07*
- Added
- **Scheduler** (creating multiple automation tasks)
- Automation startup delay
@@ -16,6 +119,8 @@
# 2022.6.10.0
*2022-06-10*
**Attention! From now on, Instagram requires Cookies, Hash and authorization headers!**
- Fixed
@@ -23,6 +128,8 @@
# 2022.6.6.0
*2022-06-06*
- Added
- Ability to pause automation
- Fixed
@@ -31,6 +138,8 @@
# 2022.6.3.0
*2022-06-03*
Changed version numbering method. From now on, new versions will be numbered by release date (YYYY.M.D)
**Attention! Starting with this release, SCrawler may not work on windows 7 and 8 or may not work correctly. All future releases will only be guaranteed to work on windows 10 and 11.**
@@ -44,6 +153,8 @@ Changed version numbering method. From now on, new versions will be numbered by
# 3.0.0.10
*2022-05-23*
- Added
- **Downloading groups**
- **Download saved Twitter posts** (bookmarks)
@@ -65,6 +176,8 @@ Changed version numbering method. From now on, new versions will be numbered by
# 3.0.0.9
*2022-04-24*
- Added
- Excluded labels
- Ability to disable user grouping
@@ -75,6 +188,8 @@ Changed version numbering method. From now on, new versions will be numbered by
# 3.0.0.8
*2022-04-19*
- Added
- Script mode ```command```
- Disabled Instagram error 403 (Forbidden) logging for downloading tagged data
@@ -83,6 +198,8 @@ Changed version numbering method. From now on, new versions will be numbered by
# 3.0.0.7
*2022-04-14*
- Added
- Ability to run a script after the user download is complete
- Hotkey ```F2``` for additional options in the user creation form
@@ -93,6 +210,8 @@ Changed version numbering method. From now on, new versions will be numbered by
# 3.0.0.6
*2022-04-04*
- Added
- ```GoTo Start``` channels button
- ```GoTo End``` channels button
@@ -104,17 +223,23 @@ Changed version numbering method. From now on, new versions will be numbered by
# 3.0.0.5
*2022-04-02*
- Added
- ```New```, ```Hot```, ```Top``` Reddit channel and user download modes
# 3.0.0.4
*2022-03-26*
- Fixed
- External plugins do not save information about downloaded files
- The user cannot be added to the collection if a special path has been specified.
# 3.0.0.3
*2022-03-24*
- Added
- Download all by specific sites
- Download all, ignoring the ```Ready for download``` option
@@ -126,6 +251,8 @@ Changed version numbering method. From now on, new versions will be numbered by
# 3.0.0.2
*2022-03-22*
- Added
- **LPSG** site plugin
- **XVIDEOS** site plugin
@@ -136,6 +263,8 @@ Changed version numbering method. From now on, new versions will be numbered by
# 3.0.0.1
*2022-03-20*
- Added
- Download data up to a specific date
- Update and Reset functions in the plugin (ISiteSettings)
@@ -149,6 +278,8 @@ Changed version numbering method. From now on, new versions will be numbered by
# 3.0.0.0
*2022-03-17*
**Attention! This version of the program makes changes user data file (Users.xml). Once you start using this version, you will not be able to use previous versions of the program. Therefore, it is highly recommended to archive the program settings folder and archive the users' data files (you can use the [```ArchiveSCrawlerUsersDataFiles.bat```](Tools/ArchiveSCrawlerUsersDataFiles.bat) tool to archive the data files of all users).**
- Added
@@ -189,6 +320,8 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
# 2.0.0.4
*2022-02-07*
**Removed compatibility of program settings with version 1.0.0.4 and lower.**
**If your program version is 1.0.0.4 and lower, it is strongly recommended that you upgrade to release 2.0.0.1 to update the program settings (and run the program). Then update to this release. Otherwise, you will have to configure the program settings again**
@@ -203,6 +336,8 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
# 2.0.0.3
*2022-02-02*
**Removed compatibility of program settings with version 1.0.0.4 and lower.**
**If your program version is 1.0.0.4 and lower, it is strongly recommended that you upgrade to release 2.0.0.1 to update the program settings (and run the program). Then update to this release. Otherwise, you will have to configure the program settings again**
@@ -218,6 +353,8 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
# 2.0.0.2
*2022-01-23*
**This is the last release that supports program settings of version 1.0.0.4 and lower. Compatibility of program settings with version 1.0.0.4 and lower will be removed in future releases. It is strongly recommended that you upgrade to this release before future releases. Otherwise, you will have to configure the program settings again. If your program version is 1.0.1.0 or higher, you should not pay attention to this message.**
- Added
@@ -240,6 +377,8 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
# 2.0.0.1
*2021-12-29*
- Added
- Download individual Imgur media files (use the "Download video" form).
- Fixed
@@ -248,6 +387,8 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
# 2.0.0.0
*2021-12-27*
- Added
- **Instagram**
- Filter by site
@@ -265,6 +406,8 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
# 1.0.1.0
*2021-12-20*
- Added
- Extended site settings
- Non-existend users will be marked in red
@@ -286,6 +429,8 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
# 1.0.0.4
*2021-12-12*
- Added
- Full channels support (you can now add channel (subreddit) for standard download)
- ```Ready for download``` now available for collections and can be changed for multiple user
@@ -294,12 +439,16 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
# 1.0.0.3
*2021-12-11*
- Fixed
- Custom "Download videos" option is not saved
- The "Download all" button is not activated after changing modes
# 1.0.0.2
*2021-12-10*
- Added
- Ability to choose what types of media you want to download (images only, videos only, both)
- Ability to name files by date
@@ -308,6 +457,8 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
# 1.0.0.1
*2021-12-09*
- Added
- Limited download if user added from the channel
- Forced limited download for any user
@@ -330,4 +481,6 @@ At the requests of some users, I added [screenshots](ProgramScreenshots) of the
# 1.0.0.0
*2021-12-07*
Initial release

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 KiB

After

Width:  |  Height:  |  Size: 370 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 379 KiB

After

Width:  |  Height:  |  Size: 381 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -18,7 +18,7 @@ https://www.4kdownload.com/products/product-stogram
| Download posts by location | No | **Yes** |
| Save Private Instagram Content with Permission| Yes | Yes |
| Download Instagram Stories and Highlights | Yes | Yes |
| See Others Instagram Feed As Your Own | No | **Yes** |
| See Others Instagram Feed As Your Own | Yes | Yes |
| Download Instagram Video Posts | Yes | Yes |
| Backup Your Instagram Account | Yes | Yes |
| Save Instagram Posts by Date | Yes | Yes |
@@ -31,7 +31,7 @@ https://www.4kdownload.com/products/product-stogram
| Automatic Subscriptions Update | **Free** | Paid (43.56 EUR) |
| Posts and Captions Export | No | Paid (43.56 EUR) |
| Advertisements free | **No ADs at all for free** | Paid (14.52) |
| Operating Systems | Windows 7+ | Windows 7+, MacOS 10.13+, Ubuntu x64 |
| Operating Systems | Windows 10+ | Windows 7+, MacOS 10.13+, Ubuntu x64 |
| Select want content type to download | **Yes** | No |
| Instagram support | Yes | Yes |
| Twitter support | **Yes** | No |
@@ -66,9 +66,9 @@ https://github.com/RipMeApp/ripme
| Export and import subscriptions | No | No |
| **Paid** | **No** | **No** |
| **Free options** | The program is completely free | The program is completely free, but site limits are not declared |
| Operating Systems | Windows 7+ | Windows, MacOS, Linux |
| Operating Systems | Windows 10+ | Windows, MacOS, Linux |
| Select want content type to download | Yes | Yes |
| Suported sites | 3 internal and any site using plugins | 86+ sites (declared) |
| Suported sites | 6 internal and any site using plugins | 86+ sites (declared) |
| Other sites support | **Yes** | No |
| Still supported | **Yes** | **No (last release date May 4, 2021)** |

View File

@@ -8,6 +8,8 @@
A program to download photo and video from [any site](#supported-sites) (e.g. Reddit, Twitter, Instagram).
**If you like SCrawler, please like the program on [this site]( https://alternativeto.net/software/scrawler/about/)**
Do you like this program? Consider adding to my coffee fund by making a donation to show your support. :blush:
[![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/andyprogram)
@@ -35,6 +37,7 @@ Do you like this program? Consider adding to my coffee fund by making a donation
- Add users from parsed channel
- **Advanced user management**
- **Automation** (downloading data automatically every ```X``` minutes)
- **Feed** (feed of downloaded media files)
- Labeling users
- Create download groups
- Adding users to favorites and temporary
@@ -100,10 +103,7 @@ Just download [latest](https://github.com/AAndyProgram/SCrawler/releases/latest)
# How to build from source
1. Delete the "PersonalUtilities" project from the solution.
1. Delete the "PersonalUtilities.Notifications" project from the solution.
1. Add the latest versions of the ```PersonalUtilities.dll``` and ```PersonalUtilities.Notifications.dll``` libraries (from the [latest release](https://github.com/AAndyProgram/SCrawler/releases/latest)).
1. Import PersonalUtilities.Functions for the whole project.
Read about how to build from source [here](CONTRIBUTING.md#how-to-build-from-source)
# How to make a plugin
@@ -149,3 +149,5 @@ Example: ```D:\Programs\SCrawler\SCrawler.exe v```
# Contact me
[![matrix](https://img.shields.io/badge/Matrix-%40andyprogram%3Amatrix.org-informational)](https://matrix.to/#/@andyprogram:matrix.org)
[![discord](https://img.shields.io/badge/discord-AndyProgram%233804-yellowgreen)](https://discordapp.com/users/1012768226679206009) AndyProgram#3804

View File

@@ -30,19 +30,5 @@ Friend Module Declarations
Friend ReadOnly Property FileRegExExt As New RParams(FileUrlRegexDefault, 0, Nothing, InputForbidRemover)
Friend ReadOnly Property FileRegExExt2 As New RParams("([^/]+?)(?=(\Z|&))", 0, Nothing, InputForbidRemover)
Friend ReadOnly Property FileExistsRegEx As RParams = RParams.DMS(FileUrlRegexDefault, 2)
Private Class PUMComparer : Implements IEqualityComparer, IEqualityComparer(Of PluginUserMedia)
Private Overloads Function Equals(ByVal x As PluginUserMedia, ByVal y As PluginUserMedia) As Boolean Implements IEqualityComparer(Of PluginUserMedia).Equals
Return x.URL = y.URL
End Function
Private Function IEqualityComparer_Equals(ByVal x As Object, ByVal y As Object) As Boolean Implements IEqualityComparer.Equals
Return DirectCast(x, PluginUserMedia).URL = DirectCast(y, PluginUserMedia).URL
End Function
Private Overloads Function GetHashCode(ByVal Obj As Object) As Integer Implements IEqualityComparer.GetHashCode
Throw New NotImplementedException()
End Function
Private Overloads Function GetHashCode(ByVal Obj As PluginUserMedia) As Integer Implements IEqualityComparer(Of PluginUserMedia).GetHashCode
Throw New NotImplementedException()
End Function
End Class
Friend ReadOnly TempListAddParams As New ListAddParams(LAP.NotContainsOnly) With {.Comparer = New PUMComparer}
Friend ReadOnly TempListAddParams As New ListAddParams(LAP.NotContainsOnly) With {.Comparer = New FComparer(Of PluginUserMedia)(Function(x, y) x.URL = y.URL)}
End Module

View File

@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
' by using the '*' as shown below:
' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("2022.7.7.0")>
<Assembly: AssemblyFileVersion("2022.7.7.0")>
<Assembly: AssemblyVersion("2022.9.17.0")>
<Assembly: AssemblyFileVersion("2022.9.17.0")>
<Assembly: NeutralResourcesLanguage("en")>

View File

@@ -30,7 +30,7 @@ Public Class SiteSettings : Implements ISiteSettings
.LoadSettings()
Else
.CookiesDomain = "www.lpsg.com"
.Cookies = New CookieKeeper("www.lpsg.com")
.Cookies = New CookieKeeper(.CookiesDomain)
End If
End With
End Sub
@@ -81,7 +81,7 @@ Public Class SiteSettings : Implements ISiteSettings
Else
Return Nothing
End If
Catch ex As Exception
Catch
Return Nothing
End Try
End Function
@@ -97,4 +97,7 @@ Public Class SiteSettings : Implements ISiteSettings
Public Function ReadyToDownload(ByVal What As ISiteSettings.Download) As Boolean Implements ISiteSettings.ReadyToDownload
Return True
End Function
Public Function GetUserPostUrl(ByVal UserID As String, ByVal PostID As String) As String Implements ISiteSettings.GetUserPostUrl
Return String.Empty
End Function
End Class

View File

@@ -38,7 +38,8 @@ Public Class UserData : Implements IPluginContentProvider
Public Property SeparateVideoFolder As Boolean Implements IPluginContentProvider.SeparateVideoFolder
Public Property DataPath As String Implements IPluginContentProvider.DataPath
Public Property PostsNumberLimit As Integer? Implements IPluginContentProvider.PostsNumberLimit
Public Property PostsDateLimit As Date? Implements IPluginContentProvider.PostsDateLimit
Public Property DownloadDateFrom As Date? Implements IPluginContentProvider.DownloadDateFrom
Public Property DownloadDateTo As Date? Implements IPluginContentProvider.DownloadDateTo
#End Region
#Region "Interface exchange options"
Public Sub ExchangeOptionsSet(ByVal Obj As Object) Implements IPluginContentProvider.ExchangeOptionsSet
@@ -95,7 +96,7 @@ Public Class UserData : Implements IPluginContentProvider
If Responser.StatusCode = Net.HttpStatusCode.ServiceUnavailable Then
LogProvider.Add("LPSG not available")
Else
LogProvider.Add(ex, "[LPSG.UserData.GetMedia]")
LogProvider.Add(ex, $"[LPSG.UserData.GetMedia({Name})]")
End If
End Try
End Sub
@@ -152,7 +153,8 @@ Public Class UserData : Implements IPluginContentProvider
If Responser.Client.StatusCode = Net.HttpStatusCode.ServiceUnavailable Then
LogProvider.Add("LPSG not available")
Else
m.DownloadState = UStates.Skipped
m.DownloadState = UStates.Missing
m.Attempts += 1
End If
End Try
RaiseEvent ProgressChanged(1)

View File

@@ -47,8 +47,7 @@ Friend NotInheritable Class M3U8
CachePath.Delete(SFO.Path, SFODelete.None, EDP.None)
End Try
End Function
Friend Shared Function Download(ByVal URL As String, ByVal Appender As String, ByVal ffmpegFile As SFile, ByVal f As SFile,
ByRef Logger As ILogProvider) As SFile
Friend Shared Function Download(ByVal URL As String, ByVal Appender As String, ByVal ffmpegFile As SFile, ByVal f As SFile, ByRef Logger As ILogProvider) As SFile
Try
If Not URL.IsEmptyString Then
Using w As New WebClient
@@ -62,7 +61,7 @@ Friend NotInheritable Class M3U8
End If
Return Nothing
Catch ex As Exception
If Not ex.HelpLink = 1 Then Logger.Add(ex, "[M3U8.Download]")
If Not ex.HelpLink = 1 Then Logger.Add(ex, $"[M3U8.Download({URL}, {Appender}, {ffmpegFile}, {f})]")
Throw ex
End Try
End Function

View File

@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
' by using the '*' as shown below:
' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("2022.7.7.0")>
<Assembly: AssemblyFileVersion("2022.7.7.0")>
<Assembly: AssemblyVersion("2022.9.24.0")>
<Assembly: AssemblyFileVersion("2022.9.24.0")>
<Assembly: NeutralResourcesLanguage("en")>

View File

@@ -17,7 +17,6 @@ Public Class SettingsForm
MyDefs = New DefaultFormOptions(Me, Design)
End Sub
Private Sub SettingsForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
With MyDefs
.MyViewInitialize(True)
.AddEditToolbar({EditToolbar.ControlItem.Add, EditToolbar.ControlItem.Delete})
@@ -25,11 +24,8 @@ Public Class SettingsForm
If Settings.Domains.Count > 0 Then Settings.Domains.ForEach(Sub(d) LIST_DOMAINS.Items.Add(d))
.EndLoaderOperations()
End With
Catch ex As Exception
MyDefs.InvokeLoaderError(ex)
End Try
End Sub
Private Sub MyDefs_ButtonOkClick() Handles MyDefs.ButtonOkClick
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
Settings.Domains.Clear()
With LIST_DOMAINS
If .Items.Count > 0 Then
@@ -39,7 +35,7 @@ Public Class SettingsForm
Settings.UpdateDomains()
MyDefs.CloseForm()
End Sub
Private Sub MyDefs_ButtonAddClick() Handles MyDefs.ButtonAddClick
Private Sub MyDefs_ButtonAddClick(ByVal Sender As Object, ByVal e As EditToolbarEventArgs) Handles MyDefs.ButtonAddClick
Dim nd$ = InputBoxE("Enter a new domain using the pattern [xvideos.com]:", "New domain")
If Not nd.IsEmptyString Then
If Not LIST_DOMAINS.Items.Contains(nd) Then
@@ -49,11 +45,10 @@ Public Class SettingsForm
End If
End If
End Sub
Private Sub MyDefs_ButtonDeleteClick() Handles MyDefs.ButtonDeleteClickE
Private Sub MyDefs_ButtonDeleteClickE(ByVal Sender As Object, ByVal e As EditToolbarEventArgs) Handles MyDefs.ButtonDeleteClickE
If _LatestSelected.ValueBetween(0, LIST_DOMAINS.Items.Count - 1) Then
Dim n$ = LIST_DOMAINS.Items(_LatestSelected)
If MsgBoxE({$"Are you sure you want to delete the [{n}] domain?",
"Removing domains"}, MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
If MsgBoxE({$"Are you sure you want to delete the [{n}] domain?", "Removing domains"}, MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
LIST_DOMAINS.Items.RemoveAt(_LatestSelected)
MsgBoxE($"Domain [{n}] removed")
Else

View File

@@ -26,7 +26,7 @@ Public Class SiteSettings : Implements ISiteSettings
Public Property Logger As ILogProvider Implements ISiteSettings.Logger
#Region "M3U8"
Private ReadOnly OS64 As Boolean
Private ReadOnly FfmpegExists As Boolean
Friend ReadOnly FfmpegExists As Boolean
Friend ReadOnly FfmpegFile As SFile
Friend ReadOnly Property UseM3U8 As Boolean
Get
@@ -179,4 +179,7 @@ Public Class SiteSettings : Implements ISiteSettings
End If
Return Nothing
End Function
Public Function GetUserPostUrl(ByVal UserID As String, ByVal PostID As String) As String Implements ISiteSettings.GetUserPostUrl
Return String.Empty
End Function
End Class

View File

@@ -14,8 +14,8 @@ Imports UStates = SCrawler.Plugin.PluginUserMedia.States
Imports UTypes = SCrawler.Plugin.PluginUserMedia.Types
Public Class UserData : Implements IPluginContentProvider
#Region "Interface declarations"
Public Event ProgressChanged(Count As Integer) Implements IPluginContentProvider.ProgressChanged
Public Event TotalCountChanged(Count As Integer) Implements IPluginContentProvider.TotalCountChanged
Public Event ProgressChanged(ByVal Count As Integer) Implements IPluginContentProvider.ProgressChanged
Public Event TotalCountChanged(ByVal Count As Integer) Implements IPluginContentProvider.TotalCountChanged
Public Property Thrower As IThrower Implements IPluginContentProvider.Thrower
Public Property LogProvider As ILogProvider Implements IPluginContentProvider.LogProvider
Public Property ESettings As ISiteSettings Implements IPluginContentProvider.Settings
@@ -37,7 +37,8 @@ Public Class UserData : Implements IPluginContentProvider
Public Property SeparateVideoFolder As Boolean Implements IPluginContentProvider.SeparateVideoFolder
Public Property DataPath As String Implements IPluginContentProvider.DataPath
Public Property PostsNumberLimit As Integer? Implements IPluginContentProvider.PostsNumberLimit
Public Property PostsDateLimit As Date? Implements IPluginContentProvider.PostsDateLimit
Public Property DownloadDateFrom As Date? Implements IPluginContentProvider.DownloadDateFrom
Public Property DownloadDateTo As Date? Implements IPluginContentProvider.DownloadDateTo
#End Region
#Region "Interface exchange options"
Public Sub ExchangeOptionsSet(ByVal Obj As Object) Implements IPluginContentProvider.ExchangeOptionsSet
@@ -56,14 +57,21 @@ Public Class UserData : Implements IPluginContentProvider
Private Property Responser As Response
Public Sub GetMedia() Implements IPluginContentProvider.GetMedia
Try
If Not Settings.UseM3U8 Then LogProvider.Add("File [ffmpeg.exe] not found") : Exit Sub
If Not Settings.UseM3U8 Then
If Settings.FfmpegExists Then
LogProvider.Add($"XVIDEOS [{Name}]: The plugin only works with x64 OS.")
Else
LogProvider.Add($"XVIDEOS [{Name}]: File [ffmpeg.exe] not found")
End If
Exit Sub
End If
If Not Responser Is Nothing Then Responser.Dispose()
Responser = New Response
Responser.Copy(Settings.Responser)
Dim NextPage% = 0
Dim r$
Dim j As EContainer, jj As EContainer
Dim jj As EContainer
Dim e As ErrorsDescriber = EDP.ThrowException
Dim user$ = Settings.GetUserUrl(Name, False)
Dim p As PluginUserMedia
@@ -74,8 +82,7 @@ Public Class UserData : Implements IPluginContentProvider
r = Responser.GetResponse($"https://www.xvideos.com/{user}/videos/new/{If(NextPage = 0, String.Empty, NextPage)}",, e)
If Not r.IsEmptyString Then
If Not EnvirSet Then UserExists = True : UserSuspended = False : EnvirSet = True
j = JsonDocument.Parse(r).XmlIfNothing
With j
With JsonDocument.Parse(r).XmlIfNothing
If .Contains("videos") Then
With .Item("videos")
If .Count > 0 Then
@@ -86,9 +93,12 @@ Public Class UserData : Implements IPluginContentProvider
.URL = $"https://www.xvideos.com{jj.Value("u")}"
}
If Not p.PostID.IsEmptyString And Not jj.Value("u").IsEmptyString Then
If Not TempPostsList.Contains(p.PostID) Then TempPostsList.Add(p.PostID) : TempMediaList.Add(p) Else Exit Do
If Not TempPostsList.Contains(p.PostID) Then TempPostsList.Add(p.PostID) : TempMediaList.Add(p) Else .Dispose() : Exit Do
End If
Next
Else
.Dispose()
Exit Do
End If
End With
Else
@@ -105,9 +115,7 @@ Public Class UserData : Implements IPluginContentProvider
If TempMediaList.Count > 0 Then
For i% = 0 To TempMediaList.Count - 1
Thrower.ThrowAny()
With TempMediaList(i)
TempMediaList(i) = GetVideoData(.URL, Responser, Settings.DownloadUHD.Value, .PostID, LogProvider)
End With
With TempMediaList(i) : TempMediaList(i) = GetVideoData(.URL, Responser, Settings.DownloadUHD.Value, .PostID, LogProvider) : End With
Next
TempMediaList.RemoveAll(Function(m) m.URL.IsEmptyString)
End If
@@ -149,7 +157,7 @@ Public Class UserData : Implements IPluginContentProvider
Dim t$ = RegexReplace(r, VideoTitleRegex)
r = resp.GetResponse(m,, EDP.ThrowException)
If Not r.IsEmptyString Then
Dim ls As List(Of VSize) = FNF.RegexFields(Of VSize)(r, {M3U8Reparse}, {1, 2})
Dim ls As List(Of VSize) = RegexFields(Of VSize)(r, {M3U8Reparse}, {1, 2})
If ls.ListExists And Not DownloadUHD Then ls.RemoveAll(Function(v) v.Size > 1080)
If ls.ListExists Then
ls.Sort()
@@ -203,7 +211,8 @@ Public Class UserData : Implements IPluginContentProvider
m.File = f
m.DownloadState = UStates.Downloaded
Catch ex As Exception
m.DownloadState = UStates.Skipped
m.DownloadState = UStates.Missing
m.Attempts += 1
End Try
TempMediaList(i) = m
RaiseEvent ProgressChanged(1)

View File

@@ -26,7 +26,8 @@ Namespace Plugin
Property SeparateVideoFolder As Boolean
Property DataPath As String
Property PostsNumberLimit As Integer?
Property PostsDateLimit As Date?
Property DownloadDateFrom As Date?
Property DownloadDateTo As Date?
Function ExchangeOptionsGet() As Object
Sub ExchangeOptionsSet(ByVal Obj As Object)
Sub XmlFieldsSet(ByVal Fields As List(Of KeyValuePair(Of String, String)))

View File

@@ -23,6 +23,7 @@ Namespace Plugin
Function IsMyImageVideo(ByVal URL As String) As ExchangeOptions
Function GetSpecialData(ByVal URL As String, ByVal Path As String, ByVal AskForPath As Boolean) As IEnumerable(Of PluginUserMedia)
Function GetInstance(ByVal What As Download) As IPluginContentProvider
Function GetUserPostUrl(ByVal UserID As String, ByVal PostID As String) As String
#Region "XML Support"
Sub Load(ByVal XMLValues As IEnumerable(Of KeyValuePair(Of String, String)))
#End Region

View File

@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
' by using the '*' as shown below:
' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("2022.7.7.0")>
<Assembly: AssemblyFileVersion("2022.7.7.0")>
<Assembly: AssemblyVersion("2022.9.17.0")>
<Assembly: AssemblyFileVersion("2022.9.17.0")>
<Assembly: NeutralResourcesLanguage("en")>

View File

@@ -13,13 +13,13 @@ Namespace Plugin
Public HostKey As String
Public IsChannel As Boolean
Public Exists As Boolean
Public Sub New(ByVal Site As String, ByVal _Name As String)
UserName = _Name
Public Sub New(ByVal Site As String, ByVal Name As String)
UserName = Name
SiteName = Site
End Sub
Public Sub New(ByVal Site As String, ByVal _Name As String, ByVal _IsChannel As Boolean)
Me.New(Site, _Name)
IsChannel = _IsChannel
Public Sub New(ByVal Site As String, ByVal Name As String, ByVal IsChannel As Boolean)
Me.New(Site, Name)
Me.IsChannel = IsChannel
End Sub
End Structure
End Namespace

View File

@@ -17,7 +17,7 @@ Namespace Plugin
GIF = 50
m3u8 = 100
End Enum
Enum States As Integer : Unknown = 0 : Tried = 1 : Downloaded = 2 : Skipped = 3 : End Enum
Enum States As Integer : Unknown = 0 : Tried = 1 : Downloaded = 2 : Skipped = 3 : Missing = 4 : End Enum
Public ContentType As Integer
Public URL As String
Public MD5 As String
@@ -26,5 +26,6 @@ Namespace Plugin
Public PostID As String
Public PostDate As Date?
Public SpecialFolder As String
Public Attempts As Integer
End Structure
End Namespace

View File

@@ -10,9 +10,9 @@ Namespace Plugin
Public Structure PropertyData
Public ReadOnly Name As String
Public ReadOnly Value As Object
Public Sub New(ByVal _Name As String, ByVal _Value As Object)
Name = _Name
Value = _Value
Public Sub New(ByVal Name As String, ByVal Value As Object)
Me.Name = Name
Me.Value = Value
End Sub
End Structure
End Namespace

View File

@@ -37,7 +37,7 @@ Namespace API.Base
Using w As New WebClient
Dim r$ = w.DownloadString($"https://downdetector.co.uk/status/{Site}/")
If Not r.IsEmptyString Then
l = FNF.RegexFields(Of Data)(r, {Params}, {1, 2})
l = RegexFields(Of Data)(r, {Params}, {1, 2})
If l.ListExists(2) Then
l.Sort()
l2 = New List(Of Data)

View File

@@ -6,9 +6,9 @@
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports SCrawler.Plugin.Hosts
Imports System.Threading
Imports PersonalUtilities.Forms.Toolbars
Imports SCrawler.Plugin.Hosts
Imports PDownload = SCrawler.Plugin.ISiteSettings.Download
Namespace API.Base
Friend NotInheritable Class ProfileSaved
@@ -27,11 +27,8 @@ Namespace API.Base
Using user As IUserData = HOST.GetInstance(PDownload.SavedPosts, Nothing, False, False)
If Not user Is Nothing AndAlso (Not user.Name.IsEmptyString Or Not HOST.IsMyClass) Then
u.Name = user.Name
With DirectCast(user, UserDataBase).User
u.IsChannel = .IsChannel
u.UpdateUserFile()
End With
With DirectCast(user, UserDataBase)
With .User : u.IsChannel = .IsChannel : u.UpdateUserFile() : End With
.User = u
.LoadUserInformation()
.IsSavedPosts = True

View File

@@ -11,12 +11,18 @@ Imports PersonalUtilities.Tools.WEB
Imports SCrawler.Plugin
Imports Download = SCrawler.Plugin.ISiteSettings.Download
Namespace API.Base
Friend MustInherit Class SiteSettingsBase : Implements ISiteSettings
Friend MustInherit Class SiteSettingsBase : Implements ISiteSettings, IResponserContainer
Friend ReadOnly Property Site As String Implements ISiteSettings.Site
Friend Overridable ReadOnly Property Icon As Icon Implements ISiteSettings.Icon
Friend Overridable ReadOnly Property Image As Image Implements ISiteSettings.Image
Private Property Logger As ILogProvider = LogConnector Implements ISiteSettings.Logger
Friend Overridable ReadOnly Property Responser As Response
Private Property IResponserContainer_Responser As Response Implements IResponserContainer.Responser
Get
Return Responser
End Get
Set : End Set
End Property
Friend MustOverride Function GetInstance(ByVal What As Download) As IPluginContentProvider Implements ISiteSettings.GetInstance
Friend Sub New(ByVal SiteName As String)
Site = SiteName
@@ -25,7 +31,15 @@ Namespace API.Base
Site = SiteName
Responser = New Response($"{SettingsFolderName}\Responser_{Site}.xml")
With Responser
If .File.Exists Then .LoadSettings() Else .CookiesDomain = CookiesDomain : .SaveSettings()
If .File.Exists Then
If EncryptCookies.CookiesEncrypted Then .CookiesEncryptKey = SettingsCLS.CookieEncryptKey
.LoadSettings()
Else
.CookiesDomain = CookiesDomain
.Cookies = New CookieKeeper(.CookiesDomain) With {.EncryptKey = SettingsCLS.CookieEncryptKey}
.CookiesEncryptKey = SettingsCLS.CookieEncryptKey
.SaveSettings()
End If
End With
End Sub
#Region "XML"
@@ -36,6 +50,7 @@ Namespace API.Base
Friend Overridable Sub BeginInit() Implements ISiteSettings.BeginInit
End Sub
Friend Overridable Sub EndInit() Implements ISiteSettings.EndInit
EncryptCookies.ValidateCookiesEncrypt(Responser)
End Sub
Friend Overridable Sub BeginUpdate() Implements ISiteSettings.BeginUpdate
End Sub
@@ -63,6 +78,9 @@ Namespace API.Base
End If
Return String.Empty
End Function
Friend Overridable Function GetUserPostUrl(ByVal UserID As String, ByVal PostID As String) As String Implements ISiteSettings.GetUserPostUrl
Return String.Empty
End Function
Protected UserRegex As RParams = Nothing
Friend Overridable Function IsMyUser(ByVal UserURL As String) As ExchangeOptions Implements ISiteSettings.IsMyUser
Try

View File

@@ -18,7 +18,7 @@ Namespace API.Base
GIF = 50
m3u8 = 100
End Enum
Friend Enum States As Integer : Unknown = 0 : Tried = 1 : Downloaded = 2 : Skipped = 3 : End Enum
Friend Enum States As Integer : Unknown = 0 : Tried = 1 : Downloaded = 2 : Skipped = 3 : Missing = 4 : End Enum
Friend [Type] As Types
Friend URL_BASE As String
Friend URL As String
@@ -27,6 +27,7 @@ Namespace API.Base
Friend Post As UserPost
Friend PictureOption As String
Friend State As States
Friend Attempts As Integer
''' <summary>
''' SomeFolder<br/>
''' SomeFolder\SomeFolder2
@@ -51,6 +52,7 @@ Namespace API.Base
Post = New UserPost With {.ID = m.PostID, .[Date] = m.PostDate}
State = m.DownloadState
SpecialFolder = m.SpecialFolder
Attempts = m.Attempts
End If
End Sub
Public Shared Widening Operator CType(ByVal _URL As String) As UserMedia
@@ -71,7 +73,8 @@ Namespace API.Base
.URL = URL,
.SpecialFolder = SpecialFolder,
.PostID = Post.ID,
.PostDate = Post.Date
.PostDate = Post.Date,
.Attempts = Attempts
}
End Function
Friend Overloads Function Equals(ByVal Other As UserMedia) As Boolean Implements IEquatable(Of UserMedia).Equals

View File

@@ -83,11 +83,11 @@ Namespace API.Base
Dim cb As Color = SystemColors.Control
Dim cf As Color = SystemColors.ControlText
If Not UserExists Then
cb = ColorBttDeleteBack
cf = ColorBttDeleteFore
cb = MyColor.DeleteBack
cf = MyColor.DeleteFore
ElseIf UserSuspended Then
cb = ColorBttEditBack
cf = ColorBttEditFore
cb = MyColor.EditBack
cf = MyColor.EditFore
End If
For Each b As ToolStripMenuItem In {BTT_CONTEXT_DOWN, BTT_CONTEXT_EDIT, BTT_CONTEXT_DELETE, BTT_CONTEXT_OPEN_PATH, BTT_CONTEXT_OPEN_SITE}
If Not b Is Nothing Then b.BackColor = cb : b.ForeColor = cf
@@ -127,6 +127,8 @@ Namespace API.Base
Private Const Name_DataMerging As String = "DataMerging"
#Region "Downloaded data"
Private Const Name_MediaType As String = "Type"
Private Const Name_MediaState As String = "State"
Private Const Name_MediaAttempts As String = "Attempts"
Private Const Name_MediaURL As String = "URL"
Private Const Name_MediaHash As String = "Hash"
Private Const Name_MediaFile As String = "File"
@@ -227,21 +229,21 @@ Namespace API.Base
Return Nothing
End If
End Function
Friend Function GetUserPictureAddress() As SFile
Return GetPicture(Of SFile)(False)
Friend Function GetUserPictureToastAddress() As SFile
Return GetPicture(Of SFile)(False, True)
End Function
Friend Overridable Sub SetPicture(ByVal f As SFile) Implements IUserData.SetPicture
Try
If Not f.IsEmptyString AndAlso f.Exists Then
If f.Exists Then
Using p As New UserImage(f, User.File) : p.Save() : End Using
End If
Catch ex As Exception
Catch
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
Protected Function GetPicture(Of T)(Optional ByVal ReturnNullImageOnNothing As Boolean = True) As T
Protected Function GetPicture(Of T)(Optional ByVal ReturnNullImageOnNothing As Boolean = True, Optional ByVal GetToast As Boolean = False) As T
Dim rsfile As Boolean = GetType(T) Is GetType(SFile)
Dim f As SFile = Nothing
Dim p As UserImage = Nothing
@@ -273,7 +275,7 @@ BlockPictureScan:
New ErrorsDescriber(EDP.ReturnValue) With {
.ReturnValue = New List(Of SFile),
.ReturnValueExists = True}).FirstOrDefault
If Not NewPicFile.IsEmptyString AndAlso NewPicFile.Exists Then
If NewPicFile.Exists Then
p = New UserImage(NewPicFile, MyFile)
p.Save()
GoTo BlockReturn
@@ -288,8 +290,14 @@ BlockReturn:
On Error GoTo BlockNullPicture
If Not p Is Nothing Then
Dim i As Image = Nothing
Dim a As SFile = p.Address
If Not rsfile Then
Dim a As SFile = Nothing
If rsfile Then
If GetToast Then
a = p.Large.Address
Else
a = p.Address
End If
Else
Select Case Settings.ViewMode.Value
Case View.LargeIcon : i = p.Large.OriginalImage.Clone
Case View.SmallIcon : i = p.Small.OriginalImage.Clone
@@ -301,8 +309,8 @@ BlockReturn:
BlockNullPicture:
If ReturnNullImageOnNothing Then
Select Case Settings.ViewMode.Value
Case View.LargeIcon : Return CObj(GetNullPicture(Settings.MaxLargeImageHeigh))
Case View.SmallIcon : Return CObj(GetNullPicture(Settings.MaxSmallImageHeigh))
Case View.LargeIcon : Return CObj(GetNullPicture(Settings.MaxLargeImageHeight))
Case View.SmallIcon : Return CObj(GetNullPicture(Settings.MaxSmallImageHeight))
End Select
End If
Return Nothing
@@ -352,10 +360,31 @@ BlockNullPicture:
Friend Overridable Property ReadyForDownload As Boolean = True Implements IUserData.ReadyForDownload
Friend Property DownloadImages As Boolean = True Implements IUserData.DownloadImages
Friend Property DownloadVideos As Boolean = True Implements IUserData.DownloadVideos
Friend Property DownloadMissingOnly As Boolean = False Implements IUserData.DownloadMissingOnly
#End Region
#Region "Content"
Protected ReadOnly _ContentList As List(Of UserMedia)
Protected ReadOnly _ContentNew As List(Of UserMedia)
Friend ReadOnly Property LatestData As List(Of UserMedia)
Protected ReadOnly MissingFinder As Predicate(Of UserMedia) = Function(c) c.State = UStates.Missing
Friend ReadOnly Property ContentMissing As List(Of UserMedia)
Get
If _ContentList.Count > 0 Then
Return _ContentList.Where(Function(c) MissingFinder(c)).ListIfNothing
Else
Return New List(Of UserMedia)
End If
End Get
End Property
Friend Overridable ReadOnly Property ContentMissingExists As Boolean
Get
Return _ContentList.Exists(MissingFinder)
End Get
End Property
Friend Sub RemoveMedia(ByVal m As UserMedia, ByVal State As UStates?)
Dim i% = If(State.HasValue, _ContentList.FindIndex(Function(mm) mm.State = State.Value And mm.Equals(m)), _ContentList.IndexOf(m))
If i >= 0 Then _ContentList.RemoveAt(i)
End Sub
Protected ReadOnly _TempMediaList As List(Of UserMedia)
Protected ReadOnly _TempPostsList As List(Of String)
Friend Function GetLastImageAddress() As SFile
@@ -521,11 +550,18 @@ BlockNullPicture:
End Function
Friend Overridable ReadOnly Property FitToAddParams As Boolean Implements IUserData.FitToAddParams
Get
If Settings.LastUpdatedDate.HasValue AndAlso LastUpdated.HasValue AndAlso
LastUpdated.Value.Date > Settings.LastUpdatedDate.Value.Date Then Return False
If Not Settings.Labels.ExcludedIgnore AndAlso Settings.Labels.Excluded.ValuesList.ListContains(Labels) Then Return False
If Settings.SelectedSites.Count = 0 OrElse Settings.SelectedSites.Contains(Site) Then
Select Case Settings.ShowingMode.Value
With Settings
If LastUpdated.HasValue And Not .ViewDateMode.Value = ShowingDates.Off Then
Dim f As Date = If(.ViewDateFrom.HasValue, .ViewDateFrom.Value.Date, Date.MinValue.Date)
Dim t As Date = If(.ViewDateTo.HasValue, .ViewDateTo.Value.Date, Date.MaxValue.Date)
Select Case DirectCast(.ViewDateMode.Value, ShowingDates)
Case ShowingDates.In : If Not LastUpdated.Value.ValueBetween(f, t) Then Return False
Case ShowingDates.Not : If LastUpdated.Value.ValueBetween(f, t) Then Return False
End Select
End If
If Not .Labels.ExcludedIgnore AndAlso .Labels.Excluded.ValuesList.ListContains(Labels) Then Return False
If .SelectedSites.Count = 0 OrElse .SelectedSites.Contains(Site) Then
Select Case .ShowingMode.Value
Case ShowingModes.Regular : Return Not Temporary And Not Favorite
Case ShowingModes.Temporary : Return Temporary
Case ShowingModes.Favorite : Return Favorite
@@ -538,6 +574,7 @@ BlockNullPicture:
Else
Return False
End If
End With
End Get
End Property
Friend Function GetLVIGroup(ByVal Destination As ListView) As ListViewGroup Implements IUserData.GetLVIGroup
@@ -562,11 +599,12 @@ BlockNullPicture:
Friend Sub New(Optional ByVal InvokeImageHandler As Boolean = True)
_ContentList = New List(Of UserMedia)
_ContentNew = New List(Of UserMedia)
LatestData = New List(Of UserMedia)
_TempMediaList = New List(Of UserMedia)
_TempPostsList = New List(Of String)
Labels = New List(Of String)
UserUpdatedEventHandlers = New List(Of IUserData.UserUpdatedEventHandler)
If InvokeImageHandler Then ImageHandler(Me)
If InvokeImageHandler Then MainFrameObj.ImageHandler(Me)
End Sub
Friend Sub SetEnvironment(ByRef h As SettingsHost, ByVal u As UserInfo, ByVal _LoadUserInformation As Boolean,
Optional ByVal AttachUserInfo As Boolean = True) Implements IUserData.SetEnvironment
@@ -577,13 +615,29 @@ BlockNullPicture:
End If
End Sub
''' <exception cref="ArgumentOutOfRangeException"></exception>
Friend Overloads Shared Function GetInstance(ByVal u As UserInfo, Optional ByVal _LoadUserInformation As Boolean = True) As IUserData
Friend Shared Function GetInstance(ByVal u As UserInfo, Optional ByVal _LoadUserInformation As Boolean = True) As IUserData
If Not u.Plugin.IsEmptyString Then
Return Settings(u.Plugin).GetInstance(u.DownloadOption, u, _LoadUserInformation)
Else
Throw New ArgumentOutOfRangeException("Plugin", $"Plugin [{u.Plugin}] information does not recognized by loader")
End If
End Function
Friend Shared Function GetPostUrl(ByVal u As IUserData, ByVal PostData As UserMedia) As String
Dim uName$ = String.Empty
Try
If Not u Is Nothing AndAlso Not u.IsCollection Then
With DirectCast(u, UserDataBase)
If Not .User.Plugin.IsEmptyString Then
uName = .User.Name
Return Settings(.User.Plugin).GetUserPostUrl(.ID, PostData.Post.ID)
End If
End With
End If
Return String.Empty
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.SendInLog, ex, $"GetPostUrl({uName}, {PostData.Post.ID})", String.Empty)
End Try
End Function
#End Region
#Region "Information & Content data files loader and saver"
#Region "User information"
@@ -670,28 +724,22 @@ BlockNullPicture:
Protected MustOverride Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean)
#End Region
#Region "User data"
Friend Overridable Overloads Sub LoadContentInformation()
Friend Overridable Overloads Sub LoadContentInformation(Optional ByVal Force As Boolean = False)
Try
UpdateDataFiles()
If Not MyFileData.Exists Then Exit Sub
If Not MyFileData.Exists Or (_DataLoaded And Not Force) Then Exit Sub
Using x As New XmlFile(MyFileData, Protector.Modes.All, False) With {.XmlReadOnly = True, .AllowSameNames = True}
x.LoadData()
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
Dim gfn As Func(Of String, String) = Function(Input) If(Input.IsEmptyString, String.Empty,
If(Input.Contains("\"), Input.CSFile.File, Input))
For Each v As EContainer In x
_ContentList.Add(New UserMedia With {
.Type = AConvert(Of Integer)(v.Attribute(Name_MediaType).Value, 0),
.Type = v.Attribute(Name_MediaType).Value.FromXML(Of Integer)(CInt(UTypes.Undefined)),
.State = v.Attribute(Name_MediaState).Value.FromXML(Of Integer)(CInt(UStates.Downloaded)),
.Attempts = v.Attribute(Name_MediaAttempts).Value.FromXML(Of Integer)(0),
.URL = v.Attribute(Name_MediaURL).Value,
.URL_BASE = v.Value,
.MD5 = v.Attribute(Name_MediaHash).Value,
@@ -718,6 +766,8 @@ BlockNullPicture:
If _ContentList.Count > 0 Then
For Each i As UserMedia In _ContentList
x.Add(New EContainer("MediaData", i.URL_BASE, {New EAttribute(Name_MediaType, CInt(i.Type)),
New EAttribute(Name_MediaState, CInt(i.State)),
New EAttribute(Name_MediaAttempts, i.Attempts),
New EAttribute(Name_MediaURL, i.URL),
New EAttribute(Name_MediaHash, i.MD5),
New EAttribute(Name_MediaFile, i.File.File),
@@ -743,16 +793,59 @@ BlockNullPicture:
If Not URL.IsEmptyString Then Process.Start(URL)
Catch ex As Exception
If Not e.Exists Then e = New ErrorsDescriber(EDP.ShowAllMsg)
MsgBoxE({$"Error on trying to open [{Site}] page of user [{Name}]", $"User [{ToString()}]"}, MsgBoxStyle.Critical, e, ex)
MsgBoxE({$"Error when trying to open [{Site}] page of user [{Name}]", $"User [{ToString()}]"}, MsgBoxStyle.Critical, e, ex)
End Try
End Sub
Friend Overridable Sub OpenFolder() Implements IUserData.OpenFolder
GlobalOpenPath(MyFile.CutPath)
End Sub
#End Region
#Region "Download functions and options"
#Region "Download limits"
Protected Enum DateResult : [Continue] : [Skip] : [Exit] : End Enum
Friend Overridable Property DownloadTopCount As Integer? = Nothing Implements IUserData.DownloadTopCount, IPluginContentProvider.PostsNumberLimit
Friend Overridable Property DownloadToDate As Date? = Nothing Implements IUserData.DownloadToDate, IPluginContentProvider.PostsDateLimit
Private _DownloadDateFrom As Date? = Nothing
Private _DownloadDateFromF As Date
Friend Overridable Property DownloadDateFrom As Date? Implements IUserData.DownloadDateFrom, IPluginContentProvider.DownloadDateFrom
Get
Return _DownloadDateFrom
End Get
Set(ByVal d As Date?)
_DownloadDateFrom = d
If _DownloadDateFrom.HasValue Then _DownloadDateFromF = _DownloadDateFrom.Value.Date Else _DownloadDateFromF = Date.MinValue.Date
End Set
End Property
Private _DownloadDateTo As Date? = Nothing
Private _DownloadDateToF As Date
Friend Overridable Property DownloadDateTo As Date? Implements IUserData.DownloadDateTo, IPluginContentProvider.DownloadDateTo
Get
Return _DownloadDateTo
End Get
Set(ByVal d As Date?)
_DownloadDateTo = d
If _DownloadDateTo.HasValue Then _DownloadDateToF = _DownloadDateTo.Value Else _DownloadDateToF = Date.MaxValue.Date
End Set
End Property
Protected Function CheckDatesLimit(ByVal DateString As String, ByVal DateProvider As IFormatProvider) As DateResult
Try
If (DownloadDateFrom.HasValue Or DownloadDateTo.HasValue) And Not DateString.IsEmptyString Then
Dim td As Date? = AConvert(Of Date)(DateString, DateProvider, Nothing)
If td.HasValue Then
If td.Value.ValueBetween(_DownloadDateFromF, _DownloadDateToF) Then
Return DateResult.Continue
ElseIf td.Value > _DownloadDateToF Then
Return DateResult.Skip
Else
Return DateResult.Exit
End If
End If
End If
Return DateResult.Continue
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.SendInLog, ex, $"[UserDataBase.CheckDatesLimit({DateString})]", DateResult.Continue)
End Try
End Function
#End Region
#Region "Download functions and options"
Protected Responser As Response
Friend Overridable Sub DownloadData(ByVal Token As CancellationToken) Implements IContentProvider.DownloadData
Dim Canceled As Boolean = False
@@ -767,6 +860,7 @@ BlockNullPicture:
Dim UpPic As Boolean = Settings.ViewModeIsPicture AndAlso GetPicture(Of Image)(False) Is Nothing
Dim sEnvir() As Boolean = {UserExists, UserSuspended}
Dim EnvirChanged As Func(Of Boolean) = Function() Not sEnvir(0) = UserExists Or Not sEnvir(1) = UserSuspended
Dim _downContent As Func(Of UserMedia, Boolean) = Function(c) c.State = UStates.Downloaded
UserExists = True
UserSuspended = False
DownloadedPictures(False) = 0
@@ -775,19 +869,26 @@ BlockNullPicture:
_TempPostsList.Clear()
Dim __SaveData As Boolean = Not CreatedByChannel Or Not Settings.FromChannelDownloadTopUse
If Not _DataLoaded Then LoadContentInformation()
LoadContentInformation()
If MyFilePosts.Exists Then _TempPostsList.ListAddList(File.ReadAllLines(MyFilePosts))
If _ContentList.Count > 0 Then _TempPostsList.ListAddList(_ContentList.Select(Function(u) u.Post.ID), LNC)
If Not DownloadMissingOnly Then
ThrowAny(Token)
DownloadDataF(Token)
ThrowAny(Token)
Else
'PENDING: UserDataBase ReparseMissing (DownloadDataF)
'ReparseMissing(Token)
End If
'_TempMediaList.ListAddList(ContentMissing, LNC)
If _TempMediaList.Count > 0 Then
If Not DownloadImages Then _TempMediaList.RemoveAll(Function(m) m.Type = UTypes.GIF Or m.Type = UTypes.Picture)
If Not DownloadVideos Then _TempMediaList.RemoveAll(Function(m) m.Type = UTypes.Video Or
m.Type = UTypes.VideoPre Or m.Type = UTypes.m3u8)
If DownloadMissingOnly Then _TempMediaList.RemoveAll(Function(m) Not m.State = UStates.Missing)
End If
ReparseVideo(Token)
@@ -796,8 +897,12 @@ BlockNullPicture:
_ContentNew.ListAddList(_TempMediaList, LAP.ClearBeforeAdd)
DownloadContent(Token)
ThrowIfDisposed()
_ContentList.ListAddList(_ContentNew.Where(Function(c) c.State = UStates.Downloaded), LNC)
If DownloadedTotal(False) > 0 Or EnvirChanged.Invoke Then
LatestData.ListAddList(_ContentNew.Where(_downContent), LNC)
Dim mcb& = If(ContentMissingExists, _ContentList.LongCount(Function(c) MissingFinder(c)), 0)
_ContentList.ListAddList(_ContentNew.Where(Function(c) _downContent(c) Or MissingFinder(c)), LNC)
Dim mca& = If(ContentMissingExists, _ContentList.LongCount(Function(c) MissingFinder(c)), 0)
If DownloadedTotal(False) > 0 Or EnvirChanged.Invoke Or Not mcb = mca Then
If __SaveData Then
LastUpdated = Now
RunScript()
@@ -830,20 +935,11 @@ BlockNullPicture:
If Not Canceled Then _DataParsed = True
_ContentNew.Clear()
DownloadTopCount = Nothing
DownloadToDate = Nothing
DownloadDateFrom = Nothing
DownloadDateTo = Nothing
DownloadMissingOnly = False
End Try
End Sub
Protected Function CheckDatesLimit(ByVal DateString As String, ByVal DateProvider As IFormatProvider) As Boolean
Try
If DownloadToDate.HasValue And Not DateString.IsEmptyString Then
Dim td As Date? = AConvert(Of Date)(DateString, DateProvider, Nothing)
If td.HasValue Then Return td.Value < DownloadToDate.Value
End If
Return True
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.SendInLog, ex, $"[UserDataBase.CheckDatesLimit({DateString})]", True)
End Try
End Function
Protected Sub UpdateDataFiles()
If Not User.File.IsEmptyString Then
MyFileData = User.File
@@ -852,11 +948,14 @@ BlockNullPicture:
MyFilePosts.Name &= "_Posts"
MyFilePosts.Extension = "txt"
Else
Throw New ArgumentNullException("User.File", "User file does not detected")
Throw New ArgumentNullException("User.File", "User file not detected")
End If
End Sub
Protected MustOverride Sub DownloadDataF(ByVal Token As CancellationToken)
Protected MustOverride Sub ReparseVideo(ByVal Token As CancellationToken)
Protected Overridable Sub ReparseVideo(ByVal Token As CancellationToken)
End Sub
Protected Overridable Sub ReparseMissing(ByVal Token As CancellationToken)
End Sub
Protected MustOverride Sub DownloadContent(ByVal Token As CancellationToken)
Protected Sub DownloadContentDefault(ByVal Token As CancellationToken)
Try
@@ -867,6 +966,7 @@ BlockNullPicture:
_ContentNew.RemoveAll(Function(c) c.URL.IsEmptyString)
If _ContentNew.Count > 0 Then
MyFile.Exists(SFO.Path)
Dim MissingErrorsAdd As Boolean = Settings.AddMissingErrorsToLog
Dim MyDir$ = MyFile.CutPath.PathNoSeparator
Dim vsf As Boolean = SeparateVideoFolderF
Dim __isVideo As Boolean
@@ -874,7 +974,7 @@ BlockNullPicture:
Dim v As UserMedia
Using w As New WebClient
If vsf Then SFileShares.SFileExists($"{MyDir}\Video\", SFO.Path)
Progress.TotalCount += _ContentNew.Count
Progress.Maximum += _ContentNew.Count
For i = 0 To _ContentNew.Count - 1
ThrowAny(Token)
v = _ContentNew(i)
@@ -925,7 +1025,9 @@ BlockNullPicture:
v.State = UStates.Downloaded
dCount += 1
Catch wex As Exception
ErrorDownloading(f, v.URL_BASE)
v.Attempts += 1
v.State = UStates.Missing
If MissingErrorsAdd Then ErrorDownloading(f, v.URL_BASE)
End Try
Else
v.State = UStates.Skipped
@@ -962,8 +1064,8 @@ BlockNullPicture:
Protected Function ChangeFileNameByProvider(ByVal f As SFile, ByVal m As UserMedia) As SFile
Dim ff As SFile = Nothing
Try
If Not f.IsEmptyString AndAlso f.Exists Then
If Settings.FileReplaceNameByDate Or Settings.FileAddTimeToFileName Then
If f.Exists Then
If Not Settings.FileReplaceNameByDate.Value = FileNameReplaceMode.None Then
ff = f
ff.Name = String.Format(FileDateAppenderPattern, f.Name, CStr(AConvert(Of String)(If(m.Post.Date, Now), FileDateAppenderProvider, String.Empty)))
ff = SFile.Indexed_IndexFile(ff,, New NumberedFile(ff))
@@ -999,14 +1101,14 @@ BlockNullPicture:
End Try
End Sub
#End Region
#Region "Delete, Move, Merge"
#Region "Delete, Move, Merge, Copy"
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 (User.Merged OrElse f.Delete(SFO.Path, Settings.DeleteMode)) Then
ImageHandler(Me, False)
If Not IncludedInCollection Then MainFrameObj.ImageHandler(Me, False)
Settings.UsersList.Remove(User)
Settings.UpdateUsersList()
Settings.Users.Remove(Me)
If Not IncludedInCollection Then Settings.Users.Remove(Me)
Downloader.UserRemove(Me)
Dispose(True)
Return 1
@@ -1123,6 +1225,48 @@ BlockNullPicture:
End If
Return f
End Function
Private Class FilesCopyingException : Inherits ErrorsDescriberException
Friend Sub New(ByVal User As IUserData, ByVal Msg As String, ByVal Path As SFile)
SendInLogOnlyMessage = True
If User.IncludedInCollection Then _MainMessage = $"[{User.CollectionName}] - "
_MainMessage &= $"[{User.Site}] - [{User.Name}]. {Msg}: {Path.Path}."
End Sub
End Class
Friend Overridable Function CopyFiles(ByVal DestinationPath As SFile, Optional ByVal e As ErrorsDescriber = Nothing) As Boolean Implements IUserData.CopyFiles
Dim fSource As SFile = Nothing
Dim fDest As SFile = Nothing
Try
Dim pOffset%
If IncludedInCollection Then
If DataMerging Then pOffset = 1 Else pOffset = 2
Else
pOffset = 1
End If
fSource = User.File.CutPath(pOffset).Path.CSFileP
Dim OptPath$ = String.Empty
If IncludedInCollection Then
OptPath = $"Collections\{CollectionName}" 'Copying a collection based on the first file
Else
OptPath = $"{Site}\{Name}"
End If
fDest = $"{DestinationPath.PathWithSeparator}{OptPath}".CSFileP
If fDest.Exists(SFO.Path, False) AndAlso MsgBoxE({$"The following path already exists:{vbCr}{fDest.Path}" & vbCr &
"Do you want to copy files here?", "Copying files"}, vbExclamation + vbYesNo) = vbNo Then _
Throw New FilesCopyingException(Me, "The following path already exists", fDest)
If DestinationPath.Exists(SFO.Path, True) Then
My.Computer.FileSystem.CopyDirectory(fSource, fDest, FileIO.UIOption.OnlyErrorDialogs, FileIO.UICancelOption.ThrowException)
Else
Throw New FilesCopyingException(Me, "Cannot create the following path", fDest)
End If
Return True
Catch cex As OperationCanceledException
Return ErrorsDescriber.Execute(e, New FilesCopyingException(Me, "Copy canceled", fDest),, False)
Catch ex As Exception
Return ErrorsDescriber.Execute(e, ex,, False)
End Try
End Function
#End Region
#Region "Errors functions"
Protected Sub LogError(ByVal ex As Exception, ByVal Message As String)
@@ -1153,6 +1297,16 @@ BlockNullPicture:
Return IIf(FriendlyName.IsEmptyString, Name, FriendlyName)
End If
End Function
Public Overrides Function GetHashCode() As Integer
Dim hcStr$
If Not CollectionName.IsEmptyString Then
hcStr = CollectionName
Else
hcStr = IIf(FriendlyName.IsEmptyString, Name, FriendlyName)
End If
If hcStr.IsEmptyString Then hcStr = LVIKey
Return hcStr.GetHashCode
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)
@@ -1208,6 +1362,7 @@ BlockNullPicture:
If disposing Then
_ContentList.Clear()
_ContentNew.Clear()
LatestData.Clear()
_TempMediaList.Clear()
_TempPostsList.Clear()
If Not Responser Is Nothing Then Responser.Dispose()
@@ -1271,6 +1426,7 @@ BlockNullPicture:
ReadOnly Property Key As String
Property DownloadImages As Boolean
Property DownloadVideos As Boolean
Property DownloadMissingOnly As Boolean
Property ScriptUse As Boolean
Property ScriptData As String
Function GetLVI(ByVal Destination As ListView) As ListViewItem
@@ -1285,10 +1441,12 @@ BlockNullPicture:
''' </summary>
Function Delete() As Integer
Function MoveFiles(ByVal CollectionName As String) As Boolean
Function CopyFiles(ByVal DestinationPath As SFile, Optional ByVal e As ErrorsDescriber = Nothing) As Boolean
Sub OpenFolder()
ReadOnly Property Self As IUserData
Property DownloadTopCount As Integer?
Property DownloadToDate As Date?
Property DownloadDateFrom As Date?
Property DownloadDateTo As Date?
Sub SetEnvironment(ByRef h As SettingsHost, ByVal u As UserInfo, ByVal _LoadUserInformation As Boolean,
Optional ByVal AttachUserInfo As Boolean = True)
ReadOnly Property Disposed As Boolean

View File

@@ -79,7 +79,7 @@ Namespace API.Imgur
End If
Return Nothing
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.ShowMainMsg + EDP.SendInLog, ex, "Imgur standalone downloader: fetch media error")
Return ErrorsDescriber.Execute(EDP.ShowMainMsg + EDP.SendInLog + EDP.ReturnValue, ex, "Imgur standalone downloader: fetch media error")
End Try
End Function
Private Shared Function DownloadingException(ByVal ex As Exception, ByVal Message As String,

View File

@@ -11,15 +11,6 @@ Namespace API.Instagram
Friend Module Declarations
Friend Const InstagramSite As String = "Instagram"
Friend ReadOnly FilesPattern As RParams = RParams.DMS(".+?([^/\?]+?\.[\w\d]{3,4})(?=(\?|\Z))", 1, EDP.ReturnValue)
Friend ReadOnly Property DateProvider As New JsonDate
Friend Class JsonDate : Implements ICustomProvider
Private Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider,
Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert
Return ADateTime.ParseUnicode(Value)
End Function
Private Function GetFormat(ByVal FormatType As Type) As Object Implements IFormatProvider.GetFormat
Throw New NotImplementedException("GetFormat is not available in this context")
End Function
End Class
Friend ReadOnly Property DateProvider As New CustomProvider(Function(v, d, p, n, e) ADateTime.ParseUnicode(v))
End Module
End Namespace

View File

@@ -7,19 +7,18 @@
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Toolbars
Namespace API.Instagram
Friend Class OptionsForm : Implements IOkCancelToolbar
Private ReadOnly MyDefs As DefaultFormOptions
Friend Class OptionsForm
Private WithEvents MyDefs As DefaultFormOptions
Private ReadOnly Property MyExchangeOptions As EditorExchangeOptions
Friend Sub New(ByRef ExchangeOptions As EditorExchangeOptions)
InitializeComponent()
MyExchangeOptions = ExchangeOptions
MyDefs = New DefaultFormOptions
MyDefs = New DefaultFormOptions(Me, Settings.Design)
End Sub
Private Sub OptionsForm_Load(sender As Object, e As EventArgs) Handles Me.Load
With MyDefs
.MyViewInitialize(Me, Settings.Design, True)
.MyViewInitialize(True)
.AddOkCancelToolbar()
With MyExchangeOptions
CH_GET_STORIES.Checked = .GetStories
@@ -28,15 +27,12 @@ Namespace API.Instagram
.EndLoaderOperations()
End With
End Sub
Private Sub OK() Implements IOkCancelToolbar.OK
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
With MyExchangeOptions
.GetStories = CH_GET_STORIES.Checked
.GetTagged = CH_GET_TAGGED.Checked
End With
MyDefs.CloseForm()
End Sub
Private Sub Cancel() Implements IOkCancelToolbar.Cancel
MyDefs.CloseForm(DialogResult.Cancel)
End Sub
End Class
End Namespace

View File

@@ -10,7 +10,7 @@ Imports SCrawler.API.Base
Imports SCrawler.Plugin
Imports SCrawler.Plugin.Attributes
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Tools
Imports PersonalUtilities.Tools.WEB
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.XML.Base
Imports PersonalUtilities.Functions.RegularExpressions
@@ -55,7 +55,7 @@ Namespace API.Instagram
Return Nothing
End Function
Private Function GetFormat(ByVal FormatType As Type) As Object Implements IFormatProvider.GetFormat
Throw New NotImplementedException()
Throw New NotImplementedException("[GetFormat] is not available in the context of [TimersChecker]")
End Function
End Class
Private Class TaggedNotifyLimitChecker : Implements IFieldsCheckerProvider
@@ -73,7 +73,7 @@ Namespace API.Instagram
End If
End Function
Private Function GetFormat(ByVal FormatType As Type) As Object Implements IFormatProvider.GetFormat
Throw New NotImplementedException()
Throw New NotImplementedException("[GetFormat] is not available in the context of [TaggedNotifyLimitChecker]")
End Function
End Class
#End Region
@@ -186,29 +186,23 @@ Namespace API.Instagram
End With
End Sub
#End Region
Friend Overrides ReadOnly Property Responser As WEB.Response
Private Initialized As Boolean = False
#End Region
#Region "Initializer"
Friend Sub New(ByRef _XML As XmlFile, ByVal GlobalPath As SFile)
MyBase.New(InstagramSite)
Responser = New WEB.Response($"{SettingsFolderName}\Responser_{Site}.xml")
MyBase.New(InstagramSite, "instagram.com")
Dim app_id$ = String.Empty
Dim www_claim$ = String.Empty
Dim token$ = String.Empty
With Responser
If .File.Exists Then
.LoadSettings()
If .Headers.Count > 0 Then
With .Headers
If .ContainsKey(Header_CSRF_TOKEN) Then token = .Item(Header_CSRF_TOKEN)
If .ContainsKey(Header_IG_APP_ID) Then app_id = .Item(Header_IG_APP_ID)
If .ContainsKey(Header_IG_WWW_CLAIM) Then www_claim = .Item(Header_IG_WWW_CLAIM)
End With
Else
.CookiesDomain = "instagram.com"
.SaveSettings()
End If
End With
@@ -234,13 +228,12 @@ Namespace API.Instagram
TaggedNotifyLimit = New PropertyValue(200)
TaggedNotifyLimitProvider = New TaggedNotifyLimitChecker
DownloadingErrorDate = New XMLValue(Of Date) With {
.Provider = New XMLValueConversionProvider(Function(ss, vv) AConvert(Of String)(vv, AModes.Var, Nothing))}
DownloadingErrorDate = New XMLValue(Of Date) With {.Provider = New XMLValueConversionProvider(Function(ss, vv) AConvert(Of String)(vv, AModes.Var, Nothing))}
DownloadingErrorDate.SetExtended("InstagramDownloadingErrorDate", Now.AddYears(-10), _XML, n)
LastDownloadDate = New XMLValue(Of Date)("LastDownloadDate", Now.AddDays(-1), _XML, n)
LastRequestsCount = New XMLValue(Of Integer)("LastRequestsCount", 0, _XML, n)
LastRequestsCountLabel = New PropertyValue(LastRequestsCountLabelStr.Invoke(LastRequestsCount.Value))
AddHandler LastRequestsCount.OnValueChanged, Sub(sender, __name, __value) LastRequestsCountLabel.Value = LastRequestsCountLabelStr.Invoke(__value)
AddHandler LastRequestsCount.OnValueChanged, Sub(sender, __name, __value) LastRequestsCountLabel.Value = LastRequestsCountLabelStr.Invoke(DirectCast(__value, Existable(Of Integer)).Value)
UrlPatternUser = "https://www.instagram.com/{0}/"
UserRegex = RParams.DMS("[htps:/]{7,8}.*?instagram.com/([^/]+)", 1)
@@ -250,6 +243,7 @@ Namespace API.Instagram
End Sub
Friend Overrides Sub EndInit()
Initialized = True
MyBase.EndInit()
End Sub
#End Region
#Region "PropertiesDataChecker"
@@ -288,7 +282,7 @@ Namespace API.Instagram
Return True
ElseIf v = -1 Then
Return MsgBoxE({"You turn off notifications for tagged posts. This is highly undesirable. Do you still want to do it?",
"Disabling tagged notification limits "}, MsgBoxStyle.YesNo) = MsgBoxResult.Yes
"Disabling tagged notification limits"}, MsgBoxStyle.YesNo) = MsgBoxResult.Yes
Else
Return False
End If

View File

@@ -104,11 +104,7 @@ Namespace API.Instagram
End Try
End Sub
Private _InstaHash As String = String.Empty
Friend Enum Sections
Timeline
Tagged
Stories
End Enum
Private Enum Sections : Timeline : Tagged : Stories : End Enum
Private Const StoriesFolder As String = "Stories"
Private Const TaggedFolder As String = "Tagged"
#Region "429 bypass"
@@ -187,7 +183,7 @@ Namespace API.Instagram
Dim m As New MMessage("You have not entered a valid posts limit", "Tagged posts download limit", {tryBtt, selectBtt, cancelBtt})
Dim mh As New MMessage("", "Tagged posts download limit", {"Confirm", tryBtt, selectBtt, cancelBtt}) With {.ButtonsPerRow = 2}
Do
v = AConvert(Of Integer)(InputBoxE(aStr, "Tagged posts download limit", CInt(MySiteSettings.TaggedNotifyLimit.Value)), Nothing)
v = AConvert(Of Integer)(InputBoxE(aStr, "Tagged posts download limit", CInt(MySiteSettings.TaggedNotifyLimit.Value)), AModes.Var, Nothing)
If v.HasValue Then
mh.Text = $"You have entered a limit of {v.Value.NumToString(p)} posts"
Select Case MsgBoxE(mh).Index
@@ -251,6 +247,7 @@ Namespace API.Instagram
Try
Dim n As EContainer, nn As EContainer, node As EContainer
Dim HasNextPage As Boolean = False
Dim Pinned As Boolean
Dim EndCursor$ = String.Empty
Dim PostID$ = String.Empty, PostDate$ = String.Empty, SpecFolder$ = String.Empty
Dim TaggedCount%
@@ -300,7 +297,7 @@ Namespace API.Instagram
RequestsCount += 1
ThrowAny(Token)
'Data
'Parsing
If Not r.IsEmptyString Then
Using j As EContainer = JsonDocument.Parse(r).XmlIfNothing
n = j.ItemF(ENode).XmlIfNothing
@@ -321,14 +318,21 @@ Namespace API.Instagram
If IsSavedPosts Then
PostID = node.Value("shortcode")
If Not PostID.IsEmptyString Then
If _TempPostsList.Contains(PostID) Then Throw New ExitException(_DownloadComplete) Else _SavedPostsIDs.Add(PostID)
If _TempPostsList.Contains(PostID) Then Throw New ExitException(_DownloadComplete) 'Else _SavedPostsIDs.Add(PostID)
End If
End If
Else
PostID = node.Value("id")
If Not PostID.IsEmptyString And _TempPostsList.Contains(PostID) Then Throw New ExitException(_DownloadComplete)
Pinned = CBool(If(node("pinned_for_users")?.Count, 0))
If Not PostID.IsEmptyString And _TempPostsList.Contains(PostID) And Not Pinned Then Throw New ExitException(_DownloadComplete)
_TempPostsList.Add(PostID)
PostDate = node.Value("taken_at_timestamp")
If Not CheckDatesLimit(PostDate, DateProvider) Then Throw New ExitException(_DownloadComplete)
If IsSavedPosts Then
_SavedPostsIDs.Add(PostID)
Else
Select Case CheckDatesLimit(PostDate, DateProvider)
Case DateResult.Skip : Continue For
Case DateResult.Exit : If Not Pinned Then Throw New ExitException(_DownloadComplete)
End Select
ObtainMedia(node, PostID, PostDate, SpecFolder)
End If
Next
@@ -342,8 +346,7 @@ Namespace API.Instagram
_TempPostsList.Add(PostID)
ObtainMedia2(nn, PostID, SpecFolder)
DownloadedTags += 1
If DownloadTagsLimit.HasValue AndAlso DownloadedTags >= DownloadTagsLimit.Value Then _
Throw New ExitException(_DownloadComplete)
If DownloadTagsLimit.HasValue AndAlso DownloadedTags >= DownloadTagsLimit.Value Then Throw New ExitException(_DownloadComplete)
Next
If TaggedLimitsNotifications Then
TaggedCount = j.Value("total_count").FromXML(Of Integer)(0)
@@ -399,7 +402,8 @@ Namespace API.Instagram
Dim e As New ErrorsDescriber(EDP.ThrowException)
For i% = _Index To _SavedPostsIDs.Count - 1
_Index = i
URL = $"https://instagram.com/p/{_SavedPostsIDs(i)}/?__a=1"
'URL = $"https://instagram.com/p/{_SavedPostsIDs(i)}/?__a=1"
URL = $"https://i.instagram.com/api/v1/media/{_SavedPostsIDs(i)}/info/"
ThrowAny(Token)
NextRequest(((i + 1) Mod 5) = 0)
ThrowAny(Token)
@@ -442,9 +446,26 @@ Namespace API.Instagram
ProcessException(DoEx, Token, $"downloading saved posts error [{URL}]")
End Try
End Sub
Protected Overrides Sub ReparseVideo(ByVal Token As CancellationToken)
End Sub
#End Region
#Region "Code ID converters"
Friend Shared Function CodeToID(ByVal Code As String) As String
Const CodeSymbols$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
Try
If Not Code.IsEmptyString Then
Dim c As Char
Dim id& = 0
For i% = 0 To Code.Length - 1
c = Code(i)
id = (id * 64) + CodeSymbols.IndexOf(c)
Next
Return id
Else
Return String.Empty
End If
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.SendInLog, ex, $"[API.Instagram.UserData.CodeToID({Code})", String.Empty)
End Try
End Function
#End Region
#Region "Obtain Media"
Private Sub ObtainMedia(ByVal node As EContainer, ByVal PostID As String, ByVal PostDate As String, ByVal SpecFolder As String)
@@ -696,6 +717,7 @@ Namespace API.Instagram
Try
If Not URL.IsEmptyString AndAlso URL.Contains("instagram.com") Then
Dim PID$ = RegexReplace(URL, RParams.DMS(".*?instagram.com/p/([_\w\d]+)", 1))
If Not PID.IsEmptyString AndAlso Not ACheck(Of Long)(PID) Then PID = CodeToID(PID)
If Not PID.IsEmptyString Then
Using t As New UserData
t.SetEnvironment(Settings(_Settings.GetType.GetCustomAttribute(Of Plugin.Attributes.Manifest)().GUID), Nothing, False, False)

View File

@@ -9,9 +9,9 @@
Imports PersonalUtilities.Tools
Imports PersonalUtilities.Forms.Toolbars
Imports PersonalUtilities.Functions.XML
Imports System.Threading
Imports SCrawler.API.Base
Imports SCrawler.Plugin.Hosts
Imports System.Threading
Imports SCrawler.API.Reddit.RedditViewExchange
Imports View = SCrawler.API.Reddit.IRedditView.View
Imports Period = SCrawler.API.Reddit.IRedditView.Period
@@ -112,7 +112,7 @@ Namespace API.Reddit
ChannelExistentUserNames.ListAddList((From p As UserPost In PostsAll
Where Not p.UserID.IsEmptyString AndAlso
Settings.UsersList.Exists(Function(u) u.Site = Site And u.Name = p.UserID)
Select p.UserID), LAP.NotContainsOnly)
Select p.UserID), LNC)
ChannelExistentUserNames.RemoveAll(Function(u) Not Settings.UsersList.Exists(Function(uu) uu.Site = Site And uu.Name = u))
End If
End Sub
@@ -165,7 +165,7 @@ Namespace API.Reddit
If Not ViewMode = View.New And AutoGetLimits Then
Return _DownloadLimitPost
Else
Dim PID$ = ListAddList(Nothing, Posts, LAP.NotContainsOnly).ListAddList(PostsLatest, LAP.NotContainsOnly).ListSort.FirstOrDefault.ID
Dim PID$ = ListAddList(Nothing, Posts, LNC).ListAddList(PostsLatest, LNC).ListSort.FirstOrDefault.ID
If AutoGetLimits And Not PID.IsEmptyString Then
Return PID
Else
@@ -233,11 +233,7 @@ Namespace API.Reddit
Return New Channel(f)
End Operator
Public Overrides Function ToString() As String
If Not Name.IsEmptyString Then
Return Name
Else
Return ID
End If
Return If(Name.IsEmptyString, ID, Name)
End Function
Friend Sub Delete()
File.Delete(, SFODelete.DeleteToRecycleBin)
@@ -261,7 +257,7 @@ Namespace API.Reddit
.DownloadData(Token)
End With
Dim b% = Posts.Count
Posts.ListAddList(d.GetNewChannelPosts(), LAP.NotContainsOnly)
Posts.ListAddList(d.GetNewChannelPosts(), LNC)
If Posts.Count - b > 0 Then CountOfLoadedPostsPerSession.Add(Posts.Count - b)
Posts.Sort()
LatestParsedDate = If(Posts.FirstOrDefault(Function(pp) pp.Date.HasValue).Date, LatestParsedDate)
@@ -364,8 +360,8 @@ Namespace API.Reddit
UpdateUsersStats()
If Not ViewMode = View.New Then
Dim l As New List(Of String)
If Posts.Count > 0 Or PostsLatest.Count > 0 Then l.ListAddList((From p In PostsAll Where Not p.ID.IsEmptyString Select p.ID), LAP.NotContainsOnly)
l.ListAddList(PostsNames, LAP.NotContainsOnly)
If Posts.Count > 0 Or PostsLatest.Count > 0 Then l.ListAddList((From p In PostsAll Where Not p.ID.IsEmptyString Select p.ID), LNC)
l.ListAddList(PostsNames, LNC)
If l.Count > 0 Then TextSaver.SaveTextToFile(l.ListToString("|"), FilePosts, True,, EDP.SendInLog)
End If
Using x As New XmlFile With {.AllowSameNames = True, .Name = "Channel"}

View File

@@ -12,8 +12,16 @@ 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\"
Friend Shared ReadOnly Property ChannelsPath As SFile
Get
Return $"{SettingsFolderName}\Channels\"
End Get
End Property
Friend Shared ReadOnly Property ChannelsPathCache As SFile
Get
Return $"{Settings.GlobalPath.Value.PathWithSeparator}_CachedData\"
End Get
End Property
Private ReadOnly Channels As List(Of Channel)
Friend Structure ChannelImage : Implements IEquatable(Of ChannelImage)
Friend File As SFile
@@ -42,7 +50,7 @@ Namespace API.Reddit
Return Nothing
End If
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.SendInLog + EDP.ReturnValue, ex)
Return ErrorsDescriber.Execute(EDP.SendInLog + EDP.ReturnValue, ex, "[API.Reddit.ChannelsCollection.GetUserFiles]")
End Try
End Function
Friend Sub UpdateUsersStats()
@@ -97,7 +105,7 @@ Namespace API.Reddit
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}
Throw New ArgumentException($"Channel ID [{ChannelID}] not found in channel collection", "ChannelID") With {.HelpLink = 1}
End Get
End Property
Friend Sub DownloadData(ByVal Token As CancellationToken, Optional ByVal SkipExists As Boolean = True,

View File

@@ -17,26 +17,8 @@ Namespace API.Reddit
New NodeParams("children", True, True, True)}
Friend ReadOnly UrlBasePattern As RParams = RParams.DM("(?<=/)([^/]+?\.[\w]{3,4})(?=(\?|\Z))", 0)
Friend ReadOnly VideoRegEx As RParams = RParams.DM("http.{0,1}://[^" & Chr(34) & "]+?mp4", 0)
Friend ReadOnly DateProvider As New JsonDate
Friend ReadOnly DateProviderChannel As New JsonDateChannel
Private ReadOnly EUR_PROVIDER As New ANumbers(ANumbers.Cultures.EUR)
Friend Class JsonDate : Implements ICustomProvider
Friend Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider,
Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert
Return ADateTime.ParseUnicodeJS(Value, NothingArg, e)
End Function
Private Function GetFormat(ByVal FormatType As Type) As Object Implements IFormatProvider.GetFormat
Throw New NotImplementedException("GetFormat is not available in this context")
End Function
End Class
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 is not available in this context")
End Function
End Class
Friend ReadOnly DateProvider As New CustomProvider(Function(v, d, p, n, e) ADateTime.ParseUnicodeJS(v, n, e))
Friend ReadOnly DateProviderChannel As New CustomProvider(Function(v, d, p, n, e) ADateTime.ParseUnicode(AConvert(Of Integer)(v, EUR_PROVIDER, v), n, e))
End Module
End Namespace

View File

@@ -15,12 +15,10 @@ Namespace API.Reddit
Friend Module M3U8_Declarations
Friend ReadOnly BaseUrlPattern As RParams = RParams.DM("([htps:/]{7,8}.+?/.+?)(?=/)", 0, EDP.ReturnValue)
''' <summary>Video</summary>
Friend ReadOnly PlayListRegEx_1 As RParams = RParams.DM("(#EXT-X-STREAM-INF)(.+)(RESOLUTION=)(\d+)(.+?[\r\n]{1,2})(.+?)([\r\n]{1,2})", 0,
RegexReturn.List, EDP.SendInLog, EDP.ReturnValue)
Friend ReadOnly PlayListRegEx_1 As RParams = RParams.DM("(#EXT-X-STREAM-INF)(.+)(RESOLUTION=)(\d+)(.+?[\r\n]{1,2})(.+?)([\r\n]{1,2})", 0, RegexReturn.List)
''' <summary>Audio, Video</summary>
Friend ReadOnly PlayListRegEx_2 As RParams = RParams.DM("(?<=#EXT-X-BYTERANGE.+?[\r\n]{1,2})(.+)(?=[\r\n]{0,2})", 0,
RegexReturn.List, EDP.SendInLog, EDP.ReturnValue)
Friend ReadOnly PlayListAudioRegEx As RParams = RParams.DM("(HLS_AUDIO_(\d+)[^""]+)", 0, RegexReturn.List, EDP.SendInLog, EDP.ReturnValue)
Friend ReadOnly PlayListRegEx_2 As RParams = RParams.DM("(?<=#EXT-X-BYTERANGE.+?[\r\n]{1,2})(.+)(?=[\r\n]{0,2})", 0, RegexReturn.List)
Friend ReadOnly PlayListAudioRegEx As RParams = RParams.DM("(HLS_AUDIO_(\d+)[^""]+)", 0, RegexReturn.List)
Friend ReadOnly DPED As New ErrorsDescriber(EDP.SendInLog + EDP.ReturnValue)
End Module
End Namespace
@@ -80,11 +78,11 @@ Namespace API.Reddit
If Not r.IsEmptyString Then
Dim l As New List(Of Resolution)
If Type = Types.Video Then
l = FNF.RegexFields(Of Resolution)(r, {PlayListRegEx_1}, {6, 4})
l = RegexFields(Of Resolution)(r, {PlayListRegEx_1}, {6, 4})
Else
Try
l = FNF.RegexFields(Of Resolution)(r, {PlayListAudioRegEx}, {1, 2})
Catch anull As FNF.RegexFieldsTextBecameNullException
l = RegexFields(Of Resolution)(r, {PlayListAudioRegEx}, {1, 2})
Catch anull As RegexFieldsTextBecameNullException
l.Clear()
End Try
End If

View File

@@ -7,17 +7,16 @@
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Toolbars
Imports CView = SCrawler.API.Reddit.IRedditView.View
Imports CPeriod = SCrawler.API.Reddit.IRedditView.Period
Namespace API.Reddit
Friend Class RedditViewSettingsForm : Implements IOkCancelToolbar
Private ReadOnly MyDefs As DefaultFormOptions
Friend Class RedditViewSettingsForm
Private WithEvents MyDefs As DefaultFormOptions
Private ReadOnly Property MyOptions As IRedditView
Friend Sub New(ByRef opt As IRedditView)
InitializeComponent()
MyOptions = opt
MyDefs = New DefaultFormOptions
MyDefs = New DefaultFormOptions(Me, Settings.Design)
End Sub
Private Sub ChannelSettingsForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
@@ -29,7 +28,7 @@ Namespace API.Reddit
End If
If Not n.IsEmptyString Then Text = n
With MyDefs
.MyViewInitialize(Me, Settings.Design, True)
.MyViewInitialize(True)
.AddOkCancelToolbar()
Select Case MyOptions.ViewMode
Case CView.Hot : OPT_VIEW_MODE_HOT.Checked = True
@@ -51,7 +50,7 @@ Namespace API.Reddit
MyDefs.InvokeLoaderError(ex)
End Try
End Sub
Private Sub OK() Implements IOkCancelToolbar.OK
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
With MyOptions
Select Case True
Case OPT_VIEW_MODE_HOT.Checked : .ViewMode = CView.Hot
@@ -69,9 +68,6 @@ Namespace API.Reddit
End With
MyDefs.CloseForm()
End Sub
Private Sub Cancel() Implements IOkCancelToolbar.Cancel
MyDefs.CloseForm(DialogResult.Cancel)
End Sub
Private Sub OPT_VIEW_MODE_NEW_CheckedChanged(sender As Object, e As EventArgs) Handles OPT_VIEW_MODE_NEW.CheckedChanged
ChangePeriodEnabled()
End Sub

View File

@@ -9,7 +9,7 @@
Imports SCrawler.API.Base
Imports SCrawler.Plugin
Imports SCrawler.Plugin.Attributes
Imports PersonalUtilities.Tools
Imports PersonalUtilities.Tools.WEB
Imports PersonalUtilities.Functions.RegularExpressions
Imports DownDetector = SCrawler.API.Base.DownDetector
Imports Download = SCrawler.Plugin.ISiteSettings.Download
@@ -30,19 +30,11 @@ Namespace API.Reddit
Friend ReadOnly Property SavedPostsUserName As PropertyValue
<PropertyOption(ControlText:="Use M3U8", ControlToolTip:="Use M3U8 or mp4 for Reddit videos"), PXML>
Friend ReadOnly Property UseM3U8 As PropertyValue
Friend Overrides ReadOnly Property Responser As WEB.Response
Friend Sub New()
MyBase.New(RedditSite)
Responser = New WEB.Response($"{SettingsFolderName}\Responser_{Site}.xml")
MyBase.New(RedditSite, "reddit.com")
With Responser
If .File.Exists Then
.LoadSettings()
Else
.CookiesDomain = "reddit.com"
.Decoders.Add(SymbolsConverter.Converters.Unicode)
.SaveSettings()
End If
If .Decoders.Count = 0 OrElse Not .Decoders.Contains(SymbolsConverter.Converters.Unicode) Then _
.Decoders.Add(SymbolsConverter.Converters.Unicode) : .SaveSettings()
End With
SavedPostsUserName = New PropertyValue(String.Empty, GetType(String))
UseM3U8 = New PropertyValue(True)
@@ -109,5 +101,8 @@ Namespace API.Reddit
Using f As New RedditViewSettingsForm(Options) : f.ShowDialog() : End Using
End If
End Sub
Friend Overrides Function GetUserPostUrl(ByVal UserID As String, ByVal PostID As String) As String
Return $"https://www.reddit.com/comments/{PostID.Split("_").LastOrDefault}/"
End Function
End Class
End Namespace

View File

@@ -58,7 +58,7 @@ Namespace API.Reddit
Friend Property AutoGetLimits As Boolean = True Implements IChannelLimits.AutoGetLimits
#End Region
Friend Property ChannelInfo As Channel
Private ReadOnly ChannelPostsNames As New List(Of String)
Private ReadOnly ChannelPostsNames As 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
@@ -150,6 +150,8 @@ Namespace API.Reddit
End Sub
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
_TotalPostsDownloaded = 0
'PENDING: Reddit ReparseMissing (DownloadDataF)
'If Not IsSavedPosts AndAlso (Not IsChannel OrElse ChannelInfo Is Nothing) Then ReparseMissing(Token)
If IsSavedPosts Then
DownloadDataChannel(String.Empty, Token)
ElseIf IsChannel Then
@@ -163,6 +165,8 @@ Namespace API.Reddit
End If
If DownloadTopCount.HasValue Then DownloadLimitCount = DownloadTopCount
End If
If SaveToCache AndAlso Not Responser.Decoders.Contains(SymbolsConverter.Converters.HTML) Then _
Responser.Decoders.Add(SymbolsConverter.Converters.HTML)
DownloadDataChannel(String.Empty, Token)
If ChannelInfo Is Nothing Then _TempPostsList.ListAddList(_TempMediaList.Select(Function(m) m.Post.ID), LNC)
Else
@@ -227,7 +231,10 @@ Namespace API.Reddit
Continue For
End If
If nn.Contains("created") Then PostDate = nn("created").Value Else PostDate = String.Empty
If DownloadToDate.HasValue AndAlso Not CheckDatesLimit(PostDate, DateTrueProvider(IsChannel)) Then Exit Sub
Select Case CheckDatesLimit(PostDate, DateTrueProvider(IsChannel))
Case DateResult.Skip : Continue For
Case DateResult.Exit : Exit Sub
End Select
_ItemsBefore = _TempMediaList.Count
added = True
@@ -370,9 +377,11 @@ Namespace API.Reddit
ElseIf Not s.Value({"media", "reddit_video"}, "fallback_url").IsEmptyString Then
tmpUrl = s.Value({"media", "reddit_video"}, "fallback_url")
If SaveToCache Then
tmpUrl = s.Value("thumbnail")
'TODELETE: Reddit thumbnail -> GetVideoRedditPreview
'tmpUrl = s.Value("thumbnail")
tmpUrl = GetVideoRedditPreview(s)
If Not tmpUrl.IsEmptyString Then
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, tmpUrl, PostID, PostDate, _UserID, IsChannel), LNC)
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, tmpUrl, PostID, PostDate, _UserID, IsChannel, False), LNC)
_TotalPostsDownloaded += 1
End If
ElseIf UseM3U8 AndAlso Not s.Value({"media", "reddit_video"}, "hls_url").IsEmptyString Then
@@ -470,6 +479,38 @@ Namespace API.Reddit
Return False
End Try
End Function
Private Function GetVideoRedditPreview(ByVal Node As EContainer) As String
Try
If Not Node Is Nothing Then
Dim n As EContainer = Node.ItemF({"preview", "images", 0})
Dim DestNode$() = Nothing
If If(n?.Count, 0) > 0 Then
If If(n("resolutions")?.Count, 0) > 0 Then
DestNode = {"resolutions"}
ElseIf If(n({"variants", "nsfw", "resolutions"})?.Count, 0) > 0 Then
DestNode = {"variants", "nsfw", "resolutions"}
End If
If Not DestNode Is Nothing Then
With n(DestNode)
Dim sl As List(Of Sizes) = .Select(Function(e) New Sizes(e.Value("width"), e.Value("url"))).
ListWithRemove(Function(ss) ss.HasError Or ss.Data.IsEmptyString)
If sl.ListExists Then
Dim s As Sizes
sl.Sort()
s = sl.First
sl.Clear()
Return s.Data
End If
End With
End If
End If
End If
Return String.Empty
Catch ex As Exception
ProcessException(ex, Nothing, "reddit video preview parsing error", False)
Return String.Empty
End Try
End Function
Protected Overrides Sub ReparseVideo(ByVal Token As CancellationToken)
Try
ThrowAny(Token)
@@ -507,6 +548,72 @@ Namespace API.Reddit
ProcessException(ex, Token, "video reparsing error", False)
End Try
End Sub
Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken)
Dim rList As New List(Of Integer)
Try
If _ContentList.Exists(MissingFinder) Then
Dim m As UserMedia
Dim j As EContainer, ss As EContainer
Dim r$, tmpUrl$, PostDate$, _UserID$
Dim err As New ErrorsDescriber(EDP.ReturnValue)
Dim node As Object() = {"data", "children", 0, "data"}
Dim eCount As Predicate(Of EContainer) = Function(e) e.Count > 0
Dim cItems As Predicate(Of EContainer) = Function(e) If(e.ItemF(node)?.Count, 0) > 0
For i% = 0 To _ContentList.Count - 1
m = _ContentList(i)
If m.State = UStates.Missing AndAlso Not m.Post.ID.IsEmptyString Then
ThrowAny(Token)
r = Responser.GetResponse($"https://www.reddit.com/comments/{m.Post.ID.Split("_").LastOrDefault}/.json",, err)
If Not r.IsEmptyString Then
j = JsonDocument.Parse(r, err)
If Not j Is Nothing Then
If j.Contains(cItems) Then
With j.ItemF({cItems}).ItemF(node)
If .Contains("created") Then PostDate = .Item("created").Value Else PostDate = String.Empty
_UserID = .Value("author")
tmpUrl = .Value("url")
If Not tmpUrl.IsEmptyString AndAlso tmpUrl.StringContains({"redgifs.com", "gfycat.com"}) Then
_TempMediaList.ListAddValue(MediaFromData(UTypes.VideoPre, tmpUrl, m.Post.ID, PostDate, _UserID, IsChannel), LNC)
_TotalPostsDownloaded += 1
ElseIf Not .Value({"media", "reddit_video"}, "fallback_url").IsEmptyString Then
tmpUrl = .Value({"media", "reddit_video"}, "fallback_url")
If UseM3U8 AndAlso Not .Value({"media", "reddit_video"}, "hls_url").IsEmptyString Then
_TempMediaList.ListAddValue(MediaFromData(UTypes.m3u8, .Value({"media", "reddit_video"}, "hls_url"),
m.Post.ID, PostDate, _UserID, IsChannel), LNC)
Else
'_TempMediaList.ListAddValue(MediaFromData(UTypes.VideoPre + UTypes.m3u8, tmpUrl, PostID, PostDate, _UserID, IsChannel), LNC)
_TempMediaList.ListAddValue(MediaFromData(UTypes.Video, tmpUrl, m.Post.ID, PostDate, _UserID, IsChannel), LNC)
_TotalPostsDownloaded += 1
End If
ElseIf CreateImgurMedia(tmpUrl, m.Post.ID, PostDate, _UserID, IsChannel) Then
_TotalPostsDownloaded += 1
ElseIf If(.Item("media_metadata")?.Count, 0) > 0 Then
DownloadGallery(.Self, m.Post.ID, PostDate, _UserID, SaveToCache)
_TotalPostsDownloaded += 1
ElseIf .Contains("preview") Then
ss = .ItemF({"preview", "images", eCount, "source", "url"}).XmlIfNothing
If Not ss.Value.IsEmptyString Then
_TempMediaList.ListAddValue(MediaFromData(UTypes.Picture, ss.Value, m.Post.ID, PostDate, _UserID, IsChannel), LNC)
_TotalPostsDownloaded += 1
End If
End If
End With
End If
j.Dispose()
End If
End If
End If
Next
End If
Catch ex As Exception
ProcessException(ex, Token, "missing data downloading error")
Finally
If rList.Count > 0 Then
For i% = rList.Count - 1 To 0 Step -1 : _ContentList.RemoveAt(rList(i)) : Next
rList.Clear()
End If
End Try
End Sub
Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal resp As Response) As IEnumerable(Of UserMedia)
Try
If Not URL.IsEmptyString AndAlso URL.Contains("redgifs") Then
@@ -526,12 +633,13 @@ Namespace API.Reddit
#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
Optional ByVal _UserID As String = "", Optional ByVal IsChannel As Boolean = False,
Optional ByVal ReplacePreview As Boolean = True) 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 = UrlToFile(m.URL) Else m.File = Nothing
If m.URL.Contains("preview") Then m.URL = $"https://i.redd.it/{m.File.File}"
If ReplacePreview And 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, DateTrueProvider(IsChannel), Nothing) Else m.Post.Date = Nothing
Return m
End Function
@@ -561,6 +669,8 @@ Namespace API.Reddit
_ContentNew.RemoveAll(Function(c) c.URL.IsEmptyString)
If _ContentNew.Count > 0 Then
MyFile.Exists(SFO.Path)
Dim MissingErrorsAdd As Boolean = Settings.AddMissingErrorsToLog
Dim IsImgurStuff As Boolean
Dim MyDir$
If Not IsSavedPosts AndAlso (IsChannel And SaveToCache And Not ChannelInfo Is Nothing) Then
MyDir = ChannelInfo.CachePath.PathNoSeparator
@@ -629,7 +739,7 @@ Namespace API.Reddit
Dim m$
Using w As New WebClient
If vsf Then SFileShares.SFileExists($"{MyDir}\Video\", SFO.Path)
Progress.TotalCount += _ContentNew.Count
Progress.Maximum += _ContentNew.Count
For i = 0 To _ContentNew.Count - 1
ThrowAny(Token)
v = _ContentNew(i)
@@ -651,6 +761,7 @@ Namespace API.Reddit
If (Not m.IsEmptyString AndAlso Not HashList.Contains(m)) Or Not (v.Type = UTypes.Picture Or
v.Type = UTypes.GIF) Or Not UseMD5 Or ImgurUrls.Count > 0 Then
isImgurStuff = ImgurUrls.Count > 0
Do
If Not cached And Not m.IsEmptyString Then HashList.Add(m)
v.MD5 = m
@@ -695,7 +806,11 @@ Namespace API.Reddit
dCount += 1
End If
Catch wex As Exception
If Not IsChannel Then ErrorDownloading(f, v.URL)
If Not IsChannel Then
If Not IsImgurStuff And MissingErrorsAdd Then ErrorDownloading(f, v.URL)
v.Attempts += 1
v.State = UStates.Missing
End If
End Try
If ImgurUrls.Count > 0 Then ImgurUrls.RemoveAt(0)
Loop While ImgurUrls.Count > 0

View File

@@ -9,15 +9,6 @@
Namespace API.RedGifs
Friend Module Declarations
Friend Const RedGifsSite As String = "RedGifs"
Friend ReadOnly DateProvider As New JsonDate
Friend Class JsonDate : Implements ICustomProvider
Friend Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider,
Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert
Return ADateTime.ParseUnicode(Value, NothingArg, e)
End Function
Private Function GetFormat(ByVal FormatType As Type) As Object Implements IFormatProvider.GetFormat
Throw New NotImplementedException("GetFormat is not available in this context")
End Function
End Class
Friend ReadOnly DateProvider As New CustomProvider(Function(v, d, p, n, e) ADateTime.ParseUnicode(v, n, e))
End Module
End Namespace

View File

@@ -13,6 +13,16 @@ Imports PersonalUtilities.Functions.RegularExpressions
Namespace API.RedGifs
<Manifest("AndyProgram_RedGifs"), UseClassAsIs>
Friend Class SiteSettings : Inherits SiteSettingsBase
Friend Overrides ReadOnly Property Icon As Icon
Get
Return My.Resources.RedGifsIcon
End Get
End Property
Friend Overrides ReadOnly Property Image As Image
Get
Return My.Resources.RedGifsPic32
End Get
End Property
Friend Sub New()
MyBase.New(RedGifsSite, "redgifs.com")
UrlPatternUser = "https://www.redgifs.com/users/{0}/"
@@ -25,5 +35,12 @@ Namespace API.RedGifs
Friend Overrides Function GetSpecialDataF(ByVal URL As String) As IEnumerable(Of UserMedia)
Return Reddit.UserData.GetVideoInfo(URL, Nothing)
End Function
Friend Overrides Function GetUserPostUrl(ByVal UserID As String, ByVal PostID As String) As String
Return $"https://www.redgifs.com/watch/{PostID}"
End Function
Friend Overrides Function Available(ByVal What As ISiteSettings.Download, ByVal Silent As Boolean) As Boolean
'PENDING: RedGifs SiteSettings Available FALSE
Return False
End Function
End Class
End Namespace

View File

@@ -9,10 +9,11 @@
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.RegularExpressions
Imports PersonalUtilities.Tools.WebDocuments.JSON
Imports System.Threading
Imports System.Net
Imports System.Threading
Imports SCrawler.API.Base
Imports UTypes = SCrawler.API.Base.UserMedia.Types
Imports UStates = SCrawler.API.Base.UserMedia.States
Namespace API.RedGifs
Friend Class UserData : Inherits UserDataBase
Friend Sub New()
@@ -20,6 +21,7 @@ Namespace API.RedGifs
Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean)
End Sub
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
ReparseMissing(Token)
DownloadData(1, Token)
End Sub
Private Overloads Sub DownloadData(ByVal Page As Integer, ByVal Token As CancellationToken)
@@ -29,32 +31,19 @@ Namespace API.RedGifs
Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException)
Dim postDate$, postID$
Dim pTotal% = 0
Dim u$
Dim ut As UTypes
If Not r.IsEmptyString Then
Using j As EContainer = JsonDocument.Parse(r).XmlIfNothing
If j.Contains("gifs") Then
pTotal = j.Value("pages").FromXML(Of Integer)(0)
For Each g As EContainer In j("gifs")
postDate = g.Value("createDate")
If Not CheckDatesLimit(postDate, DateProvider) Then Exit Sub
Select Case CheckDatesLimit(postDate, DateProvider)
Case DateResult.Skip : Continue For
Case DateResult.Exit : Exit Sub
End Select
postID = g.Value("id")
If Not _TempPostsList.Contains(postID) Then _TempPostsList.Add(postID) Else Exit For
With g("urls")
If .ListExists Then
u = If(.Item("hd"), .Item("sd")).XmlIfNothingValue
If Not u.IsEmptyString Then
ut = UTypes.Undefined
'Type 1: video
'Type 2: image
Select Case g.Value("type").FromXML(Of Integer)(0)
Case 1 : ut = UTypes.Video
Case 2 : ut = UTypes.Picture
End Select
If Not ut = UTypes.Undefined Then _TempMediaList.ListAddValue(MediaFromData(ut, u, postID, postDate))
End If
End If
End With
ObtainMedia(g, postID, postDate)
Next
End If
End Using
@@ -64,16 +53,84 @@ Namespace API.RedGifs
ProcessException(ex, Token, $"data downloading error [{URL}]")
End Try
End Sub
Protected Overrides Sub ReparseVideo(ByVal Token As CancellationToken)
Private Sub ObtainMedia(ByVal j As EContainer, ByVal PostID As String,
Optional ByVal PostDateStr As String = Nothing, Optional ByVal PostDateDate As Date? = Nothing,
Optional ByVal State As UStates = UStates.Unknown)
With j("urls")
If .ListExists Then
Dim u$ = If(.Item("hd"), .Item("sd")).XmlIfNothingValue
If Not u.IsEmptyString Then
Dim ut As UTypes = UTypes.Undefined
'Type 1: video
'Type 2: image
Select Case j.Value("type").FromXML(Of Integer)(0)
Case 1 : ut = UTypes.Video
Case 2 : ut = UTypes.Picture
End Select
If Not ut = UTypes.Undefined Then _TempMediaList.ListAddValue(MediaFromData(ut, u, PostID, PostDateStr, PostDateDate, State))
End If
End If
End With
End Sub
Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken)
Dim rList As New List(Of Integer)
Try
If _ContentList.Exists(MissingFinder) Then
Dim url$, r$
Dim u As UserMedia
Dim j As EContainer
For i% = 0 To _ContentList.Count - 1
If _ContentList(i).State = UserMedia.States.Missing Then
ThrowAny(Token)
u = _ContentList(i)
If Not u.Post.ID.IsEmptyString Then
url = $"https://api.redgifs.com/v2/gifs/{u.Post.ID}?views=yes&users=yes"
Try
r = Responser.GetResponse(url,, EDP.ThrowException)
If Not r.IsEmptyString Then
j = JsonDocument.Parse(r)
If Not j Is Nothing Then
If If(j("gif")?.Count, 0) > 0 Then
ObtainMedia(j("gif"), u.Post.ID,, u.Post.Date, UStates.Missing)
rList.Add(i)
End If
End If
End If
Catch down_ex As Exception
u.Attempts += 1
_ContentList(i) = u
End Try
Else
rList.Add(i)
End If
End If
Next
End If
Catch dex As ObjectDisposedException When Disposed
Catch ex As Exception
ProcessException(ex, Token, $"missing data downloading error")
Finally
If Not Disposed And rList.Count > 0 Then
For i% = rList.Count - 1 To 0 Step -1 : _ContentList.RemoveAt(rList(i)) : Next
End If
End Try
End Sub
Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
DownloadContentDefault(Token)
End Sub
Private Shared Function MediaFromData(ByVal t As UTypes, ByVal _URL As String, ByVal PostID As String, ByVal PostDate As String) As UserMedia
Private Shared Function MediaFromData(ByVal t As UTypes, ByVal _URL As String, ByVal PostID As String,
ByVal PostDateStr As String, ByVal PostDateDate As Date?, ByVal State As UStates) As UserMedia
_URL = LinkFormatterSecure(RegexReplace(_URL.Replace("\", String.Empty), LinkPattern))
Dim m As New UserMedia(_URL, t) With {.Post = New UserPost With {.ID = PostID}}
If Not m.URL.IsEmptyString Then m.File = CStr(RegexReplace(m.URL, FilesPattern)) : m.URL_BASE = m.URL
If Not PostDate.IsEmptyString Then m.Post.Date = AConvert(Of Date)(PostDate, DateProvider, Nothing) Else m.Post.Date = Nothing
If Not PostDateStr.IsEmptyString Then
m.Post.Date = AConvert(Of Date)(PostDateStr, DateProvider, Nothing)
ElseIf PostDateDate.HasValue Then
m.Post.Date = PostDateDate
Else
m.Post.Date = Nothing
End If
m.State = State
Return m
End Function
Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False) As Integer

View File

@@ -9,7 +9,7 @@
Imports SCrawler.API.Base
Imports SCrawler.Plugin
Imports SCrawler.Plugin.Attributes
Imports PersonalUtilities.Tools
Imports PersonalUtilities.Tools.WEB
Imports PersonalUtilities.Functions.RegularExpressions
Namespace API.Twitter
<Manifest("AndyProgram_Twitter"), SavedPosts, UseClassAsIs>
@@ -33,16 +33,17 @@ Namespace API.Twitter
Private ReadOnly Property Token As PropertyValue
<PropertyOption(ControlText:="Saved posts user name", ControlToolTip:="Personal profile username", LeftOffset:=120), PXML>
Friend ReadOnly Property SavedPostsUserName As PropertyValue
Friend Overrides ReadOnly Property Responser As WEB.Response
Friend Overrides ReadOnly Property Responser As Response
Friend Sub New()
MyBase.New(TwitterSite)
Responser = New WEB.Response($"{SettingsFolderName}\Responser_{Site}.xml")
Responser = New Response($"{SettingsFolderName}\Responser_{Site}.xml")
Dim a$ = String.Empty
Dim t$ = String.Empty
With Responser
If .File.Exists Then
If EncryptCookies.CookiesEncrypted Then .CookiesEncryptKey = SettingsCLS.CookieEncryptKey
.LoadSettings()
With .Headers
If .ContainsKey(Header_Authorization) Then a = .Item(Header_Authorization)
@@ -52,11 +53,11 @@ Namespace API.Twitter
.ContentType = "application/json"
.Accept = "*/*"
.CookiesDomain = "twitter.com"
.Cookies = New CookieKeeper(.CookiesDomain) With {.EncryptKey = SettingsCLS.CookieEncryptKey}
.CookiesEncryptKey = SettingsCLS.CookieEncryptKey
.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", " Not;A Brand"";v=""99"", ""Google Chrome"";v=""91"", ""Chromium"";v=""91""")
.Add("sec-ch-ua-mobile", "?0")
.Add("sec-fetch-dest", "empty")
.Add("sec-fetch-mode", "cors")
@@ -102,5 +103,8 @@ Namespace API.Twitter
Friend Overrides Function GetSpecialDataF(ByVal URL As String) As IEnumerable(Of UserMedia)
Return UserData.GetVideoInfo(URL, Responser)
End Function
Friend Overrides Function GetUserPostUrl(ByVal UserID As String, ByVal PostID As String) As String
Return $"https://twitter.com/{UserID}/status/{PostID}"
End Function
End Class
End Namespace

View File

@@ -13,6 +13,7 @@ Imports PersonalUtilities.Functions.RegularExpressions
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"
@@ -33,6 +34,8 @@ Namespace API.Twitter
Else
If _ContentList.Count > 0 Then _DataNames.ListAddList(_ContentList.Select(Function(c) c.File.File), LAP.ClearBeforeAdd, LAP.NotContainsOnly)
DownloadData(String.Empty, Token)
'PENDING: Twitter ReparseMissing (DownloadDataF)
'ReparseMissing(Token)
End If
End Sub
Private Overloads Sub DownloadData(ByVal POST As String, ByVal Token As CancellationToken)
@@ -41,8 +44,8 @@ Namespace API.Twitter
Dim NextCursor$ = String.Empty
Dim __NextCursor As Predicate(Of EContainer) = Function(e) e.Value({"content", "operation", "cursor"}, "cursorType") = "Bottom"
Dim PostID$ = String.Empty
Dim PostDate$, dName$
Dim m As EContainer, nn As EContainer, s As EContainer
Dim PostDate$ ', dName$
Dim nn As EContainer, s As EContainer ', m As EContainer
Dim NewPostDetected As Boolean = False
Dim ExistsDetected As Boolean = False
@@ -63,7 +66,7 @@ Namespace API.Twitter
Dim r$ = 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
If w.ListExists Then
For Each nn In If(IsSavedPosts, w({"globalObjects", "tweets"}).XmlIfNothing, w)
ThrowAny(Token)
If nn.Count > 0 Then
@@ -84,7 +87,10 @@ Namespace API.Twitter
'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 CheckDatesLimit(PostDate, Declarations.DateProvider) Then Exit Sub
Select Case CheckDatesLimit(PostDate, Declarations.DateProvider)
Case DateResult.Skip : Continue For
Case DateResult.Exit : Exit Sub
End Select
If Not _TempPostsList.Contains(PostID) Then
NewPostDetected = True
@@ -96,22 +102,24 @@ Namespace API.Twitter
If IsSavedPosts OrElse 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
dName = UrlFile(m("media_url").Value)
If Not dName.IsEmptyString AndAlso Not _DataNames.Contains(dName) Then
_DataNames.Add(dName)
_TempMediaList.ListAddValue(MediaFromData(m("media_url").Value,
PostID, PostDate, GetPictureOption(m)), LNC)
End If
End If
Next
End If
End If
'TODELETE: Twitter ObtainMedia
'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
' dName = UrlFile(m("media_url").Value)
' If Not dName.IsEmptyString AndAlso Not _DataNames.Contains(dName) Then
' _DataNames.Add(dName)
' _TempMediaList.ListAddValue(MediaFromData(m("media_url").Value,
' PostID, PostDate, GetPictureOption(m)), LNC)
' End If
' End If
' Next
' End If
'End If
ObtainMedia(nn, PostID, PostDate)
End If
End If
Next
@@ -136,13 +144,68 @@ Namespace API.Twitter
ProcessException(ex, Token, $"data downloading error{IIf(IsSavedPosts, " (Saved Posts)", String.Empty)} [{URL}]")
End Try
End Sub
Private Sub ObtainMedia(ByVal e As EContainer, ByVal PostID As String, ByVal PostDate As String, Optional ByVal State As UStates = UStates.Unknown)
If Not CheckVideoNode(e, PostID, PostDate) Then
Dim s As EContainer = e.ItemF({"extended_entities", "media"})
If s Is Nothing OrElse s.Count = 0 Then s = e.ItemF({"retweeted_status", "extended_entities", "media"})
If If(s?.Count, 0) > 0 Then
For Each m In s
If m.Contains("media_url") Then
Dim dName$ = UrlFile(m("media_url").Value)
If Not dName.IsEmptyString AndAlso Not _DataNames.Contains(dName) Then
_DataNames.Add(dName)
_TempMediaList.ListAddValue(MediaFromData(m("media_url").Value,
PostID, PostDate, GetPictureOption(m), State), LNC)
End If
End If
Next
End If
End If
End Sub
Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken)
'PENDING: Twitter ReparseMissing verify
Dim rList As New List(Of Integer)
Dim URL$ = String.Empty
Try
If ContentMissingExists Then
Dim m As UserMedia
Dim r$, PostDate$
Dim j As EContainer
For i% = 0 To _ContentList.Count - 1
If _ContentList(i).State = UStates.Missing Then
m = _ContentList(i)
If Not m.Post.ID.IsEmptyString Then
ThrowAny(Token)
URL = $"https://api.twitter.com/1.1/statuses/show.json?id={m.Post.ID}"
r = Responser.GetResponse(URL,, EDP.ReturnValue)
If Not r.IsEmptyString Then
j = JsonDocument.Parse(r)
If Not j Is Nothing Then
PostDate = String.Empty
If j.Contains("created_at") Then PostDate = j("created_at").Value Else PostDate = String.Empty
ObtainMedia(j, m.Post.ID, PostDate, UStates.Missing)
rList.Add(i)
End If
End If
End If
End If
Next
End If
Catch ex As Exception
ProcessException(ex, Token, $"ReparseMissing error [{URL}]")
Finally
If rList.Count > 0 Then
For i% = rList.Count - 1 To 0 Step -1 : _ContentList.RemoveAt(i) : Next
rList.Clear()
End If
End Try
End Sub
Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal resp As Response) As IEnumerable(Of UserMedia)
Try
If URL.Contains("twitter") Then
Dim PostID$ = RegexReplace(URL, RParams.DM("(?<=/)\d+", 0))
If Not PostID.IsEmptyString Then
Dim r$ = DirectCast(resp.Copy(), Response).
GetResponse($"https://api.twitter.com/1.1/statuses/show.json?id={PostID}",, EDP.ReturnValue)
Dim r$ = DirectCast(resp.Copy(), Response).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
@@ -163,7 +226,7 @@ Namespace API.Twitter
Const P4K As String = "4096x4096"
Try
Dim ww As EContainer = w("sizes")
If Not ww Is Nothing AndAlso ww.Count > 0 Then
If ww.ListExists Then
Dim l As New List(Of Sizes)
Dim Orig As Sizes? = New Sizes(w.Value({"original_info"}, "height").FromXML(Of Integer)(-1), P4K)
If Orig.Value.Value = -1 Then Orig = Nothing
@@ -177,7 +240,6 @@ Namespace API.Twitter
Return P4K
ElseIf l(0).Data.IsEmptyString Then
Return P4K
'If LargeContained Then Return "large" Else Return P4K
Else
Return l(0).Data
End If
@@ -222,8 +284,8 @@ Namespace API.Twitter
Dim url$, ff$
Dim f As SFile
Dim m As UserMedia
With w({"extended_entities", "media"}).XmlIfNothing
If .Count > 0 Then
With w({"extended_entities", "media"})
If .ListExists Then
For Each n As EContainer In .Self
If n.Value("type") = "animated_gif" Then
With n({"video_info", "variants"}).XmlIfNothing.ItemF({gifUrl}).XmlIfNothing
@@ -251,7 +313,7 @@ Namespace API.Twitter
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
If v.ListExists Then
Dim l As New List(Of Sizes)
Dim u$
Dim nn As EContainer
@@ -270,8 +332,6 @@ Namespace API.Twitter
End If
Return String.Empty
End Function
Protected Overrides Sub ReparseVideo(ByVal Token As CancellationToken)
End Sub
Private Function UrlFile(ByVal URL As String) As String
Try
Dim f As SFile = CStr(RegexReplace(LinkFormatterSecure(RegexReplace(URL.Replace("\", String.Empty), LinkPattern)), FilesPattern))
@@ -282,7 +342,8 @@ Namespace API.Twitter
End Function
#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
Optional ByVal _PictureOption As String = Nothing,
Optional ByVal State As UStates = UStates.Unknown) 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))
@@ -290,6 +351,7 @@ Namespace API.Twitter
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
m.State = State
Return m
End Function
#End Region

View File

@@ -79,7 +79,7 @@ Namespace API
If Count > 0 Then
Return Collections(0).GetPicture
Else
Return GetNullPicture(Settings.MaxLargeImageHeigh)
Return GetNullPicture(Settings.MaxLargeImageHeight)
End If
End Function
#End Region
@@ -92,6 +92,11 @@ Namespace API
End If
End Get
End Property
Friend Overrides ReadOnly Property ContentMissingExists As Boolean
Get
Return Count > 0 AndAlso Collections.Exists(Function(c) DirectCast(c, UserDataBase).ContentMissingExists)
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
@@ -191,10 +196,10 @@ Namespace API
Friend Overrides Property LastUpdated As Date?
Get
If Count > 0 Then
With If((From c As IUserData In Collections
With (From c As IUserData 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
Select DirectCast(c, UserDataBase).LastUpdated.Value).ToList
If .ListExists Then Return .Max
End With
End If
Return Nothing
@@ -285,8 +290,8 @@ Namespace API
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())
Friend Overrides Sub LoadContentInformation(Optional ByVal Force As Boolean = False)
If Count > 0 Then Collections.ForEach(Sub(c) DirectCast(c, UserDataBase).LoadContentInformation(Force))
End Sub
Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean)
End Sub
@@ -309,8 +314,6 @@ Namespace API
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
Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False) As Integer
@@ -328,7 +331,7 @@ Namespace API
Friend Overrides Sub OpenFolder()
Try
If Count > 0 Then GlobalOpenPath(Collections(0).File.CutPath(2))
Catch ex As Exception
Catch
End Try
End Sub
#End Region
@@ -343,6 +346,14 @@ Namespace API
Return False
End Get
End Property
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 Sub Clear() Implements ICollection(Of IUserData).Clear
Collections.ListClearDispose
End Sub
#End Region
#Region "Add"
''' <exception cref="InvalidOperationException"></exception>
Friend Overloads Sub Add(ByVal _Item As IUserData) Implements ICollection(Of IUserData).Add
With _Item
@@ -359,7 +370,7 @@ Namespace API
ConsolidateScripts()
.UpdateUserInformation()
End If
ImageHandler(_Item, False)
MainFrameObj.ImageHandler(_Item, False)
AddRemoveBttDeleteHandler(.Self, True)
AddHandler .Self.UserUpdated, AddressOf User_OnUserUpdated
End With
@@ -406,10 +417,12 @@ Namespace API
If Count > 1 AndAlso ScriptUse Then Collections.ForEach(Sub(c) c.ScriptUse = True)
End Sub
Friend Sub AddRange(ByVal _Items As IEnumerable(Of IUserData))
If Not _Items Is Nothing AndAlso _Items.Count > 0 Then
If _Items.ListExists Then
For i% = 0 To _Items.Count - 1 : Add(_Items(i)) : Next
End If
End Sub
#End Region
#Region "Move, Merge"
Friend Overrides Function MoveFiles(ByVal __CollectionName As String) As Boolean
Throw New NotImplementedException("Move files is not available in the collection context")
End Function
@@ -437,15 +450,8 @@ Namespace API
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
#End Region
#Region "Remove, Delete"
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 &
@@ -454,7 +460,7 @@ Namespace API
Return False
Else
DirectCast(_Item, UserDataBase).MoveFiles(String.Empty)
ImageHandler(_Item)
MainFrameObj.ImageHandler(_Item)
AddRemoveBttDeleteHandler(_Item, False)
RaiseEvent OnUserRemoved(_Item)
Return Collections.Remove(_Item)
@@ -469,7 +475,7 @@ Namespace API
Settings.Users.Remove(Me)
Collections.ForEach(Sub(c) c.Delete())
Downloader.UserRemove(Me)
ImageHandler(Me, False)
MainFrameObj.ImageHandler(Me, False)
Collections.ListClearDispose
Dispose(False)
f.Delete(SFO.Path, SFODelete.EmptyOnly + Settings.DeleteMode, EDP.SendInLog)
@@ -487,12 +493,12 @@ Namespace API
Settings.Users.Remove(Me)
Collections.ForEach(Sub(c)
c.MoveFiles(String.Empty)
ImageHandler(c)
MainFrameObj.ImageHandler(c)
End Sub)
Collections.Clear()
f.Delete(SFO.Path, SFODelete.Default + Settings.DeleteMode, EDP.SendInLog)
Downloader.UserRemove(Me)
ImageHandler(Me, False)
MainFrameObj.ImageHandler(Me, False)
Dispose(False)
Return 3
Else
@@ -511,7 +517,7 @@ Namespace API
Dim RemoveMeIfNull As Action = Sub()
If Count = 0 Then
Settings.Users.Remove(Me)
ImageHandler(Me, False)
MainFrameObj.ImageHandler(Me, False)
RaiseEvent OnCollectionSelfRemoved(Me)
Dispose(False)
End If
@@ -544,6 +550,17 @@ Namespace API
End If
End With
End Sub
#End Region
#Region "Copy"
Friend Overrides Function CopyFiles(ByVal DestinationPath As SFile, Optional ByVal e As ErrorsDescriber = Nothing) As Boolean
Return Count > 0 AndAlso Collections(0).CopyFiles(DestinationPath, e)
End Function
#End Region
#Region "Contains"
Friend Function Contains(ByVal _Item As IUserData) As Boolean Implements ICollection(Of IUserData).Contains
Return Count > 0 AndAlso Collections.Contains(_Item)
End Function
#End Region
#Region "IEnumerable Support"
Private Function GetEnumerator() As IEnumerator(Of IUserData) Implements IEnumerable(Of IUserData).GetEnumerator
Return New MyEnumerator(Of IUserData)(Me)
@@ -551,7 +568,6 @@ Namespace API
Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Return GetEnumerator()
End Function
#End Region
#End Region
Friend Overrides Function Equals(ByVal Other As UserDataBase) As Boolean
If Other.IsCollection Then

View File

@@ -142,7 +142,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits
Friend Sub New()
InitializeComponent()
MyDefs = New DefaultFormOptions
CProgress = New MyProgress(ToolbarBOTTOM, PR_CN, LBL_STATUS, "Downloading data") With {.PerformMod = 10, .DropCurrentProgressOnTotalChange = False}
CProgress = New MyProgress(ToolbarBOTTOM, PR_CN, LBL_STATUS, "Downloading data") With {.PerformMod = 10, .ResetProgressOnMaximumChanges = False}
CProvider = New ANumbers With {.FormatOptions = ANumbers.Options.GroupIntegral}
LimitProvider = New ADateTime("dd.MM.yyyy HH:mm")
PendingUsers = New List(Of PendingUser)
@@ -194,6 +194,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits
.ButtonKey(RButton.Previous) = Keys.F2
.ButtonKey(RButton.Next) = Keys.F3
.LabelNumbersProvider = CProvider
.Limit = ImagesInRow * ImagesRows
.AddThisToolbar()
End With
ToolbarTOP.Items.AddRange({CMB_CHANNELS.GetControlHost,
@@ -216,7 +217,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits
RefillChannels(Settings.LatestSelectedChannel.Value)
ChangeComboIndex(0)
MyRange.LabelText = String.Empty
CMB_CHANNELS_ActionOnCheckedChange(CMB_CHANNELS.Checked)
CMB_CHANNELS_ActionOnCheckedChange(Nothing, Nothing, CMB_CHANNELS.Checked)
With LIST_POSTS
Dim s As Size = GetImageSize()
.LargeImageList = New ImageList With {.ColorDepth = ColorDepth.Depth32Bit, .ImageSize = s}
@@ -296,8 +297,8 @@ Friend Class ChannelViewForm : Implements IChannelLimits
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 -= .Margin.Horizontal
s.Height -= .Margin.Vertical
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
@@ -329,9 +330,9 @@ Friend Class ChannelViewForm : Implements IChannelLimits
If Not TokenSource Is Nothing OrElse Not HOST.Source.Available(Plugin.ISiteSettings.Download.Channel, False) Then Exit Sub
Dim InvokeToken As Action = Sub()
If TokenSource Is Nothing Then
CProgress.TotalCount = 0
CProgress.CurrentCounter = 0
CProgress.Enabled = True
CProgress.Maximum = 0
CProgress.Value = 0
CProgress.Visible = True
TokenSource = New CancellationTokenSource
Token = TokenSource.Token
BTT_DOWNLOAD.Enabled = False
@@ -388,7 +389,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits
Finally
If Not TokenSource Is Nothing AndAlso Not Settings.Channels.Downloading Then
TokenSource = Nothing
CProgress.Enabled = False
CProgress.Visible = False
BTT_DOWNLOAD.Enabled = True
BTT_STOP.Enabled = False
_CollectionDownloading = False
@@ -400,7 +401,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits
CH_HIDE_EXISTS_USERS.Enabled = True
CMB_CHANNELS.Enabled(True) = True
BTT_SHOW_STATS.Enabled = True
CMB_CHANNELS_ActionOnCheckedChange(CMB_CHANNELS.Checked)
CMB_CHANNELS_ActionOnCheckedChange(Nothing, Nothing, CMB_CHANNELS.Checked)
MyRange.Enabled = True
MyRange.UpdateControls()
End If
@@ -549,7 +550,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits
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}]"
LBL_LIMIT_TEXT.Text = $"to post [{c.FirstOrDefault(Function(p) Not p.ID.IsEmptyString).ID}]"
End If
Else
OPT_LIMITS_COUNT.Checked = True
@@ -571,7 +572,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits
Dim c As Channel = GetCurrentChannel()
If Not c Is Nothing Then MyRange.Source = c
End Sub
Private Sub CMB_CHANNELS_ActionOnButtonClick(ByVal Sender As ActionButton) Handles CMB_CHANNELS.ActionOnButtonClick
Private Sub CMB_CHANNELS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles CMB_CHANNELS.ActionOnButtonClick
Dim c As Channel
Select Case Sender.DefaultButton
Case ADB.Refresh : RefillChannels()
@@ -579,12 +580,12 @@ Friend Class ChannelViewForm : Implements IChannelLimits
Case ADB.Delete
Try
c = GetCurrentChannel()
If Not c Is Nothing AndAlso MsgBoxE($"Do you really want to delete channel [{c}]?", MsgBoxStyle.Exclamation + MsgBoxStyle.YesNo) = 0 Then
If Not c Is Nothing AndAlso MsgBoxE($"Are you sure you want to delete the channel [{c}]?", vbExclamation + vbYesNo) = vbYes Then
Settings.Channels.Remove(c)
RefillChannels()
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Error on trying to delete channel")
Catch del_ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, del_ex, "An error occurred while trying to delete a channel")
End Try
Case ADB.Up : ChangeComboIndex(-1)
Case ADB.Down : ChangeComboIndex(1)
@@ -597,19 +598,19 @@ Friend Class ChannelViewForm : Implements IChannelLimits
If f.DialogResult = DialogResult.OK Then c.Save()
End Using
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Error on trying to edit channel")
Catch edit_ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, edit_ex, "An error occurred while trying to edit a channel")
End Try
Case ADB.Info
Try
c = GetCurrentChannel()
If Not c Is Nothing Then MsgBoxE({c.GetChannelStats(True), "Channel statistics"})
Catch info_ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, info_ex, "Error on trying to show channel info")
ErrorsDescriber.Execute(EDP.LogMessageValue, info_ex, "An error occurred while trying to display channel information")
End Try
End Select
End Sub
Private Sub CMB_CHANNELS_ActionOnCheckedChange(ByVal Mode As Boolean) Handles CMB_CHANNELS.ActionOnCheckedChange
Private Sub CMB_CHANNELS_ActionOnCheckedChange(ByVal Sender As Object, ByVal e As EventArgs, ByVal Checked As Boolean) Handles CMB_CHANNELS.ActionOnCheckedChange
Dim OneChannel As Boolean = Not CMB_CHANNELS.Checked
CMB_CHANNELS.Enabled(False) = OneChannel
If OneChannel Then
@@ -683,7 +684,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits
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}]")
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, $"Error 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
@@ -693,7 +694,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits
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}]")
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, $"Error 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
@@ -734,14 +735,14 @@ Friend Class ChannelViewForm : Implements IChannelLimits
MsgBoxE("User does not selected", MsgBoxStyle.Exclamation)
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Error on removing user from selected")
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Error 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?",
Dim result% = MsgBoxE(New MMessage($"Are you sure you 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",
@@ -771,7 +772,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits
#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)
If f.Exists Then f.Open() Else MsgBoxE($"Picture file [{f}] not found", MsgBoxStyle.Critical)
End Sub
Private Function GetPostBySelected(Optional ByVal SpecificTag As String = Nothing) As UserPost
Dim p As UserPost = Nothing
@@ -798,7 +799,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits
MyRange.Limit = ImagesInRow * ImagesRows
MyRange.GoTo(0)
End Sub
Private Sub MyRange_IndexChanged(ByVal Sender As IRangeSwitcherProvider, ByVal Index As Integer) Handles MyRange.IndexChanged
Private Sub MyRange_IndexChanged(ByVal Sender As Object, ByVal e As EventArgs) Handles MyRange.IndexChanged
Try
If MyDefs.Initializing Then Exit Sub
AppendPendingUsers()
@@ -828,8 +829,8 @@ Friend Class ChannelViewForm : Implements IChannelLimits
ErrorsDescriber.Execute(EDP.LogMessageValue, ex)
End Try
End Sub
Private Sub MyRange_RangesChanged(ByVal Sender As IRangeSwitcherProvider, ByVal Index As Integer) Handles MyRange.RangesChanged
If Sender.Count > 0 Then MyRange_IndexChanged(Nothing, 0)
Private Sub MyRange_RangesChanged(ByVal Sender As IRangeSwitcherProvider, ByVal e As EventArgs) Handles MyRange.RangesChanged
If Sender.Count > 0 Then Sender.CurrentIndex = 0
End Sub
#End Region
End Class

View File

@@ -6,36 +6,22 @@
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports System.ComponentModel
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Controls.Base
Imports PersonalUtilities.Forms.Toolbars
Friend Class ChannelsStatsForm : Implements IOkCancelDeleteToolbar
Private ReadOnly MyDefs As DefaultFormOptions
Friend Class ChannelsStatsForm
Private WithEvents MyDefs As DefaultFormOptions
Friend Property DeletedChannels As Integer = 0
Friend Sub New()
InitializeComponent()
MyDefs = New DefaultFormOptions
MyDefs = New DefaultFormOptions(Me, Settings.Design)
End Sub
Private Sub ChannelsStatsForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
With MyDefs
.MyViewInitialize(Me, Settings.Design)
.MyViewInitialize()
.AddOkCancelToolbar()
.MyOkCancel.EnableDelete = False
If Settings.Channels.Count > 0 Then
RefillList()
Else
MsgBoxE("Channels not found", vbExclamation)
End If
If Settings.Channels.Count > 0 Then RefillList() Else MsgBoxE("Channels not found", vbExclamation)
.EndLoaderOperations()
End With
Catch ex As Exception
MyDefs.InvokeLoaderError(ex)
End Try
End Sub
Private Sub ChannelsStatsForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
MyDefs.Dispose()
End Sub
Private Sub RefillList()
CMB_CHANNELS.Items.Clear()
@@ -45,13 +31,7 @@ Friend Class ChannelsStatsForm : Implements IOkCancelDeleteToolbar
CMB_CHANNELS.EndUpdate()
End If
End Sub
Private Sub OK() Implements IOkCancelToolbar.OK
MyDefs.CloseForm()
End Sub
Private Sub Cancel() Implements IOkCancelToolbar.Cancel
MyDefs.CloseForm(DialogResult.Cancel)
End Sub
Private Sub Delete() Implements IOkCancelDeleteToolbar.Delete
Private Sub MyDefs_ButtonDeleteClickOC(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonDeleteClickOC
Try
Dim c As List(Of String) = CMB_CHANNELS.Items.CheckedItems.Select(Function(cc) CStr(cc.Value(1))).ListIfNothing
If c.ListExists Then
@@ -76,7 +56,7 @@ Friend Class ChannelsStatsForm : Implements IOkCancelDeleteToolbar
Private Sub CMB_CHANNELS_ActionOnChangeDetected(ByVal c As Boolean) Handles CMB_CHANNELS.ActionOnChangeDetected
If Not MyDefs.Initializing Then MyDefs.MyOkCancel.EnableDelete = CMB_CHANNELS.ListCheckedIndexes.Count > 0
End Sub
Private Sub CMB_CHANNELS_ActionOnButtonClearClick() Handles CMB_CHANNELS.ActionOnButtonClearClick
CMB_CHANNELS.ListCheckedIndexes = Nothing
Private Sub CMB_CHANNELS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles CMB_CHANNELS.ActionOnButtonClick
If Sender.DefaultButton = ActionButton.DefaultButtons.Clear Then CMB_CHANNELS.ListCheckedIndexes = Nothing
End Sub
End Class

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 B

View File

@@ -23,8 +23,8 @@ Namespace DownloadObjects
Friend Sub New()
InitializeComponent()
JobsList = New List(Of DownloadProgress)
AddHandler Downloader.OnReconfigured, AddressOf Downloader_OnReconfigured
Downloader_OnReconfigured()
AddHandler Downloader.Reconfigured, AddressOf Downloader_Reconfigured
Downloader_Reconfigured()
End Sub
Private Sub ActiveDownloadingProgress_Load(sender As Object, e As EventArgs) Handles Me.Load
MyView = New FormsView(Me)
@@ -37,14 +37,13 @@ Namespace DownloadObjects
e.Cancel = True
Hide()
End Sub
Private Sub Downloader_OnReconfigured()
Private Sub Downloader_Reconfigured()
Const RowHeight% = 30
Dim a As Action = Sub()
With TP_MAIN
If .Controls.Count > 0 Then
For Each c As Control In .Controls
If Not c Is Nothing Then c.Dispose()
Next
.Controls.Clear()
End If
@@ -59,7 +58,7 @@ Namespace DownloadObjects
.RowStyles.Add(New RowStyle(SizeType.Absolute, RowHeight))
.RowCount += 1
JobsList.Add(New DownloadProgress(j))
AddHandler JobsList.Last.OnTotalCountChange, AddressOf Jobs_OnTotalCountChange
AddHandler JobsList.Last.ProgressMaximumChanged, AddressOf Jobs_ProgressMaximumChanged
.Controls.Add(JobsList.Last.Get, 0, .RowStyles.Count - 1)
End With
Next
@@ -75,11 +74,11 @@ Namespace DownloadObjects
End Sub
If TP_MAIN.InvokeRequired Then TP_MAIN.Invoke(a) Else a.Invoke
End Sub
Private Sub Jobs_OnTotalCountChange()
Private Sub Jobs_ProgressMaximumChanged()
If JobsList.Count > 0 And Not DisableProgressChange Then
MainProgress.TotalCount = JobsList.Sum(Function(j) CLng(j.Job.Progress.TotalCount))
MainProgress.CurrentCounter = Math.Max(JobsList.Sum(Function(j) CLng(j.Job.Progress.CurrentCounter)) - 1, 0)
If MainProgress.CurrentCounter > 0 Then MainProgress.Perform()
MainProgress.Maximum = JobsList.Sum(Function(j) CLng(j.Job.Progress.Maximum))
MainProgress.Value = Math.Max(JobsList.Sum(Function(j) CLng(j.Job.Progress.Value)) - 1, 0)
If MainProgress.Value > 0 Then MainProgress.Perform()
End If
End Sub
End Class

View File

@@ -9,13 +9,18 @@
Imports System.Threading
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.XML.Base
Imports PersonalUtilities.Tools
Imports PersonalUtilities.Tools.Notifications
Imports SCrawler.DownloadObjects.Groups
Imports SCrawler.API
Imports SCrawler.API.Base
Namespace DownloadObjects
Friend Class AutoDownloader : Inherits GroupParameters : Implements IEContainerProvider
Friend Event UserFind(ByVal Key As String, ByVal Activate As Boolean)
Private Shared ReadOnly Property CachePath As SFile
Get
Return Settings.CachePath
End Get
End Property
Friend Enum Modes As Integer
None = 0
[Default] = 1
@@ -38,26 +43,35 @@ Namespace DownloadObjects
Private ReadOnly Property KeySite As String
Private ReadOnly Property KeyDismiss As String
Private ReadOnly Property Images As Dictionary(Of String, SFile)
Private ReadOnly Property AutoDownloaderSource As AutoDownloader
Private Sub New()
Images = New Dictionary(Of String, SFile)
End Sub
Friend Sub New(ByVal _Key As String)
Private Sub New(ByVal _Key As String)
Me.New
Key = _Key
KeyFolder = $"{Key}{KeyOpenFolder}"
KeySite = $"{Key}{KeyOpenSite}"
KeyDismiss = $"{Key}{KeyBttDismiss}"
End Sub
Friend Sub New(ByVal _Key As String, ByRef _User As IUserData)
Friend Sub New(ByVal _Key As String, ByRef _User As IUserData, ByRef Source As AutoDownloader)
Me.New(_Key)
User = _User
IUserDataKey = _User.Key
AutoDownloaderSource = Source
If _User.IncludedInCollection Then
Dim cn$ = _User.CollectionName
Dim i% = Settings.Users.FindIndex(Function(u) u.IsCollection And u.Name = cn)
If i >= 0 Then IUserDataKey = Settings.Users(i).Key
End If
End Sub
Public Shared Widening Operator CType(ByVal Key As String) As NotifiedUser
Return New NotifiedUser(Key)
End Operator
Friend Sub ShowNotification()
Try
If Not AutoDownloaderSource Is Nothing Then
If AutoDownloaderSource.ShowNotifications Then
If Not User Is Nothing Then
Dim Text$ = $"{User.Site} - {User.Name}{vbNewLine}" &
$"Downloaded: {User.DownloadedPictures(False)} images, {User.DownloadedVideos(False)} videos"
@@ -68,16 +82,29 @@ Namespace DownloadObjects
Title = User.ToString
End If
Using Notify As New Notification(Text, Title) With {.Key = Key}
Dim uPic As SFile = DirectCast(User, UserDataBase).GetUserPictureAddress
Dim uPic As SFile = Nothing
Dim uif As SFile = Nothing
Dim uif_orig As SFile = Nothing
Dim uif_compressed As SFile = Nothing
Dim uifKey$ = String.Empty
If uPic.Exists Then Notify.Images = {New ToastImage(uPic)}
If User.DownloadedPictures(False) > 0 Then
If AutoDownloaderSource.ShowPictureUser Then uPic = DirectCast(User, UserDataBase).GetUserPictureToastAddress
If AutoDownloaderSource.ShowPictureUser AndAlso uPic.Exists Then Notify.Images = {New ToastImage(uPic)}
If AutoDownloaderSource.ShowPictureDownloaded And User.DownloadedPictures(False) > 0 Then
uif = DirectCast(User, UserDataBase).GetLastImageAddress
uif_orig = uif
If uif.Exists Then
uif_compressed = uif
uif_compressed.Path = CachePath.Path
uif_compressed.Name = $"360_{uif.Name}"
Using imgR As New ImageRenderer(uif, EDP.SendInLog)
Try : imgR.FitToWidth(360).Save(uif_compressed) : Catch : End Try
End Using
If uif_compressed.Exists Then uif = uif_compressed
If uif.Exists Then
Notify.Images = {New ToastImage(uif, IImage.Modes.Inline)}
uifKey = $"{Key}_{Images.Keys.Count + 1}_{KeyBttPhoto}"
If Not Images.ContainsKey(uifKey) Then Images.Add(uifKey, uif)
If Not Images.ContainsKey(uifKey) Then Images.Add(uifKey, uif_orig)
End If
End If
End If
Notify.Buttons = {
@@ -89,6 +116,8 @@ Namespace DownloadObjects
Notify.Show()
End Using
End If
End If
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendInLog, ex, "[AutoDownloader.NotifiedUser.ShowNotification]")
If Not User Is Nothing Then
@@ -144,6 +173,9 @@ Namespace DownloadObjects
Private Const Name_StartupDelay As String = "StartupDelay"
Private Const Name_LastDownloadDate As String = "LastDownloadDate"
Private Const Name_ShowNotifications As String = "Notify"
Private Const Name_ShowPictureDown As String = "ShowDownloadedPicture"
Private Const Name_ShowPictureUser As String = "ShowUserPicture"
Private Const Name_ShowSimpleNotification As String = "ShowSimpleNotification"
#End Region
#Region "Declarations"
Friend Property Source As Scheduler
@@ -161,6 +193,9 @@ Namespace DownloadObjects
Friend Property Timer As Integer = DefaultTimer
Friend Property StartupDelay As Integer = 0
Friend Property ShowNotifications As Boolean = True
Friend Property ShowPictureDownloaded As Boolean = True
Friend Property ShowPictureUser As Boolean = True
Friend Property ShowSimpleNotification As Boolean = False
#Region "Date"
Private ReadOnly LastDownloadDateXML As Date? = Nothing
Private _LastDownloadDate As Date = Now.AddYears(-1)
@@ -190,6 +225,7 @@ Namespace DownloadObjects
End If
End Function
#End Region
#Region "Information"
Friend ReadOnly Property Information As String
Get
Return $"Last download date: {GetLastDateString()} ({GetWorkingState()})"
@@ -214,8 +250,7 @@ Namespace DownloadObjects
Public Overrides Function ToString() As String
Return $"{Name} ({GetWorkingState()}): last download date: {GetLastDateString()}; next run: {GetNextDateString()}"
End Function
Private File As SFile = $"Settings\AutoDownload.xml"
Private AThread As Thread
#End Region
#End Region
#Region "Initializer"
Private ReadOnly Initialization As Boolean = True
@@ -245,6 +280,9 @@ Namespace DownloadObjects
StartupDelay = x.Value(Name_StartupDelay).FromXML(Of Integer)(0)
If StartupDelay < 0 Then StartupDelay = 0
ShowNotifications = x.Value(Name_ShowNotifications).FromXML(Of Boolean)(True)
ShowPictureDownloaded = x.Value(Name_ShowPictureDown).FromXML(Of Boolean)(True)
ShowPictureUser = x.Value(Name_ShowPictureUser).FromXML(Of Boolean)(True)
ShowSimpleNotification = x.Value(Name_ShowSimpleNotification).FromXML(Of Boolean)(False)
LastDownloadDateXML = AConvert(Of Date)(x.Value(Name_LastDownloadDate), DateProvider, Nothing)
If LastDownloadDateXML.HasValue Then
LastDownloadDate = LastDownloadDateXML.Value
@@ -285,12 +323,16 @@ Namespace DownloadObjects
New EContainer(Name_Timer, Timer),
New EContainer(Name_StartupDelay, StartupDelay),
New EContainer(Name_ShowNotifications, ShowNotifications.BoolToInteger),
New EContainer(Name_ShowPictureDown, ShowPictureDownloaded.BoolToInteger),
New EContainer(Name_ShowPictureUser, ShowPictureUser.BoolToInteger),
New EContainer(Name_ShowSimpleNotification, ShowSimpleNotification.BoolToInteger),
New EContainer(Name_LastDownloadDate, CStr(AConvert(Of String)(If(LastDownloadDateXML.HasValue Or _LastDownloadDateChanged,
CObj(LastDownloadDate), Nothing), DateProvider, String.Empty)))
}
End Function
#End Region
#Region "Execution"
Private AThread As Thread
Friend ReadOnly Property Working As Boolean
Get
Return If(AThread?.IsAlive, False)
@@ -344,12 +386,18 @@ Namespace DownloadObjects
Dim users As New List(Of IUserData)
Dim GName$
Dim i%
Dim DownloadedUsersCount% = 0
Dim l As New ListAddParams(LAP.IgnoreICopier + LAP.NotContainsOnly)
Dim simple As Boolean = ShowSimpleNotification And ShowNotifications
Dim notify As Action = Sub()
With Downloader.Downloaded
If ShowNotifications And .Count > 0 Then .ForEach(Sub(ByVal u As IUserData)
If Keys.Contains(u.Key) Then
If simple Then
DownloadedUsersCount += 1
Else
ShowNotification(u)
End If
Keys.Remove(u.Key)
End If
End Sub)
@@ -389,6 +437,8 @@ Namespace DownloadObjects
While .Working Or .Count > 0 : notify.Invoke() : Thread.Sleep(200) : End While
.AutoDownloaderWorking = False
notify.Invoke
If simple And DownloadedUsersCount > 0 Then _
MainFrameObj.ShowNotification($"{DownloadedUsersCount} user(s) downloaded with scheduler plan '{Name}'", $"Scheduler plan '{Name}'")
End With
End If
Catch ex As Exception
@@ -406,14 +456,14 @@ Namespace DownloadObjects
If i >= 0 Then
UserKeys(i).ShowNotification()
Else
UserKeys.Add(New NotifiedUser(k, TDownloader.GetUserFromMainCollection(u)))
UserKeys.Add(New NotifiedUser(k, Settings.GetUser(u), Me))
UserKeys.Last.ShowNotification()
End If
End Sub
Friend Function NotificationClicked(ByVal Key As String) As Boolean
Dim i% = UserKeys.IndexOf(Key)
If i >= 0 Then
RaiseEvent UserFind(UserKeys(i).IUserDataKey, UserKeys(i).Open(Key))
MainFrameObj.FocusUser(UserKeys(i).IUserDataKey, UserKeys(i).Open(Key))
Return True
Else
Return False

View File

@@ -30,6 +30,7 @@ Namespace DownloadObjects
Dim TP_MODE As System.Windows.Forms.TableLayoutPanel
Dim ActionButton3 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton4 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TP_NOTIFY As System.Windows.Forms.TableLayoutPanel
Dim TT_MAIN As System.Windows.Forms.ToolTip
Me.DEF_GROUP = New SCrawler.DownloadObjects.Groups.GroupDefaults()
Me.TXT_GROUPS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
@@ -38,12 +39,16 @@ Namespace DownloadObjects
Me.OPT_SPEC = New System.Windows.Forms.RadioButton()
Me.OPT_DISABLED = New System.Windows.Forms.RadioButton()
Me.OPT_GROUP = New System.Windows.Forms.RadioButton()
Me.CH_NOTIFY = New System.Windows.Forms.CheckBox()
Me.TXT_TIMER = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.LBL_LAST_TIME_UP = New System.Windows.Forms.Label()
Me.NUM_DELAY = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.CH_NOTIFY = New System.Windows.Forms.CheckBox()
Me.CH_SHOW_PIC = New System.Windows.Forms.CheckBox()
Me.CH_SHOW_PIC_USER = New System.Windows.Forms.CheckBox()
Me.CH_NOTIFY_SIMPLE = New System.Windows.Forms.CheckBox()
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
TP_MODE = New System.Windows.Forms.TableLayoutPanel()
TP_NOTIFY = New System.Windows.Forms.TableLayoutPanel()
TT_MAIN = New System.Windows.Forms.ToolTip(Me.components)
CONTAINER_MAIN.ContentPanel.SuspendLayout()
CONTAINER_MAIN.SuspendLayout()
@@ -52,6 +57,7 @@ Namespace DownloadObjects
TP_MODE.SuspendLayout()
CType(Me.TXT_TIMER, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.NUM_DELAY, System.ComponentModel.ISupportInitialize).BeginInit()
TP_NOTIFY.SuspendLayout()
Me.SuspendLayout()
'
'CONTAINER_MAIN
@@ -77,10 +83,10 @@ Namespace DownloadObjects
Me.DEF_GROUP.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.DEF_GROUP.Controls.Add(Me.TXT_GROUPS, 0, 5)
Me.DEF_GROUP.Controls.Add(TP_MODE, 0, 0)
Me.DEF_GROUP.Controls.Add(Me.CH_NOTIFY, 0, 6)
Me.DEF_GROUP.Controls.Add(Me.TXT_TIMER, 0, 7)
Me.DEF_GROUP.Controls.Add(Me.LBL_LAST_TIME_UP, 0, 9)
Me.DEF_GROUP.Controls.Add(Me.NUM_DELAY, 0, 8)
Me.DEF_GROUP.Controls.Add(TP_NOTIFY, 0, 6)
Me.DEF_GROUP.Dock = System.Windows.Forms.DockStyle.Fill
Me.DEF_GROUP.Location = New System.Drawing.Point(0, 0)
Me.DEF_GROUP.Name = "DEF_GROUP"
@@ -96,6 +102,7 @@ Namespace DownloadObjects
Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
Me.DEF_GROUP.Size = New System.Drawing.Size(476, 301)
Me.DEF_GROUP.TabIndex = 0
'
@@ -113,7 +120,7 @@ Namespace DownloadObjects
Me.TXT_GROUPS.Location = New System.Drawing.Point(4, 140)
Me.TXT_GROUPS.Name = "TXT_GROUPS"
Me.TXT_GROUPS.Size = New System.Drawing.Size(468, 22)
Me.TXT_GROUPS.TabIndex = 2
Me.TXT_GROUPS.TabIndex = 1
'
'TP_MODE
'
@@ -136,7 +143,7 @@ Namespace DownloadObjects
TP_MODE.RowCount = 1
TP_MODE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MODE.Size = New System.Drawing.Size(474, 25)
TP_MODE.TabIndex = 1
TP_MODE.TabIndex = 0
'
'OPT_ALL
'
@@ -203,17 +210,6 @@ Namespace DownloadObjects
TT_MAIN.SetToolTip(Me.OPT_GROUP, "Download groups")
Me.OPT_GROUP.UseVisualStyleBackColor = True
'
'CH_NOTIFY
'
Me.CH_NOTIFY.AutoSize = True
Me.CH_NOTIFY.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_NOTIFY.Location = New System.Drawing.Point(4, 169)
Me.CH_NOTIFY.Name = "CH_NOTIFY"
Me.CH_NOTIFY.Size = New System.Drawing.Size(468, 19)
Me.CH_NOTIFY.TabIndex = 3
Me.CH_NOTIFY.Text = "Show notifications"
Me.CH_NOTIFY.UseVisualStyleBackColor = True
'
'TXT_TIMER
'
ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image)
@@ -225,7 +221,7 @@ Namespace DownloadObjects
Me.TXT_TIMER.Location = New System.Drawing.Point(4, 195)
Me.TXT_TIMER.Name = "TXT_TIMER"
Me.TXT_TIMER.Size = New System.Drawing.Size(468, 22)
Me.TXT_TIMER.TabIndex = 4
Me.TXT_TIMER.TabIndex = 3
'
'LBL_LAST_TIME_UP
'
@@ -235,7 +231,7 @@ Namespace DownloadObjects
Me.LBL_LAST_TIME_UP.Location = New System.Drawing.Point(4, 250)
Me.LBL_LAST_TIME_UP.Name = "LBL_LAST_TIME_UP"
Me.LBL_LAST_TIME_UP.Size = New System.Drawing.Size(468, 25)
Me.LBL_LAST_TIME_UP.TabIndex = 6
Me.LBL_LAST_TIME_UP.TabIndex = 5
Me.LBL_LAST_TIME_UP.Text = "Last download date: "
Me.LBL_LAST_TIME_UP.TextAlign = System.Drawing.ContentAlignment.TopCenter
'
@@ -256,9 +252,77 @@ Namespace DownloadObjects
Me.NUM_DELAY.NumberMaximum = New Decimal(New Integer() {1440, 0, 0, 0})
Me.NUM_DELAY.NumberUpDownAlign = System.Windows.Forms.LeftRightAlignment.Left
Me.NUM_DELAY.Size = New System.Drawing.Size(468, 22)
Me.NUM_DELAY.TabIndex = 5
Me.NUM_DELAY.TabIndex = 4
Me.NUM_DELAY.Text = "0"
'
'TP_NOTIFY
'
TP_NOTIFY.ColumnCount = 4
TP_NOTIFY.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25.0!))
TP_NOTIFY.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25.0!))
TP_NOTIFY.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25.0!))
TP_NOTIFY.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25.0!))
TP_NOTIFY.Controls.Add(Me.CH_NOTIFY, 0, 0)
TP_NOTIFY.Controls.Add(Me.CH_SHOW_PIC, 2, 0)
TP_NOTIFY.Controls.Add(Me.CH_SHOW_PIC_USER, 3, 0)
TP_NOTIFY.Controls.Add(Me.CH_NOTIFY_SIMPLE, 1, 0)
TP_NOTIFY.Dock = System.Windows.Forms.DockStyle.Fill
TP_NOTIFY.Location = New System.Drawing.Point(1, 166)
TP_NOTIFY.Margin = New System.Windows.Forms.Padding(0)
TP_NOTIFY.Name = "TP_NOTIFY"
TP_NOTIFY.RowCount = 1
TP_NOTIFY.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_NOTIFY.Size = New System.Drawing.Size(474, 25)
TP_NOTIFY.TabIndex = 2
'
'CH_NOTIFY
'
Me.CH_NOTIFY.AutoSize = True
Me.CH_NOTIFY.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_NOTIFY.Location = New System.Drawing.Point(3, 3)
Me.CH_NOTIFY.Name = "CH_NOTIFY"
Me.CH_NOTIFY.Size = New System.Drawing.Size(112, 19)
Me.CH_NOTIFY.TabIndex = 0
Me.CH_NOTIFY.Text = "Show notifications"
TT_MAIN.SetToolTip(Me.CH_NOTIFY, "Show notification when some data has been downloaded")
Me.CH_NOTIFY.UseVisualStyleBackColor = True
'
'CH_SHOW_PIC
'
Me.CH_SHOW_PIC.AutoSize = True
Me.CH_SHOW_PIC.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_SHOW_PIC.Location = New System.Drawing.Point(239, 3)
Me.CH_SHOW_PIC.Name = "CH_SHOW_PIC"
Me.CH_SHOW_PIC.Size = New System.Drawing.Size(112, 19)
Me.CH_SHOW_PIC.TabIndex = 2
Me.CH_SHOW_PIC.Text = "Image"
TT_MAIN.SetToolTip(Me.CH_SHOW_PIC, "Show downloaded image in notification")
Me.CH_SHOW_PIC.UseVisualStyleBackColor = True
'
'CH_SHOW_PIC_USER
'
Me.CH_SHOW_PIC_USER.AutoSize = True
Me.CH_SHOW_PIC_USER.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_SHOW_PIC_USER.Location = New System.Drawing.Point(357, 3)
Me.CH_SHOW_PIC_USER.Name = "CH_SHOW_PIC_USER"
Me.CH_SHOW_PIC_USER.Size = New System.Drawing.Size(114, 19)
Me.CH_SHOW_PIC_USER.TabIndex = 3
Me.CH_SHOW_PIC_USER.Text = "User icon"
TT_MAIN.SetToolTip(Me.CH_SHOW_PIC_USER, "Show user image in notification")
Me.CH_SHOW_PIC_USER.UseVisualStyleBackColor = True
'
'CH_NOTIFY_SIMPLE
'
Me.CH_NOTIFY_SIMPLE.AutoSize = True
Me.CH_NOTIFY_SIMPLE.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_NOTIFY_SIMPLE.Location = New System.Drawing.Point(121, 3)
Me.CH_NOTIFY_SIMPLE.Name = "CH_NOTIFY_SIMPLE"
Me.CH_NOTIFY_SIMPLE.Size = New System.Drawing.Size(112, 19)
Me.CH_NOTIFY_SIMPLE.TabIndex = 1
Me.CH_NOTIFY_SIMPLE.Text = "Simple"
TT_MAIN.SetToolTip(Me.CH_NOTIFY_SIMPLE, resources.GetString("CH_NOTIFY_SIMPLE.ToolTip"))
Me.CH_NOTIFY_SIMPLE.UseVisualStyleBackColor = True
'
'AutoDownloaderEditorForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
@@ -285,6 +349,8 @@ Namespace DownloadObjects
TP_MODE.PerformLayout()
CType(Me.TXT_TIMER, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.NUM_DELAY, System.ComponentModel.ISupportInitialize).EndInit()
TP_NOTIFY.ResumeLayout(False)
TP_NOTIFY.PerformLayout()
Me.ResumeLayout(False)
End Sub
@@ -295,9 +361,12 @@ Namespace DownloadObjects
Private WithEvents OPT_SPEC As RadioButton
Private WithEvents OPT_DISABLED As RadioButton
Private WithEvents CH_NOTIFY As CheckBox
Friend WithEvents TXT_TIMER As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents TXT_TIMER As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents OPT_GROUP As RadioButton
Private WithEvents LBL_LAST_TIME_UP As Label
Private WithEvents NUM_DELAY As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents CH_SHOW_PIC As CheckBox
Private WithEvents CH_SHOW_PIC_USER As CheckBox
Private WithEvents CH_NOTIFY_SIMPLE As CheckBox
End Class
End Namespace

View File

@@ -227,6 +227,14 @@
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value>
</data>
<metadata name="TP_NOTIFY.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<data name="CH_NOTIFY_SIMPLE.ToolTip" xml:space="preserve">
<value>Show a simple notification instead of a user notification.
This means that if any user data has been downloaded with the plan, a simple notification will be shown with the number of users downloaded.
The 'Image' and 'User icon' parameters will be ignored.</value>
</data>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>

View File

@@ -8,17 +8,16 @@
' but WITHOUT ANY WARRANTY
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Controls.Base
Imports PersonalUtilities.Forms.Toolbars
Imports DModes = SCrawler.DownloadObjects.AutoDownloader.Modes
Namespace DownloadObjects
Friend Class AutoDownloaderEditorForm : Implements IOkCancelToolbar
Private ReadOnly MyDefs As DefaultFormOptions
Friend Class AutoDownloaderEditorForm
Private WithEvents MyDefs As DefaultFormOptions
Private ReadOnly MyGroups As List(Of String)
Private ReadOnly Property Plan As AutoDownloader
Friend Sub New(ByRef _Plan As AutoDownloader)
InitializeComponent()
Plan = _Plan
MyDefs = New DefaultFormOptions
MyDefs = New DefaultFormOptions(Me, Settings.Design)
MyGroups.ListAddList(Plan.Groups, LAP.NotContainsOnly)
End Sub
Private Class AutomationTimerChecker : Implements IFieldsCheckerProvider
@@ -39,7 +38,7 @@ Namespace DownloadObjects
End Class
Private Sub AutoDownloaderEditorForm_Load(sender As Object, e As EventArgs) Handles Me.Load
With MyDefs
.MyViewInitialize(Me, Settings.Design, True)
.MyViewInitialize(True)
.AddOkCancelToolbar()
With Plan
Select Case .Mode
@@ -49,14 +48,17 @@ Namespace DownloadObjects
Case DModes.Specified : OPT_SPEC.Checked = True
Case DModes.Groups : OPT_GROUP.Checked = True
End Select
ChangeEnabled()
DEF_GROUP.Set(Plan)
If MyGroups.Count > 0 Then TXT_GROUPS.Text = MyGroups.ListToString
If Settings.Groups.Count = 0 Then TXT_GROUPS.Clear() : TXT_GROUPS.Enabled = False
CH_NOTIFY.Checked = .ShowNotifications
CH_NOTIFY_SIMPLE.Checked = .ShowSimpleNotification
CH_SHOW_PIC.Checked = .ShowPictureDownloaded
CH_SHOW_PIC_USER.Checked = .ShowPictureUser
TXT_TIMER.Text = .Timer
NUM_DELAY.Value = .StartupDelay
LBL_LAST_TIME_UP.Text = .Information
ChangeEnabled()
End With
.MyFieldsChecker = New FieldsChecker
With .MyFieldsCheckerE
@@ -71,8 +73,8 @@ Namespace DownloadObjects
Private Sub AutoDownloaderEditorForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
MyGroups.Clear()
End Sub
Private Sub OK() Implements IOkCancelToolbar.OK
If If(MyDefs.MyFieldsChecker?.AllParamsOK, True) Then
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
If MyDefs.MyFieldsChecker.AllParamsOK Then
With Plan
Select Case True
Case OPT_DISABLED.Checked : .Mode = DModes.None
@@ -84,6 +86,10 @@ Namespace DownloadObjects
DEF_GROUP.Get(Plan)
.Groups.Clear()
.Groups.ListAddList(MyGroups)
.ShowNotifications = CH_NOTIFY.Checked
.ShowSimpleNotification = CH_NOTIFY_SIMPLE.Checked
.ShowPictureDownloaded = CH_SHOW_PIC.Checked
.ShowPictureUser = CH_SHOW_PIC_USER.Checked
.Timer = AConvert(Of Integer)(TXT_TIMER.Text, AutoDownloader.DefaultTimer)
.StartupDelay = NUM_DELAY.Value
.Update()
@@ -91,10 +97,7 @@ Namespace DownloadObjects
MyDefs.CloseForm()
End If
End Sub
Private Sub Cancel() Implements IOkCancelToolbar.Cancel
MyDefs.CloseForm(DialogResult.Cancel)
End Sub
Private Sub TXT_GROUPS_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_GROUPS.ActionOnButtonClick
Private Sub TXT_GROUPS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles TXT_GROUPS.ActionOnButtonClick
Select Case Sender.DefaultButton
Case ActionButton.DefaultButtons.Edit
Using f As New LabelsForm(MyGroups, Settings.Groups.Select(Function(g) g.Name)) With {.Text = "Groups"}
@@ -119,14 +122,17 @@ Namespace DownloadObjects
Private Sub OPT_GROUP_CheckedChanged(sender As Object, e As EventArgs) Handles OPT_GROUP.CheckedChanged
ChangeEnabled()
End Sub
Private Sub ChangeEnabled()
Private Sub ChangeEnabled() Handles CH_NOTIFY.CheckedChanged, CH_NOTIFY_SIMPLE.CheckedChanged
DEF_GROUP.Enabled = OPT_SPEC.Checked
TXT_GROUPS.Enabled = OPT_GROUP.Checked
TXT_TIMER.Enabled = Not OPT_DISABLED.Checked
NUM_DELAY.Enabled = Not OPT_DISABLED.Checked
CH_NOTIFY.Enabled = Not OPT_DISABLED.Checked
CH_NOTIFY_SIMPLE.Enabled = CH_NOTIFY.Enabled And CH_NOTIFY.Checked
CH_SHOW_PIC.Enabled = CH_NOTIFY.Checked And Not OPT_DISABLED.Checked And Not CH_NOTIFY_SIMPLE.Checked
CH_SHOW_PIC_USER.Enabled = CH_NOTIFY.Checked And Not OPT_DISABLED.Checked And Not CH_NOTIFY_SIMPLE.Checked
End Sub
Private Sub NUM_DELAY_ActionOnButtonClick(ByVal Sender As ActionButton) Handles NUM_DELAY.ActionOnButtonClick
Private Sub NUM_DELAY_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles NUM_DELAY.ActionOnButtonClick
If Sender.DefaultButton = ActionButton.DefaultButtons.Clear Then NUM_DELAY.Value = 0
End Sub
End Class

View File

@@ -0,0 +1,117 @@
' Copyright (C) 2022 Andy
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Namespace DownloadObjects
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Friend Class DownloadFeedForm : Inherits System.Windows.Forms.Form
<System.Diagnostics.DebuggerNonUserCode()>
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
Private components As System.ComponentModel.IContainer
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Dim SEP_1 As System.Windows.Forms.ToolStripSeparator
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(DownloadFeedForm))
Me.ToolbarTOP = New System.Windows.Forms.ToolStrip()
Me.BTT_REFRESH = New System.Windows.Forms.ToolStripButton()
Me.BTT_CLEAR = New System.Windows.Forms.ToolStripButton()
Me.TP_DATA = New System.Windows.Forms.TableLayoutPanel()
SEP_1 = New System.Windows.Forms.ToolStripSeparator()
Me.ToolbarTOP.SuspendLayout()
Me.SuspendLayout()
'
'SEP_1
'
SEP_1.Name = "SEP_1"
SEP_1.Size = New System.Drawing.Size(6, 25)
'
'ToolbarTOP
'
Me.ToolbarTOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden
Me.ToolbarTOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_REFRESH, Me.BTT_CLEAR, SEP_1})
Me.ToolbarTOP.Location = New System.Drawing.Point(0, 0)
Me.ToolbarTOP.Name = "ToolbarTOP"
Me.ToolbarTOP.Size = New System.Drawing.Size(484, 25)
Me.ToolbarTOP.TabIndex = 0
'
'BTT_REFRESH
'
Me.BTT_REFRESH.Image = Global.SCrawler.My.Resources.Resources.Refresh
Me.BTT_REFRESH.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_REFRESH.Name = "BTT_REFRESH"
Me.BTT_REFRESH.Size = New System.Drawing.Size(66, 22)
Me.BTT_REFRESH.Text = "Refresh"
Me.BTT_REFRESH.ToolTipText = "Refresh data list"
'
'BTT_CLEAR
'
Me.BTT_CLEAR.Image = Global.SCrawler.My.Resources.Resources.Delete
Me.BTT_CLEAR.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_CLEAR.Name = "BTT_CLEAR"
Me.BTT_CLEAR.Size = New System.Drawing.Size(54, 22)
Me.BTT_CLEAR.Text = "Clear"
Me.BTT_CLEAR.ToolTipText = "Clear data list"
'
'TP_DATA
'
Me.TP_DATA.AutoScroll = True
Me.TP_DATA.ColumnCount = 1
Me.TP_DATA.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_DATA.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
Me.TP_DATA.Dock = System.Windows.Forms.DockStyle.Fill
Me.TP_DATA.Location = New System.Drawing.Point(0, 25)
Me.TP_DATA.Name = "TP_DATA"
Me.TP_DATA.RowCount = 11
Me.TP_DATA.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TP_DATA.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TP_DATA.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TP_DATA.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TP_DATA.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TP_DATA.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TP_DATA.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TP_DATA.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TP_DATA.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TP_DATA.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TP_DATA.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TP_DATA.Size = New System.Drawing.Size(484, 436)
Me.TP_DATA.TabIndex = 1
'
'DownloadFeedForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.BackColor = System.Drawing.SystemColors.Window
Me.ClientSize = New System.Drawing.Size(484, 461)
Me.Controls.Add(Me.TP_DATA)
Me.Controls.Add(Me.ToolbarTOP)
Me.ForeColor = System.Drawing.SystemColors.WindowText
Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon)
Me.KeyPreview = True
Me.MinimumSize = New System.Drawing.Size(300, 300)
Me.Name = "DownloadFeedForm"
Me.Text = "Download Feed"
Me.ToolbarTOP.ResumeLayout(False)
Me.ToolbarTOP.PerformLayout()
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Private WithEvents ToolbarTOP As ToolStrip
Private WithEvents TP_DATA As TableLayoutPanel
Private WithEvents BTT_REFRESH As ToolStripButton
Private WithEvents BTT_CLEAR As ToolStripButton
End Class
End Namespace

View File

@@ -0,0 +1,203 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="ToolbarTOP.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAABMLAAATCwAAAAAAAAAA
AAAZeOoAGXjqJBl46p4ZeOrtGXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq7Rl4
6p4ZeOokGXjqABl46iQZeOq+GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46r4ZeOokGXjqnhl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46p4ZeOrrGXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GHfq/xh3
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8Yd+r/F3fq/xd36v8Xd+r/GHjq/xl46v8ZeOr/GHjq/xd3
6v8Xd+r/F3fq/xh36v8ZeOr/GXjq/xl46v8ZeOr/GXjq6xl46v4ZeOr/GXjq/xl46v8ZeOr/GHfq/xl4
6v8pguz/KYHr/xl46v8Yd+r/GXjq/xl46v8ZeOr/GXjq/yqC7P8yh+z/Mofs/zKH7P8mf+v/GXjq/xl4
6v8hfev/Mofs/zOH7P8zh+z/L4Xs/xt56v8ZeOr/GXjq/xl46v8ZeOr+GXjq/xl46v8ZeOr/GXjq/xh3
6v8ogev/j731/9Xm+//T5fv/ibr0/yV/6/8Yd+r/GXjq/xl46v8ceur/o8n3/+Pv/P/g7fz/4+78/3qx
8/8Wdur/Fnbq/1id8P/e7Pz/4e38/+Pu/P/A2vn/KoLs/xh36v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/4289f/+/v/////////////9/v//hbf0/xh36v8ZeOr/GHjq/yN+6//J3/r/////////
////////fLLz/xV26v8Vdur/bKjy//7+/////////////9Pl+/8ogev/GHfq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xh36v8ogev/0eT7///////////////////////K4Pr/JH/r/xh46v8Xd+r/N4rt/+Pv
/P////////////v9//9hovH/FXbq/xV26v+CtfT/////////////////xN36/yF96/8YeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GHfq/yeA6//P4/v//////////////////////8jf+v8jfuv/GHjq/xV2
6v9npvH/+/3/////////////6vP9/z+P7v8Xd+r/GXjq/6PJ9/////////////////+rzvf/Gnnq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GHjq/4W39P/8/f/////////////6/P//fLLz/xh3
6v8YeOr/IHzr/7bU+P/////////////////C2/n/In3r/xh36v8mgOv/zOH6/////////////////4e4
9P8Wdur/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8Yd+r/JH7r/4C18//I3/r/x976/3uy
8/8hfev/GHjq/xZ26v9lpfH/9fn+/////////////////32z8/8Wdur/Fnbq/0qU7v/w9v7/////////
///4+/7/Wp7w/xV26v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8YeOr/GHfq/yN+
6/8ifev/F3fq/xh46v8Wdur/QI/u/9jo+//////////////////a6vz/NYnt/xd36v8Xd+r/i7v0////
/////////////9zr/P8yhuz/F3fq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GHjq/xh46v8YeOr/Fnbq/z+O7f/I3/r//////////////////P3//32z8/8Xd+r/F3fq/zCF
7P/V5vv/////////////////pMr3/xp56v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xh46v8Xd+r/FXbq/x976/9jo/H/1+f7//////////////////////+41fj/JoDr/xh3
6v8Xd+r/frPz//3+//////////////b6/v9anvD/Fnbq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8beer/IX3r/zSI7P9jpPH/s9P4//T5/v//////////////////////0uX7/z2N
7f8Xd+r/Fnfq/z2N7f/d6/z/////////////////wNr5/yR+6/8YeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8Yd+r/JoDr/53F9v/G3vr/4e38//n8/v///////////////////////////9Pl
+/9IlO7/Fnfq/xh36v8ifev/rc/4//////////////////b6/v9jo/H/Fnbq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xh36v8thOz/2+r8//////////////////////////////////z9
//+61/n/Po7t/xZ36v8YeOr/G3nq/4m69P/7/P//////////////////r9D4/yF86/8YeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GHfq/y2E7P/b6vz///////////////////////7+
///e7Pz/gLTz/yeA6/8Xd+r/GHfq/xt56v97svP/9Pj+/////////////////+Dt/P9DkO7/Fnfq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8Yd+r/LYTs/9vq/P///////P3//+31
/f/G3vr/gbX0/ziK7f8Xd+r/GHfq/xd36v8hfev/h7j0//T4/v/////////////////0+P7/bKny/xd3
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xh46v8kfuv/e7Hz/4G1
9P9mpfH/Q5Hu/yR+6/8Wdur/F3fq/xh36v8Wdur/OYvt/6rN9//5/P7/////////////////+vz//4q7
9P8ceur/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8Wdur/FXbq/xV26v8Wdur/GHfq/xZ26v8Wdur/K4Ps/3ev8//a6fz///////////////////////r8
//+VwfX/IHzr/xh36v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xZ26v8Vdur/FXbq/xd36v8ifev/QpDu/4K29P/Q4/v/+/3/////////////////////
///1+f7/jLz1/yF96/8Yd+r/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ee+r/T5fv/2Oj8f94sPP/msT2/8Td+v/s9P3//v7/////////////////////
////////4+/8/3Cr8v8ceur/GHfq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GHfq/yyD7P/V5vv//v//////////////////////////////////////
////////+Pv+/7XU+P9Gku7/F3fq/xh46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8Yd+r/LYPs/9rp/P//////////////////////////////
////////+Pv+/8fe+v9pp/H/In7r/xZ26v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xh36v8thOz/2un8////////////////////
///7/f//4+/8/63P+P9io/H/J4Dr/xZ26v8YeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GHfq/yqC7P+/2vn/3Ov8/83i
+v+11Pj/kb71/2Ok8f83iu3/HHrq/xZ26v8Yd+r/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr+GXjq/xl46v8ZeOr/G3nq/y6E
7P8thOz/JX/r/xx66v8Xd+r/FXbq/xd36v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/hl46usZeOr/GXjq/xl4
6v8ZeOr/GHfq/xh36v8YeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOrrGXjqnhl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6p4ZeOokGXjqvhl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOq+GXjqJBl46gAZeOokGXjqnxl46u0ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl46v8ZeOr/GXjq/xl4
6v8ZeOrtGXjqnhl46iQZeOoAgAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAE=
</value>
</data>
</root>

View File

@@ -0,0 +1,374 @@
' Copyright (C) 2022 Andy
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports System.ComponentModel
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Toolbars
Imports PersonalUtilities.Tools
Imports RCI = PersonalUtilities.Forms.Toolbars.RangeSwitcherToolbar.ControlItem
Imports UserMediaD = SCrawler.DownloadObjects.TDownloader.UserMediaD
Namespace DownloadObjects
Friend Class DownloadFeedForm
#Region "Declarations"
Private WithEvents MyDefs As DefaultFormOptions
Private WithEvents MyRange As RangeSwitcherToolbar(Of UserMediaD)
Private ReadOnly DataList As List(Of UserMediaD)
Private WithEvents BTT_DELETE_SELECTED As ToolStripButton
Private WithEvents LBL_FILES As ToolStripLabel
Private DataRows As Integer = 10
Private DataColumns As Integer = 1
Private FeedEndless As Boolean = False
Private ReadOnly FileNotExist As Predicate(Of UserMediaD) = Function(d) Not d.Data.File.Exists
#End Region
#Region "Initializer"
Friend Sub New()
InitializeComponent()
MyDefs = New DefaultFormOptions(Me, Settings.Design)
MyRange = New RangeSwitcherToolbar(Of UserMediaD)(ToolbarTOP)
DataList = New List(Of UserMediaD)
LBL_FILES = New ToolStripLabel With {.Text = String.Empty, .AutoToolTip = False, .ToolTipText = String.Empty}
BTT_DELETE_SELECTED = New ToolStripButton With {
.Text = "Delete selected",
.AutoToolTip = True,
.ToolTipText = "Delete marked files",
.Image = My.Resources.Delete,
.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText
}
End Sub
#End Region
#Region "Form handlers"
Private Sub DownloadFeedForm_Load(sender As Object, e As EventArgs) Handles Me.Load
With MyDefs
.MyViewInitialize()
LastWinState = WindowState
With MyRange
.AutoToolTip = True
.ButtonKey(RCI.Previous) = Keys.F3
.ButtonKey(RCI.Next) = Keys.F4
.AddThisToolbar()
End With
ToolbarTOP.Items.AddRange({New ToolStripSeparator, BTT_DELETE_SELECTED, New ToolStripSeparator, LBL_FILES})
UpdateSettings()
RefillList()
.EndLoaderOperations(False)
End With
End Sub
Private Sub DownloadFeedForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
e.Cancel = True
Hide()
End Sub
Private Sub DownloadFeedForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
ClearTable()
MyRange.Dispose()
BTT_CLEAR.Dispose()
DataList.Clear()
LBL_FILES.Dispose()
End Sub
Private Sub DownloadFeedForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If e.KeyCode = Keys.F5 Then RefillList() : e.Handled = True
End Sub
#End Region
#Region "Settings"
Friend Sub UpdateSettings()
With Settings
Dim c% = .FeedDataRows * .FeedDataColumns
Dim rangeChanged As Boolean = Not c = DataRows * DataColumns
DataRows = .FeedDataRows
DataColumns = .FeedDataColumns
FeedEndless = .FeedEndless
If rangeChanged Then
ClearTable()
ControlInvoke(TP_DATA, Sub()
With TP_DATA
.RowStyles.Clear()
.RowCount = 0
.ColumnStyles.Clear()
.ColumnCount = 0
Dim i%
Dim p% = IIf(DataColumns = 1, 100, 50)
For i = 0 To DataColumns - 1 : .ColumnStyles.Add(New ColumnStyle(SizeType.Percent, p)) : Next
.ColumnCount = .ColumnStyles.Count
For i = 0 To DataRows : .RowStyles.Add(New RowStyle(SizeType.Absolute, 0)) : Next
.RowCount = .RowStyles.Count
.HorizontalScroll.Visible = False
End With
End Sub)
End If
MyRange.HandlersSuspended = True
MyRange.Limit = c
MyRange.HandlersSuspended = False
If Not MyDefs.Initializing And rangeChanged Then RefillList()
End With
End Sub
#End Region
#Region "Refill"
Friend Sub Downloader_FilesChanged(ByVal Added As Boolean)
ControlInvoke(ToolbarTOP, LBL_FILES, Sub() LBL_FILES.Text = IIf(Added, "New files found", "Some files have been removed"))
LBL_FILES.ControlChangeColor(ToolbarTOP, Added, False)
End Sub
Private Sub RefillList() Handles BTT_REFRESH.Click
DataPopulated = False
Try : Downloader.Files.RemoveAll(FileNotExist) : Catch : End Try
DataList.ListAddList(Downloader.Files, LAP.ClearBeforeAdd, LAP.NotContainsOnly)
MyRange.Source = DataList
ControlInvoke(ToolbarTOP, LBL_FILES, Sub() LBL_FILES.Text = String.Empty)
LBL_FILES.ControlDropColor(ToolbarTOP)
If DataList.Count = 0 Then
ClearTable()
ElseIf Not DataPopulated Then
MyRange_IndexChanged(MyRange, Nothing)
End If
End Sub
Private Sub BTT_CLEAR_Click(sender As Object, e As EventArgs) Handles BTT_CLEAR.Click
Downloader.Files.Clear()
ClearTable()
RefillList()
End Sub
#End Region
#Region "Delete"
Private Sub BTT_DELETE_SELECTED_Click(sender As Object, e As EventArgs) Handles BTT_DELETE_SELECTED.Click
Const MsgTitle$ = "Deleting marked files"
Try
Dim c As IEnumerable(Of FeedMedia) = ControlInvoke(TP_DATA, Function() If(TP_DATA.Controls.Count > 0, TP_DATA.Controls.ToObjectsList.Cast(Of FeedMedia)().Where(Function(f) f.Checked), New FeedMedia() {}))
If c.ListExists Then
If MsgBoxE({$"Are you sure you want to delete {c.Count} file(s)?", MsgTitle}, vbExclamation,,, {"Process", "Cancel"}) = 0 Then
Dim indx% = MyRange.CurrentIndex
Dim d% = 0
ControlInvoke(TP_DATA, Sub()
With TP_DATA
.SuspendLayout()
For Each fm As FeedMedia In c
If fm.DeleteFile(True) Then
d += 1
DataList.RemoveAll(Function(dd) dd.Data.File = fm.File)
TPRemoveControl(fm, False)
End If
Next
.ResumeLayout(True)
End With
End Sub)
If d > 0 Then RefillAfterDelete()
MsgBoxE({$"{d}/{c.Count} file(s) deleted", MsgTitle})
Else
MsgBoxE({"Operation canceled", MsgTitle})
End If
Else
MsgBoxE({"No files selected", MsgTitle}, vbExclamation)
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, MsgTitle)
End Try
End Sub
Private Sub FeedMedia_MediaDeleted(ByVal Sender As FeedMedia)
Try
ControlInvoke(TP_DATA, Sub() TPRemoveControl(Sender, True))
DataList.RemoveAll(Function(dd) dd.Data.File = Sender.File)
RefillAfterDelete()
Catch
End Try
End Sub
Private Sub TPRemoveControl(ByVal CNT As FeedMedia, ByVal Suspend As Boolean)
Try
If Suspend Then TP_DATA.SuspendLayout()
Dim p As TableLayoutPanelCellPosition = TP_DATA.GetCellPosition(CNT)
Dim HeightChanged As Boolean = False
TP_DATA.Controls.Remove(CNT)
CNT.Dispose()
If DataColumns = 1 Then
If p.Column >= 0 And p.Row >= 0 Then TP_DATA.RowStyles(p.Row).Height = 0 : HeightChanged = True
Else
If p.Row.ValueBetween(0, TP_DATA.RowStyles.Count - 1) And p.Column.ValueBetween(0, TP_DATA.ColumnStyles.Count - 1) Then
Dim found As Boolean = False
For i% = 0 To TP_DATA.ColumnStyles.Count - 1
If Not TP_DATA.GetControlFromPosition(i, p.Row) Is Nothing Then found = True : Exit For
Next
If Not found Then TP_DATA.RowStyles(p.Row).Height = 0 : HeightChanged = True
End If
End If
If HeightChanged Then TP_DATA.AutoScroll = False : TP_DATA.AutoScroll = True
Catch
Finally
If Suspend Then TP_DATA.ResumeLayout(True)
End Try
End Sub
Private Sub RefillAfterDelete()
If ControlInvoke(TP_DATA, Function() TP_DATA.Controls.Count) = 0 Then
With MyRange
Dim indx% = .CurrentIndex
.HandlersSuspended = True
.Source = DataList
If .Count > 0 Then
If indx.ValueBetween(0, .Count - 1) Then
.CurrentIndex = indx
ElseIf (indx - 1).ValueBetween(0, .Count - 1) Then
.CurrentIndex = indx - 1
Else
.CurrentIndex = .Count - 1
End If
.HandlersSuspended = False
DirectCast(MyRange.Switcher, RangeSwitcher(Of UserMediaD)).PerformIndexChanged()
End If
.HandlersSuspended = False
End With
End If
End Sub
#End Region
#Region "Range"
Private DataPopulated As Boolean = False
Private Structure TPCELL
Private ReadOnly RowsCount As Integer
Private ReadOnly ColumnsCount As Integer
Friend ReadOnly Row As Integer
Friend ReadOnly Column As Integer
Friend Sub New(ByVal RowsCount As Integer, ByVal ColumnsCount As Integer)
Me.RowsCount = RowsCount
Me.ColumnsCount = ColumnsCount
Row = 0
Column = 0
End Sub
Private Sub New(ByVal RowsCount As Integer, ByVal ColumnsCount As Integer, ByVal Row As Integer, ByVal Column As Integer)
Me.New(RowsCount, ColumnsCount)
Me.Row = Row
Me.Column = Column
End Sub
Friend Function [Next]() As TPCELL
Dim r% = Row
Dim c% = Column + 1
If Not c.ValueBetween(0, ColumnsCount - 1) Then c = 0 : r += 1
Return New TPCELL(RowsCount, ColumnsCount, r, c)
End Function
End Structure
Private RefillInProgress As Boolean = False
Private Sub MyRange_IndexChanged(ByVal Sender As IRangeSwitcherProvider, ByVal e As EventArgs) Handles MyRange.IndexChanged
Try
If Not RefillInProgress AndAlso Sender.CurrentIndex >= 0 Then
RefillInProgress = True
AllowTopScroll = False
ScrollSuspended = True
Dim d As List(Of UserMediaD) = MyRange.Current
Dim d2 As List(Of UserMediaD)
Dim i%
If d.ListExists And d.All(Function(md) FileNotExist(md)) Then
i = Sender.CurrentIndex
Sender.HandlersSuspended = True
RefillList()
If Sender.Count > 0 Then
If i.ValueBetween(0, Sender.Count - 1) Then Sender.CurrentIndex = i
Sender.HandlersSuspended = False
End If
RefillInProgress = False
Sender.HandlersSuspended = False
DirectCast(MyRange.Switcher, RangeSwitcher(Of UserMediaD)).PerformIndexChanged()
Exit Sub
End If
If d.ListExists Then
ClearTable()
If Sender.CurrentIndex > 0 And FeedEndless Then
d2 = DirectCast(MyRange.Switcher, RangeSwitcher(Of UserMediaD)).Item(Sender.CurrentIndex - 1).ListTake(-2, DataColumns, EDP.ReturnValue).ListIfNothing
If d2.Count > 0 Then d.InsertRange(0, d2) : d2.Clear()
End If
Dim w% = GetWidth()
Dim p As New TPCELL(DataRows, DataColumns)
Dim fmList As New List(Of FeedMedia)
d.ForEach(Sub(de) fmList.Add(New FeedMedia(de, w, AddressOf FeedMedia_MediaDeleted)))
If fmList.Count > 0 Then fmList.ListDisposeRemoveAll(Function(fm) fm Is Nothing OrElse fm.HasError)
If fmList.Count > 0 Then
For i = 0 To fmList.Count - 1
ControlInvoke(TP_DATA, Sub() TP_DATA.Controls.Add(fmList(i), p.Column, p.Row))
p = p.Next
Next
End If
ResizeGrid()
fmList.Clear()
d.Clear()
End If
RefillInProgress = False
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendInLog, ex, $"[DownloadObjects.DownloadFeedForm.Range.IndexChanged({Sender.CurrentIndex})]")
RefillInProgress = False
Finally
If Not RefillInProgress Then
ControlInvoke(TP_DATA, Sub()
With TP_DATA.VerticalScroll
If Offset = 1 Then .Value = 0 Else .Value = .Maximum
End With
End Sub)
ScrollSuspended = False
DataPopulated = True
End If
End Try
End Sub
#End Region
#Region "Size"
Private LastWinState As FormWindowState = FormWindowState.Normal
Private Function GetWidth() As Integer
Return (TP_DATA.Width - PaddingE.GetOf({Me, TP_DATA}).Horizontal(2)) / DataColumns
End Function
Private Sub DownloadFeedForm_ResizeEnd(sender As Object, e As EventArgs) Handles Me.ResizeEnd
ResizeGrid()
End Sub
Private Sub DownloadFeedForm_SizeChanged(sender As Object, e As EventArgs) Handles Me.SizeChanged
If Not LastWinState = WindowState And Not If(MyDefs?.Initializing, True) Then LastWinState = WindowState : ResizeGrid()
End Sub
Private Sub ResizeGrid()
ControlInvoke(TP_DATA, Sub()
With TP_DATA
If .Controls.Count > 0 Then
Dim w% = GetWidth()
Dim p As TableLayoutPanelCellPosition
Dim rh As New Dictionary(Of Integer, List(Of Integer))
For Each cnt As FeedMedia In .Controls
cnt.Width = w
p = .GetCellPosition(cnt)
If Not rh.ContainsKey(p.Row) Then rh.Add(p.Row, New List(Of Integer))
rh(p.Row).Add(cnt.Height)
Next
For i% = 0 To .RowStyles.Count - 1 : .RowStyles(i).Height = 0 : Next
If rh.Count > 0 Then
For Each kv In rh
.RowStyles(kv.Key).Height = kv.Value.Max
kv.Value.Clear()
Next
End If
rh.Clear()
.AutoScroll = False
.AutoScroll = True
End If
End With
End Sub)
End Sub
#End Region
#Region "Scroll"
Private AllowTopScroll As Boolean = False
Private ScrollSuspended As Boolean = False
Private Offset As Integer = 1
Private Sub TP_DATA_Paint(sender As Object, e As PaintEventArgs) Handles TP_DATA.Paint
If Not MyDefs.Initializing And Not ScrollSuspended And FeedEndless Then
ControlInvoke(TP_DATA, Sub()
With TP_DATA
Offset = IIf(.VerticalScroll.Value = 0 And AllowTopScroll, -1, 1)
If .VerticalScroll.Value + .VerticalScroll.LargeChange >= .DisplayRectangle.Height Or (.VerticalScroll.Value = 0 And AllowTopScroll) Then
If MyRange.TryMove(Offset) Then MyRange.Move(Offset)
End If
If Not AllowTopScroll And .VerticalScroll.Value > 0 Then AllowTopScroll = True
End With
End Sub)
End If
End Sub
#End Region
Private Sub ClearTable()
ControlInvoke(TP_DATA, Sub()
If TP_DATA.Controls.Count > 0 Then
For Each cnt As Control In TP_DATA.Controls : cnt.Dispose() : Next
TP_DATA.Controls.Clear()
End If
End Sub)
End Sub
End Class
End Namespace

View File

@@ -11,8 +11,8 @@ Imports Download = SCrawler.Plugin.ISiteSettings.Download
Imports TDJob = SCrawler.DownloadObjects.TDownloader.Job
Namespace DownloadObjects
Friend Class DownloadProgress : Implements IDisposable
Friend Event OnDownloadDone(ByVal Message As String)
Friend Event OnTotalCountChange()
Friend Event DownloadDone As NotificationEventHandler
Friend Event ProgressMaximumChanged()
Private ReadOnly TP_MAIN As TableLayoutPanel
Private ReadOnly TP_CONTROLS As TableLayoutPanel
Private WithEvents BTT_START As Button
@@ -89,10 +89,10 @@ Namespace DownloadObjects
End If
With Job
.Progress = New MyProgress(PR_MAIN, LBL_INFO) With {.DropCurrentProgressOnTotalChange = False}
.Progress = New MyProgress(PR_MAIN, LBL_INFO) With {.ResetProgressOnMaximumChanges = False}
With .Progress
AddHandler .OnProgressChange, AddressOf JobProgress_OnProgressChange
AddHandler .OnTotalCountChange, AddressOf JobProgress_OnTotalCountChange
AddHandler .ProgressChanged, AddressOf JobProgress_ProgressChanged
AddHandler .MaximumChanged, AddressOf JobProgress_MaximumChanged
End With
End With
@@ -139,7 +139,7 @@ Namespace DownloadObjects
Job.Progress.InformationTemporary = $"{Job.Host.Name} downloading started"
Job.Start()
Instance.Download(Job.Token)
RaiseEvent OnDownloadDone($"Downloading saved {Job.Host.Name} posts is completed")
RaiseEvent DownloadDone($"Downloading saved {Job.Host.Name} posts is completed")
Catch ex As Exception
Job.Progress.InformationTemporary = $"{Job.Host.Name} downloading error"
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, {$"{Job.Host.Name} saved posts downloading error", "Saved posts"})
@@ -147,15 +147,15 @@ Namespace DownloadObjects
btte.Invoke(BTT_START, True)
btte.Invoke(BTT_STOP, False)
Job.Stopped()
If Job.Type = Download.SavedPosts Then Job.Progress.TotalCount = 0 : Job.Progress.CurrentCounter = 0
If Job.Type = Download.SavedPosts Then Job.Progress.Maximum = 0 : Job.Progress.Value = 0
End Try
End Sub
#End Region
#Region "Progress, Jobs count"
Private Sub JobProgress_OnTotalCountChange(ByVal Source As IMyProgress, ByVal Index As Integer)
RaiseEvent OnTotalCountChange()
Private Sub JobProgress_MaximumChanged(ByVal Sender As Object, ByVal e As ProgressEventArgs)
RaiseEvent ProgressMaximumChanged()
End Sub
Private Sub JobProgress_OnProgressChange(ByVal Source As IMyProgress, ByVal Index As Integer)
Private Sub JobProgress_ProgressChanged(ByVal Sender As Object, ByVal e As ProgressEventArgs)
If Not Job.Type = Download.SavedPosts Then MainProgress.Perform()
End Sub
#End Region

View File

@@ -11,7 +11,7 @@ Imports PersonalUtilities.Forms
Imports SCrawler.DownloadObjects
Imports SCrawler.Plugin.Hosts
Friend Class DownloadSavedPostsForm
Friend Event OnDownloadDone As NotificationEventHandler
Friend Event DownloadDone As NotificationEventHandler
Private MyView As FormsView
Private ReadOnly JobsList As List(Of DownloadProgress)
Friend ReadOnly Property Working As Boolean
@@ -45,7 +45,7 @@ Friend Class DownloadSavedPostsForm
MyView.SetMeSize()
If JobsList.Count > 0 Then
For Each j As DownloadProgress In JobsList
AddHandler j.OnDownloadDone, AddressOf Jobs_OnDownloadDone
AddHandler j.DownloadDone, AddressOf Jobs_DownloadDone
TP_MAIN.RowStyles.Add(New RowStyle(SizeType.Absolute, 60))
TP_MAIN.RowCount += 1
TP_MAIN.Controls.Add(j.Get, 0, TP_MAIN.RowStyles.Count - 1)
@@ -65,8 +65,8 @@ Friend Class DownloadSavedPostsForm
[Stop]()
MyView.Dispose(Settings.Design)
End Sub
Private Sub Jobs_OnDownloadDone(ByVal Message As String)
RaiseEvent OnDownloadDone(Message)
Private Sub Jobs_DownloadDone(ByVal Message As String)
RaiseEvent DownloadDone(Message)
End Sub
Private Sub BTT_DOWN_ALL_Click(sender As Object, e As EventArgs) Handles BTT_DOWN_ALL.Click
Start()

View File

@@ -55,7 +55,7 @@ Namespace DownloadObjects
End If
BTT_CLEAR.Visible = ViewMode = ViewModes.Session
RefillList()
Catch ex As Exception
Catch
Finally
Opened = True
End Try
@@ -163,10 +163,10 @@ Namespace DownloadObjects
Try
If _LatestSelected.ValueBetween(0, _TempUsersList.Count - 1) AndAlso
Not DirectCast(_TempUsersList(_LatestSelected), UserDataBase).Disposed Then _TempUsersList(_LatestSelected).OpenFolder()
Catch ex As Exception
Catch
End Try
End Sub
Friend Sub Downloader_OnDownloadCountChange()
Friend Sub Downloader_DownloadCountChange()
If ViewMode = ViewModes.Session Then RefillList()
End Sub
Private Sub BTT_UP_Click(sender As Object, e As EventArgs) Handles BTT_UP.Click

206
SCrawler/Download/FeedMedia.Designer.vb generated Normal file
View File

@@ -0,0 +1,206 @@
' Copyright (C) 2022 Andy
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Namespace DownloadObjects
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Public Class FeedMedia : Inherits System.Windows.Forms.UserControl
<System.Diagnostics.DebuggerNonUserCode()>
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
Private components As System.ComponentModel.IContainer
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container()
Dim CONTEXT_SEP_1 As System.Windows.Forms.ToolStripSeparator
Dim CONTEXT_SEP_2 As System.Windows.Forms.ToolStripSeparator
Dim CONTEXT_SEP_3 As System.Windows.Forms.ToolStripSeparator
Dim TP_LBL As System.Windows.Forms.TableLayoutPanel
Me.CH_CHECKED = New System.Windows.Forms.CheckBox()
Me.LBL_INFO = New System.Windows.Forms.Label()
Me.CONTEXT_DATA = New System.Windows.Forms.ContextMenuStrip(Me.components)
Me.BTT_CONTEXT_OPEN_MEDIA = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_OPEN_USER = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_OPEN_USER_URL = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_OPEN_USER_POST = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_FIND_USER = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_INFO = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_DELETE = New System.Windows.Forms.ToolStripMenuItem()
Me.TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
CONTEXT_SEP_1 = New System.Windows.Forms.ToolStripSeparator()
CONTEXT_SEP_2 = New System.Windows.Forms.ToolStripSeparator()
CONTEXT_SEP_3 = New System.Windows.Forms.ToolStripSeparator()
TP_LBL = New System.Windows.Forms.TableLayoutPanel()
TP_LBL.SuspendLayout()
Me.CONTEXT_DATA.SuspendLayout()
Me.TP_MAIN.SuspendLayout()
Me.SuspendLayout()
'
'CONTEXT_SEP_1
'
CONTEXT_SEP_1.Name = "CONTEXT_SEP_1"
CONTEXT_SEP_1.Size = New System.Drawing.Size(134, 6)
'
'CONTEXT_SEP_2
'
CONTEXT_SEP_2.Name = "CONTEXT_SEP_2"
CONTEXT_SEP_2.Size = New System.Drawing.Size(134, 6)
'
'CONTEXT_SEP_3
'
CONTEXT_SEP_3.Name = "CONTEXT_SEP_3"
CONTEXT_SEP_3.Size = New System.Drawing.Size(134, 6)
'
'TP_LBL
'
TP_LBL.ColumnCount = 2
TP_LBL.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_LBL.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_LBL.Controls.Add(Me.CH_CHECKED, 0, 0)
TP_LBL.Controls.Add(Me.LBL_INFO, 1, 0)
TP_LBL.Dock = System.Windows.Forms.DockStyle.Fill
TP_LBL.Location = New System.Drawing.Point(0, 0)
TP_LBL.Margin = New System.Windows.Forms.Padding(0)
TP_LBL.Name = "TP_LBL"
TP_LBL.RowCount = 1
TP_LBL.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_LBL.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_LBL.Size = New System.Drawing.Size(146, 25)
TP_LBL.TabIndex = 0
'
'CH_CHECKED
'
Me.CH_CHECKED.AutoSize = True
Me.CH_CHECKED.CheckAlign = System.Drawing.ContentAlignment.MiddleCenter
Me.CH_CHECKED.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_CHECKED.Location = New System.Drawing.Point(3, 3)
Me.CH_CHECKED.Name = "CH_CHECKED"
Me.CH_CHECKED.Size = New System.Drawing.Size(19, 19)
Me.CH_CHECKED.TabIndex = 0
Me.CH_CHECKED.UseVisualStyleBackColor = True
'
'LBL_INFO
'
Me.LBL_INFO.AutoSize = True
Me.LBL_INFO.ContextMenuStrip = Me.CONTEXT_DATA
Me.LBL_INFO.Dock = System.Windows.Forms.DockStyle.Fill
Me.LBL_INFO.Location = New System.Drawing.Point(28, 0)
Me.LBL_INFO.Name = "LBL_INFO"
Me.LBL_INFO.Size = New System.Drawing.Size(115, 25)
Me.LBL_INFO.TabIndex = 1
Me.LBL_INFO.TextAlign = System.Drawing.ContentAlignment.MiddleLeft
'
'CONTEXT_DATA
'
Me.CONTEXT_DATA.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_CONTEXT_OPEN_MEDIA, Me.BTT_CONTEXT_OPEN_USER, CONTEXT_SEP_1, Me.BTT_CONTEXT_OPEN_USER_URL, Me.BTT_CONTEXT_OPEN_USER_POST, CONTEXT_SEP_2, Me.BTT_CONTEXT_FIND_USER, Me.BTT_CONTEXT_INFO, CONTEXT_SEP_3, Me.BTT_CONTEXT_DELETE})
Me.CONTEXT_DATA.Name = "CONTEXT_PIC"
Me.CONTEXT_DATA.Size = New System.Drawing.Size(138, 176)
'
'BTT_CONTEXT_OPEN_MEDIA
'
Me.BTT_CONTEXT_OPEN_MEDIA.Image = Global.SCrawler.My.Resources.Resources.Folder_32
Me.BTT_CONTEXT_OPEN_MEDIA.Name = "BTT_CONTEXT_OPEN_MEDIA"
Me.BTT_CONTEXT_OPEN_MEDIA.Size = New System.Drawing.Size(137, 22)
Me.BTT_CONTEXT_OPEN_MEDIA.Text = "Open"
'
'BTT_CONTEXT_OPEN_USER
'
Me.BTT_CONTEXT_OPEN_USER.Image = Global.SCrawler.My.Resources.Resources.Folder_32
Me.BTT_CONTEXT_OPEN_USER.Name = "BTT_CONTEXT_OPEN_USER"
Me.BTT_CONTEXT_OPEN_USER.Size = New System.Drawing.Size(137, 22)
Me.BTT_CONTEXT_OPEN_USER.Text = "Open user"
'
'BTT_CONTEXT_OPEN_USER_URL
'
Me.BTT_CONTEXT_OPEN_USER_URL.Image = Global.SCrawler.My.Resources.Resources.GlobeBlue_32
Me.BTT_CONTEXT_OPEN_USER_URL.Name = "BTT_CONTEXT_OPEN_USER_URL"
Me.BTT_CONTEXT_OPEN_USER_URL.Size = New System.Drawing.Size(137, 22)
Me.BTT_CONTEXT_OPEN_USER_URL.Text = "Open user"
'
'BTT_CONTEXT_OPEN_USER_POST
'
Me.BTT_CONTEXT_OPEN_USER_POST.Image = Global.SCrawler.My.Resources.Resources.GlobeBlue_32
Me.BTT_CONTEXT_OPEN_USER_POST.Name = "BTT_CONTEXT_OPEN_USER_POST"
Me.BTT_CONTEXT_OPEN_USER_POST.Size = New System.Drawing.Size(137, 22)
Me.BTT_CONTEXT_OPEN_USER_POST.Text = "Open post"
'
'BTT_CONTEXT_FIND_USER
'
Me.BTT_CONTEXT_FIND_USER.Image = Global.SCrawler.My.Resources.Resources.InfoPic_32
Me.BTT_CONTEXT_FIND_USER.Name = "BTT_CONTEXT_FIND_USER"
Me.BTT_CONTEXT_FIND_USER.Size = New System.Drawing.Size(137, 22)
Me.BTT_CONTEXT_FIND_USER.Text = "Find user"
'
'BTT_CONTEXT_INFO
'
Me.BTT_CONTEXT_INFO.Image = Global.SCrawler.My.Resources.Resources.InfoPic_32
Me.BTT_CONTEXT_INFO.Name = "BTT_CONTEXT_INFO"
Me.BTT_CONTEXT_INFO.Size = New System.Drawing.Size(137, 22)
Me.BTT_CONTEXT_INFO.Text = "Information"
'
'BTT_CONTEXT_DELETE
'
Me.BTT_CONTEXT_DELETE.Image = Global.SCrawler.My.Resources.Resources.Delete
Me.BTT_CONTEXT_DELETE.Name = "BTT_CONTEXT_DELETE"
Me.BTT_CONTEXT_DELETE.Size = New System.Drawing.Size(137, 22)
Me.BTT_CONTEXT_DELETE.Text = "Delete"
'
'TP_MAIN
'
Me.TP_MAIN.ColumnCount = 1
Me.TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
Me.TP_MAIN.Controls.Add(TP_LBL, 0, 0)
Me.TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
Me.TP_MAIN.Location = New System.Drawing.Point(0, 0)
Me.TP_MAIN.Margin = New System.Windows.Forms.Padding(0)
Me.TP_MAIN.Name = "TP_MAIN"
Me.TP_MAIN.RowCount = 2
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_MAIN.Size = New System.Drawing.Size(146, 146)
Me.TP_MAIN.TabIndex = 0
'
'FeedMedia
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.BackColor = System.Drawing.SystemColors.Window
Me.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D
Me.Controls.Add(Me.TP_MAIN)
Me.ForeColor = System.Drawing.SystemColors.WindowText
Me.Margin = New System.Windows.Forms.Padding(0)
Me.Name = "FeedMedia"
Me.Size = New System.Drawing.Size(146, 146)
TP_LBL.ResumeLayout(False)
TP_LBL.PerformLayout()
Me.CONTEXT_DATA.ResumeLayout(False)
Me.TP_MAIN.ResumeLayout(False)
Me.ResumeLayout(False)
End Sub
Private WithEvents TP_MAIN As TableLayoutPanel
Private WithEvents CONTEXT_DATA As ContextMenuStrip
Private WithEvents BTT_CONTEXT_OPEN_MEDIA As ToolStripMenuItem
Private WithEvents BTT_CONTEXT_OPEN_USER_URL As ToolStripMenuItem
Private WithEvents BTT_CONTEXT_OPEN_USER_POST As ToolStripMenuItem
Private WithEvents BTT_CONTEXT_FIND_USER As ToolStripMenuItem
Private WithEvents BTT_CONTEXT_DELETE As ToolStripMenuItem
Private WithEvents BTT_CONTEXT_OPEN_USER As ToolStripMenuItem
Private WithEvents CH_CHECKED As CheckBox
Private WithEvents LBL_INFO As Label
Private WithEvents BTT_CONTEXT_INFO As ToolStripMenuItem
End Class
End Namespace

View File

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

View File

@@ -0,0 +1,241 @@
' Copyright (C) 2022 Andy
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
'Imports System.Windows.Forms.PropertyGridInternal
Imports System.ComponentModel
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Tools
Imports SCrawler.API.Base
Imports UserMediaD = SCrawler.DownloadObjects.TDownloader.UserMediaD
Namespace DownloadObjects
<ToolboxItem(False), DesignTimeVisible(False)>
Public Class FeedMedia
#Region "Declarations"
Friend Event MediaDeleted(ByVal Sender As Object)
Private Const VideoHeight As Integer = 450
Private WithEvents MyPicture As PictureBox
Private ReadOnly MyImage As ImageRenderer
Private ReadOnly MyVideo As FeedVideo
Friend ReadOnly Property Exists As Boolean
Get
Return Not MyPicture Is Nothing Or Not MyVideo Is Nothing
End Get
End Property
Friend ReadOnly Property HasError As Boolean
Friend ReadOnly File As SFile
Public Shadows Property Width As Integer
Get
Return MyBase.Width
End Get
Set(ByVal w As Integer)
If Size.Width <> w Then
Dim s As New Size(w, If(MyImage Is Nothing, VideoHeight, MyImage.FitToWidthF(w).Height))
Dim objSize As Size = s
objSize.Height += (TP_MAIN.RowStyles(0).Height + PaddingE.GetOf({TP_MAIN}).Vertical(2))
MinimumSize = objSize
MyBase.MaximumSize = objSize
Size = objSize
If Not MyImage Is Nothing Then
With MyPicture
.MinimumSize = Nothing
.MaximumSize = Nothing
.Size = s
.MinimumSize = s
.MaximumSize = s
End With
End If
End If
End Set
End Property
Private ReadOnly UserKey As String
Private ReadOnly Post As UserMedia
Friend ReadOnly Property Checked As Boolean
Get
Return CH_CHECKED.Checked
End Get
End Property
Friend ReadOnly Property Information As String
#End Region
#Region "Initializers"
Public Sub New()
InitializeComponent()
End Sub
Friend Sub New(ByVal Media As UserMediaD, ByVal Width As Integer, ByVal Handler As MediaDeletedEventHandler)
Try
InitializeComponent()
File = Media.Data.File
If Not File.Exists And Media.Data.Type = UserMedia.Types.Video Then File.Path = $"{File.Path.CSFilePS}Video"
If Not File.Exists Then
If Not Media.Data.SpecialFolder.IsEmptyString Then
File.Path = $"{File.Path.CSFilePS}{Media.Data.SpecialFolder}".CSFileP
If Not File.Exists And Media.Data.Type = UserMedia.Types.Video Then File.Path = $"{File.Path.CSFilePS}Video"
End If
End If
If File.Exists Then
Information = $"Type: {Media.Data.Type}"
Information.StringAppendLine($"File: {File.File}")
Information.StringAppendLine($"Address: {File}")
Information.StringAppendLine($"Downloaded: {Media.Date.ToStringDate(ADateTime.Formats.BaseDateTime)}")
If Media.Data.Post.Date.HasValue Then Information.StringAppendLine($"Posted: {Media.Data.Post.Date.Value.ToStringDate(ADateTime.Formats.BaseDateTime)}")
Dim info$ = $"[{Media.Data.Type}] - "
Dim h%
Dim s As Size
Post = Media.Data
Select Case Media.Data.Type
Case UserMedia.Types.Picture, UserMedia.Types.GIF
MyImage = New ImageRenderer(File)
s = MyImage.FitToWidthF(Width)
h = s.Height
MyPicture = New PictureBox With {
.SizeMode = PictureBoxSizeMode.Zoom,
.Image = MyImage,
.InitialImage = .Image,
.Dock = DockStyle.None,
.Anchor = AnchorStyles.Left + AnchorStyles.Top,
.Size = s,
.MinimumSize = s,
.MaximumSize = s,
.Tag = File,
.Margin = New Padding(0),
.Padding = New Padding(0),
.ContextMenuStrip = CONTEXT_DATA
}
TP_MAIN.Controls.Add(MyPicture, 0, 1)
BTT_CONTEXT_OPEN_MEDIA.Text &= " picture"
BTT_CONTEXT_DELETE.Text &= " picture"
Case UserMedia.Types.Video
MyVideo = New FeedVideo(File) With {.Tag = File, .Dock = DockStyle.Fill, .ContextMenuStrip = CONTEXT_DATA}
TP_MAIN.Controls.Add(MyVideo, 0, 1)
BTT_CONTEXT_OPEN_MEDIA.Text &= " video"
BTT_CONTEXT_DELETE.Text &= " video"
h = VideoHeight
Case Else : Throw New ArgumentNullException With {.HelpLink = 1}
End Select
If Not Media.User Is Nothing Then
With Media.User
UserKey = .Key
Information &= vbNewLine.StringDup(2)
If .IncludedInCollection Then Information.StringAppendLine($"User collection: { .CollectionName}")
Information.StringAppendLine($"User site: { .Site}")
Information.StringAppendLine($"User name: {IIf(Not .FriendlyName.IsEmptyString And Not .IncludedInCollection, .FriendlyName, .Name)}")
If .Site = API.Instagram.InstagramSite Then BTT_CONTEXT_OPEN_USER_POST.Visible = False
If .IncludedInCollection Then info &= $"[{ .CollectionName}]: "
info &= $"{ .Site} - {IIf(Not .FriendlyName.IsEmptyString And Not .IncludedInCollection, .FriendlyName, .Name)}"
End With
End If
If Settings.FeedAddSessionToCaption Then info = $"[{Media.Session}] {info}"
If Settings.FeedAddDateToCaption Then info &= $" ({Media.Date.ToStringDate(ADateTime.Formats.BaseDateTime)})"
LBL_INFO.Text = info
s = New Size(Width, h + TP_MAIN.RowStyles(0).Height + PaddingE.GetOf({TP_MAIN}).Vertical(2))
Size = s
MinimumSize = s
MaximumSize = s
If Not Handler Is Nothing Then AddHandler Me.MediaDeleted, Handler
Else
Throw New ArgumentNullException With {.HelpLink = 1}
End If
Catch aex As ArgumentNullException When aex.HelpLink = 1
HasError = True
Catch tex As Threading.ThreadStateException
HasError = True
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendInLog, ex, $"[DownloadObjects.FeedMedia({File})]")
HasError = True
End Try
End Sub
#End Region
#Region "Dispose"
Private Sub FeedImage_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
If Not MyImage Is Nothing Then MyImage.Dispose()
If Not MyPicture Is Nothing Then MyPicture.Dispose()
If Not MyVideo Is Nothing Then MyVideo.Dispose()
End Sub
#End Region
#Region "LBL"
Private Sub LBL_INFO_MouseClick(sender As Object, e As MouseEventArgs) Handles LBL_INFO.MouseClick
If e.Button = MouseButtons.Left Then ControlInvoke(CH_CHECKED, Sub() CH_CHECKED.Checked = Not CH_CHECKED.Checked)
End Sub
Private Sub LBL_INFO_DoubleClick(sender As Object, e As EventArgs) Handles LBL_INFO.DoubleClick
If Not UserKey.IsEmptyString Then
Dim u As IUserData = Settings.GetUser(UserKey)
If Not u Is Nothing Then u.OpenFolder()
End If
End Sub
#End Region
#Region "Picture / Video objects"
Private Sub MyPicture_DoubleClick(sender As Object, e As EventArgs) Handles MyPicture.DoubleClick
Try : Process.Start(File) : Catch : End Try
End Sub
#End Region
#Region "Context"
Private Sub BTT_CONTEXT_OPEN_MEDIA_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_OPEN_MEDIA.Click
File.Open(, EDP.None)
End Sub
Private Sub BTT_CONTEXT_OPEN_USER_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_OPEN_USER.Click
If Not UserKey.IsEmptyString Then
Dim u As IUserData = Settings.GetUser(UserKey)
If Not u Is Nothing Then u.OpenFolder()
End If
End Sub
Private Sub BTT_CONTEXT_OPEN_USER_URL_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_OPEN_USER_URL.Click
If Not UserKey.IsEmptyString Then
Dim u As IUserData = Settings.GetUser(UserKey)
If Not u Is Nothing Then u.OpenSite()
End If
End Sub
Private Sub BTT_CONTEXT_OPEN_USER_POST_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_OPEN_USER_POST.Click
Try
If Not UserKey.IsEmptyString And Not Post.Post.ID.IsEmptyString Then
Dim u As IUserData = Settings.GetUser(UserKey)
If Not u Is Nothing Then
Dim url$ = UserDataBase.GetPostUrl(u, Post)
If Not url.IsEmptyString Then
Try : Process.Start(url) : Catch : End Try
End If
End If
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, $"[FeedMedia.OpenPost({UserKey}, {Post.Post.ID})]")
End Try
End Sub
Private Sub BTT_CONTEXT_FIND_USER_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_FIND_USER.Click
If Not UserKey.IsEmptyString Then MainFrameObj.FocusUser(UserKey, True)
End Sub
Private Sub BTT_CONTEXT_INFO_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_INFO.Click
MsgBoxE({Information, "Post information"})
End Sub
Private Sub BTT_CONTEXT_DELETE_Click(sender As Object, e As EventArgs) Handles BTT_CONTEXT_DELETE.Click
DeleteFile(False)
End Sub
Friend Function DeleteFile(ByVal Silent As Boolean) As Boolean
Const msgTitle$ = "Deleting a file"
Try
If Silent OrElse MsgBoxE({$"Are you sure you want to delete the [{File.File}] file?{vbCr}{File}", msgTitle}, vbExclamation,,, {"Process", "Cancel"}) = 0 Then
If Not MyVideo Is Nothing Then MyVideo.Stop()
If File.Delete(SFO.File, Settings.DeleteMode, EDP.ThrowException) Then
If Not Silent Then RaiseEvent MediaDeleted(Me) : MsgBoxE({"File deleted", msgTitle})
LBL_INFO.Height = 0
Height = 0
Return True
End If
End If
Return False
Catch ex As Exception
Dim e As New ErrorsDescriber(EDP.LogMessageValue) With {.ShowMainMsg = Not Silent, .ShowExMsg = .ShowMainMsg}
Return ErrorsDescriber.Execute(e, ex, $"[FeedMedia.DeleteFile({File})]", False)
End Try
End Function
#End Region
End Class
End Namespace

182
SCrawler/Download/FeedVideo.Designer.vb generated Normal file
View File

@@ -0,0 +1,182 @@
' Copyright (C) 2022 Andy
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Namespace DownloadObjects
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Public Class FeedVideo : Inherits System.Windows.Forms.UserControl
<System.Diagnostics.DebuggerNonUserCode()>
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
Private components As System.ComponentModel.IContainer
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
Dim TP_BUTTONS As System.Windows.Forms.TableLayoutPanel
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(FeedVideo))
Me.MyVideo = New LibVLCSharp.WinForms.VideoView()
Me.TR_POSITION = New System.Windows.Forms.TrackBar()
Me.TR_VOLUME = New System.Windows.Forms.TrackBar()
Me.LBL_TIME = New System.Windows.Forms.Label()
Me.BTT_PLAY = New System.Windows.Forms.Button()
Me.BTT_PAUSE = New System.Windows.Forms.Button()
Me.BTT_STOP = New System.Windows.Forms.Button()
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
TP_BUTTONS = New System.Windows.Forms.TableLayoutPanel()
TP_MAIN.SuspendLayout()
CType(Me.MyVideo, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TR_POSITION, System.ComponentModel.ISupportInitialize).BeginInit()
TP_BUTTONS.SuspendLayout()
CType(Me.TR_VOLUME, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'TP_MAIN
'
TP_MAIN.ColumnCount = 1
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MAIN.Controls.Add(Me.MyVideo, 0, 0)
TP_MAIN.Controls.Add(Me.TR_POSITION, 0, 1)
TP_MAIN.Controls.Add(TP_BUTTONS, 0, 2)
TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
TP_MAIN.Location = New System.Drawing.Point(0, 0)
TP_MAIN.Margin = New System.Windows.Forms.Padding(0)
TP_MAIN.Name = "TP_MAIN"
TP_MAIN.RowCount = 3
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_MAIN.Size = New System.Drawing.Size(180, 160)
TP_MAIN.TabIndex = 0
'
'MyVideo
'
Me.MyVideo.BackColor = System.Drawing.Color.Black
Me.MyVideo.Dock = System.Windows.Forms.DockStyle.Fill
Me.MyVideo.Location = New System.Drawing.Point(1, 1)
Me.MyVideo.Margin = New System.Windows.Forms.Padding(1)
Me.MyVideo.MediaPlayer = Nothing
Me.MyVideo.Name = "MyVideo"
Me.MyVideo.Size = New System.Drawing.Size(178, 105)
Me.MyVideo.TabIndex = 0
'
'TR_POSITION
'
Me.TR_POSITION.Dock = System.Windows.Forms.DockStyle.Fill
Me.TR_POSITION.Location = New System.Drawing.Point(3, 110)
Me.TR_POSITION.Name = "TR_POSITION"
Me.TR_POSITION.Size = New System.Drawing.Size(174, 19)
Me.TR_POSITION.TabIndex = 1
'
'TP_BUTTONS
'
TP_BUTTONS.ColumnCount = 5
TP_BUTTONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_BUTTONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_BUTTONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_BUTTONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_BUTTONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 100.0!))
TP_BUTTONS.Controls.Add(Me.BTT_PLAY, 0, 0)
TP_BUTTONS.Controls.Add(Me.BTT_PAUSE, 1, 0)
TP_BUTTONS.Controls.Add(Me.BTT_STOP, 2, 0)
TP_BUTTONS.Controls.Add(Me.TR_VOLUME, 4, 0)
TP_BUTTONS.Controls.Add(Me.LBL_TIME, 3, 0)
TP_BUTTONS.Dock = System.Windows.Forms.DockStyle.Fill
TP_BUTTONS.Location = New System.Drawing.Point(1, 133)
TP_BUTTONS.Margin = New System.Windows.Forms.Padding(1)
TP_BUTTONS.Name = "TP_BUTTONS"
TP_BUTTONS.RowCount = 1
TP_BUTTONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_BUTTONS.Size = New System.Drawing.Size(178, 26)
TP_BUTTONS.TabIndex = 2
'
'TR_VOLUME
'
Me.TR_VOLUME.Dock = System.Windows.Forms.DockStyle.Fill
Me.TR_VOLUME.Location = New System.Drawing.Point(81, 3)
Me.TR_VOLUME.Name = "TR_VOLUME"
Me.TR_VOLUME.Size = New System.Drawing.Size(94, 20)
Me.TR_VOLUME.TabIndex = 3
'
'LBL_TIME
'
Me.LBL_TIME.AutoSize = True
Me.LBL_TIME.Dock = System.Windows.Forms.DockStyle.Fill
Me.LBL_TIME.Location = New System.Drawing.Point(78, 0)
Me.LBL_TIME.Name = "LBL_TIME"
Me.LBL_TIME.Size = New System.Drawing.Size(1, 26)
Me.LBL_TIME.TabIndex = 4
Me.LBL_TIME.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
'
'BTT_PLAY
'
Me.BTT_PLAY.BackgroundImage = Global.SCrawler.My.Resources.Resources.StartPic_01_Green_16
Me.BTT_PLAY.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom
Me.BTT_PLAY.Dock = System.Windows.Forms.DockStyle.Fill
Me.BTT_PLAY.Location = New System.Drawing.Point(1, 1)
Me.BTT_PLAY.Margin = New System.Windows.Forms.Padding(1)
Me.BTT_PLAY.Name = "BTT_PLAY"
Me.BTT_PLAY.Size = New System.Drawing.Size(23, 24)
Me.BTT_PLAY.TabIndex = 0
Me.BTT_PLAY.UseVisualStyleBackColor = True
'
'BTT_PAUSE
'
Me.BTT_PAUSE.BackgroundImage = Global.SCrawler.My.Resources.Resources.Pause_Blue_16
Me.BTT_PAUSE.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom
Me.BTT_PAUSE.Dock = System.Windows.Forms.DockStyle.Fill
Me.BTT_PAUSE.Location = New System.Drawing.Point(26, 1)
Me.BTT_PAUSE.Margin = New System.Windows.Forms.Padding(1)
Me.BTT_PAUSE.Name = "BTT_PAUSE"
Me.BTT_PAUSE.Size = New System.Drawing.Size(23, 24)
Me.BTT_PAUSE.TabIndex = 1
Me.BTT_PAUSE.UseVisualStyleBackColor = True
'
'BTT_STOP
'
Me.BTT_STOP.BackgroundImage = CType(resources.GetObject("BTT_STOP.BackgroundImage"), System.Drawing.Image)
Me.BTT_STOP.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom
Me.BTT_STOP.Dock = System.Windows.Forms.DockStyle.Fill
Me.BTT_STOP.Location = New System.Drawing.Point(51, 1)
Me.BTT_STOP.Margin = New System.Windows.Forms.Padding(1)
Me.BTT_STOP.Name = "BTT_STOP"
Me.BTT_STOP.Size = New System.Drawing.Size(23, 24)
Me.BTT_STOP.TabIndex = 2
Me.BTT_STOP.UseVisualStyleBackColor = True
'
'FeedVideo
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.Controls.Add(TP_MAIN)
Me.Name = "FeedVideo"
Me.Size = New System.Drawing.Size(180, 160)
TP_MAIN.ResumeLayout(False)
TP_MAIN.PerformLayout()
CType(Me.MyVideo, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TR_POSITION, System.ComponentModel.ISupportInitialize).EndInit()
TP_BUTTONS.ResumeLayout(False)
TP_BUTTONS.PerformLayout()
CType(Me.TR_VOLUME, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
End Sub
Private WithEvents MyVideo As LibVLCSharp.WinForms.VideoView
Private WithEvents TR_POSITION As TrackBar
Private WithEvents BTT_PLAY As Button
Private WithEvents BTT_PAUSE As Button
Private WithEvents BTT_STOP As Button
Private WithEvents TR_VOLUME As TrackBar
Private WithEvents LBL_TIME As Label
End Class
End Namespace

View File

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

View File

@@ -0,0 +1,114 @@
' Copyright (C) 2022 Andy
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports LibVLCSharp
Imports System.ComponentModel
Imports PersonalUtilities.Tools
Imports PersonalUtilities.Tools.WEB
Imports VLCState = LibVLCSharp.Shared.VLCState
Namespace DownloadObjects
<ToolboxItem(False), DesignTimeVisible(False)>
Public Class FeedVideo
Private WithEvents MediaPlayer As [Shared].MediaPlayer
Private ReadOnly TimeChange As Action = Sub()
Dim v# = DivideWithZeroChecking(MediaPlayer.Time, MediaPlayer.Length) * 10
If v > 10 Then TR_POSITION.Value = 10 Else TR_POSITION.Value = v
End Sub
Private ReadOnly TimeChangeLabel As Action = Sub()
If MediaPlayer.Time >= 0 Then
Dim t As TimeSpan = TimeSpan.FromMilliseconds(MediaPlayer.Time)
If Not VideoLength.HasValue Then
VideoLength = TimeSpan.FromMilliseconds(MediaPlayer.Length)
VideoLengthStr = VideoLength.Value.ToStringTime(FeedVideoLengthProvider)
End If
LBL_TIME.Text = $"{t.ToStringTime(FeedVideoLengthProvider)}/{VideoLengthStr}"
End If
End Sub
Private ReadOnly MyImage As ImageRenderer
Private VideoLength As TimeSpan?
Private VideoLengthStr As String
Public Sub New()
InitializeComponent()
End Sub
Friend Sub New(ByVal File As SFile)
InitializeComponent()
Dim debugLogs As Boolean = False
#If DEBUG Then
debugLogs = True
#End If
MediaPlayer = New [Shared].MediaPlayer(New [Shared].Media(New [Shared].LibVLC(enableDebugLogs:=debugLogs), New Uri(File.ToString)))
MyVideo.MediaPlayer = MediaPlayer
TR_VOLUME.Value = MediaPlayer.Volume / 10
If Settings.UseM3U8 Then
Dim f As SFile = $"{Settings.CachePath.PathWithSeparator}FeedSnapshots\{File.GetHashCode}.png"
If Not f.Exists Then f = FFMPEG.TakeSnapshot(File, f, Settings.FfmpegFile, TimeSpan.FromSeconds(1))
If f.Exists Then
MyImage = New ImageRenderer(f, EDP.None)
If Not MyImage.HasError Then
MyVideo.BackgroundImage = MyImage
MyVideo.BackgroundImageLayout = ImageLayout.Zoom
End If
End If
End If
UpdateButtons()
End Sub
Private Sub FeedVideo_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
If Not MediaPlayer Is Nothing Then MediaPlayer.Dispose()
If Not MyImage Is Nothing Then MyImage.Dispose()
End Sub
Private Sub BTT_PLAY_Click(sender As Object, e As EventArgs) Handles BTT_PLAY.Click
Try
Select Case MediaPlayer.State
Case VLCState.NothingSpecial, VLCState.Stopped, VLCState.Paused : MediaPlayer.Play()
Case VLCState.Ended : MediaPlayer.Stop() : MediaPlayer.Play()
End Select
Catch
Finally
UpdateButtons()
End Try
End Sub
Private Sub BTT_PAUSE_Click(sender As Object, e As EventArgs) Handles BTT_PAUSE.Click
Try : MediaPlayer.Pause() : Catch : End Try
UpdateButtons()
End Sub
Friend Sub [Stop]() Handles BTT_STOP.Click
Try : MediaPlayer.Stop() : Catch : End Try
UpdateButtons()
End Sub
Private Sub MediaPlayer_TimeChanged(sender As Object, e As [Shared].MediaPlayerTimeChangedEventArgs) Handles MediaPlayer.TimeChanged
If TR_POSITION.InvokeRequired Then TR_POSITION.Invoke(TimeChange) Else TimeChange.Invoke
If LBL_TIME.InvokeRequired Then LBL_TIME.Invoke(TimeChangeLabel) Else TimeChangeLabel.Invoke
End Sub
Private Sub TR_POSITION_MouseUp(sender As Object, e As MouseEventArgs) Handles TR_POSITION.MouseUp
Try : MediaPlayer.Time = (MediaPlayer.Length / 100) * (TR_POSITION.Value * 10) : Catch : End Try
End Sub
Private Sub TR_VOLUME_MouseUp(sender As Object, e As MouseEventArgs) Handles TR_VOLUME.MouseUp
Try : MediaPlayer.Volume = TR_VOLUME.Value * 10 : Catch : End Try
End Sub
Private Sub MediaPlayer_Stopped(sender As Object, e As EventArgs) Handles MediaPlayer.Stopped
Dim a As Action = Sub() TR_POSITION.Value = TR_POSITION.Maximum
If TR_POSITION.InvokeRequired Then TR_POSITION.Invoke(a) Else a.Invoke
UpdateButtons()
End Sub
Private Sub UpdateButtons() Handles MediaPlayer.Playing, MediaPlayer.Paused, MediaPlayer.Opening
Try
Dim _play As Boolean = False, _pause As Boolean = False, _stop As Boolean = False
Select Case MediaPlayer.State
Case VLCState.NothingSpecial, VLCState.Stopped : _play = True
Case VLCState.Paused : _play = True : _stop = True
Case VLCState.Ended : _play = True
Case VLCState.Playing : _pause = True : _stop = True
End Select
ControlInvoke(BTT_PLAY, Sub() BTT_PLAY.Enabled = _play)
ControlInvoke(BTT_PAUSE, Sub() BTT_PAUSE.Enabled = _pause)
ControlInvoke(BTT_STOP, Sub() BTT_STOP.Enabled = _stop)
Catch
End Try
End Sub
End Class
End Namespace

View File

@@ -48,16 +48,16 @@ Namespace DownloadObjects.Groups
}
BTT_DELETE = New ToolStripMenuItem With {
.Image = PersonalUtilities.My.Resources.DeletePic_02_Red_24,
.BackColor = ColorBttDeleteBack,
.ForeColor = ColorBttDeleteFore,
.BackColor = MyColor.DeleteBack,
.ForeColor = MyColor.DeleteFore,
.Text = "Delete",
.ToolTipText = String.Empty,
.AutoToolTip = False
}
BTT_EDIT = New ToolStripMenuItem With {
.Image = PersonalUtilities.My.Resources.PencilPic_01_48,
.BackColor = ColorBttEditBack,
.ForeColor = ColorBttEditFore,
.BackColor = MyColor.EditBack,
.ForeColor = MyColor.EditFore,
.Text = "Edit",
.ToolTipText = String.Empty,
.AutoToolTip = False
@@ -87,7 +87,7 @@ Namespace DownloadObjects.Groups
If Not e.Value.IsEmptyString Then Labels.ListAddList(e.Value.Split("|"), LAP.NotContainsOnly)
End Sub
Public Overrides Function ToString() As String
Return $"{IIf(Index >= 0 And Index <= 8, $"#{Index + 1}: ", String.Empty)}{Name}"
Return $"{IIf(Index.ValueBetween(0, 8), $"#{Index + 1}: ", String.Empty)}{Name}"
End Function
Private _ControlSent As Boolean = False
Friend Function GetControl() As ToolStripMenuItem

View File

@@ -44,10 +44,7 @@ Namespace DownloadObjects.Groups
End Property
Friend Sub Update()
If Count > 0 Then
Using x As New XmlFile With {.Name = "Groups", .AllowSameNames = True}
x.AddRange(GroupsList)
x.Save(GroupFile)
End Using
Using x As New XmlFile With {.Name = "Groups", .AllowSameNames = True} : x.AddRange(GroupsList) : x.Save(GroupFile) : End Using
Else
GroupFile.Delete()
End If

View File

@@ -100,7 +100,7 @@ Namespace DownloadObjects.Groups
Controls.Add(TP_2, 0, 3)
Controls.Add(TXT_LABELS, 0, 4)
End Sub
Private Sub TXT_LABELS_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_LABELS.ActionOnButtonClick
Private Sub TXT_LABELS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles TXT_LABELS.ActionOnButtonClick
Select Case Sender.DefaultButton
Case ADB.Edit
Using f As New LabelsForm(Labels)

View File

@@ -7,15 +7,14 @@
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Toolbars
Namespace DownloadObjects.Groups
Friend Class GroupEditorForm : Implements IOkCancelToolbar
Private ReadOnly MyDefs As DefaultFormOptions
Friend Class GroupEditorForm
Private WithEvents MyDefs As DefaultFormOptions
Friend Property MyGroup As DownloadGroup
Friend Sub New(ByRef g As DownloadGroup)
InitializeComponent()
MyGroup = g
MyDefs = New DefaultFormOptions
MyDefs = New DefaultFormOptions(Me, Settings.Design)
End Sub
Friend Class NameChecker : Implements IFieldsCheckerProvider
Private Property ErrorMessage As String Implements IFieldsCheckerProvider.ErrorMessage
@@ -48,7 +47,7 @@ Namespace DownloadObjects.Groups
End Class
Private Sub GroupEditorForm_Load(sender As Object, e As EventArgs) Handles Me.Load
With MyDefs
.MyViewInitialize(Me, Settings.Design, True)
.MyViewInitialize(True)
.AddOkCancelToolbar()
If Not MyGroup Is Nothing Then
With MyGroup
@@ -59,13 +58,13 @@ Namespace DownloadObjects.Groups
Text = "New Group"
End If
.MyFieldsChecker = New FieldsChecker
DirectCast(.MyFieldsChecker, FieldsChecker).AddControl(Of String)(DEFS_GROUP.TXT_NAME, DEFS_GROUP.TXT_NAME.CaptionText,,
.MyFieldsCheckerE.AddControl(Of String)(DEFS_GROUP.TXT_NAME, DEFS_GROUP.TXT_NAME.CaptionText,,
New NameChecker(If(MyGroup?.Name, String.Empty), Settings.Groups, "Group"))
.MyFieldsChecker.EndLoaderOperations()
.EndLoaderOperations()
End With
End Sub
Private Sub OK() Implements IOkCancelToolbar.OK
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
If MyDefs.MyFieldsChecker.AllParamsOK Then
If MyGroup Is Nothing Then MyGroup = New DownloadGroup
With MyGroup
@@ -75,8 +74,5 @@ Namespace DownloadObjects.Groups
MyDefs.CloseForm()
End If
End Sub
Private Sub Cancel() Implements IOkCancelToolbar.Cancel
MyDefs.CloseForm(DialogResult.Cancel)
End Sub
End Class
End Namespace

View File

@@ -0,0 +1,175 @@
' Copyright (C) 2022 Andy
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Namespace DownloadObjects
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Friend Class MissingPostsForm : Inherits System.Windows.Forms.Form
<System.Diagnostics.DebuggerNonUserCode()>
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
Private components As System.ComponentModel.IContainer
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container()
Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
Dim CONTEXT_SEP_1 As System.Windows.Forms.ToolStripSeparator
Dim CONTEXT_SEP_2 As System.Windows.Forms.ToolStripSeparator
Dim CONTEXT_SEP_3 As System.Windows.Forms.ToolStripSeparator
Me.LIST_DATA = New System.Windows.Forms.ListView()
Me.CONTEXT_OPERATIONS = New System.Windows.Forms.ContextMenuStrip(Me.components)
Me.BTT_DOWN = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_OPEN_POST = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_OPEN_USER = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FIND_USER = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_DELETE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CONTEXT_SHOW_POST_INFO = New System.Windows.Forms.ToolStripMenuItem()
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
CONTEXT_SEP_1 = New System.Windows.Forms.ToolStripSeparator()
CONTEXT_SEP_2 = New System.Windows.Forms.ToolStripSeparator()
CONTEXT_SEP_3 = New System.Windows.Forms.ToolStripSeparator()
CONTAINER_MAIN.ContentPanel.SuspendLayout()
CONTAINER_MAIN.SuspendLayout()
Me.CONTEXT_OPERATIONS.SuspendLayout()
Me.SuspendLayout()
'
'CONTAINER_MAIN
'
CONTAINER_MAIN.BottomToolStripPanelVisible = False
'
'CONTAINER_MAIN.ContentPanel
'
CONTAINER_MAIN.ContentPanel.Controls.Add(Me.LIST_DATA)
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(284, 236)
CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
CONTAINER_MAIN.LeftToolStripPanelVisible = False
CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
CONTAINER_MAIN.Name = "CONTAINER_MAIN"
CONTAINER_MAIN.RightToolStripPanelVisible = False
CONTAINER_MAIN.Size = New System.Drawing.Size(284, 261)
CONTAINER_MAIN.TabIndex = 0
'
'LIST_DATA
'
Me.LIST_DATA.Activation = System.Windows.Forms.ItemActivation.OneClick
Me.LIST_DATA.ContextMenuStrip = Me.CONTEXT_OPERATIONS
Me.LIST_DATA.Dock = System.Windows.Forms.DockStyle.Fill
Me.LIST_DATA.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None
Me.LIST_DATA.HideSelection = False
Me.LIST_DATA.Location = New System.Drawing.Point(0, 0)
Me.LIST_DATA.Name = "LIST_DATA"
Me.LIST_DATA.Size = New System.Drawing.Size(284, 236)
Me.LIST_DATA.TabIndex = 0
Me.LIST_DATA.TileSize = New System.Drawing.Size(168, 15)
Me.LIST_DATA.UseCompatibleStateImageBehavior = False
Me.LIST_DATA.View = System.Windows.Forms.View.Tile
'
'CONTEXT_SEP_1
'
CONTEXT_SEP_1.Name = "CONTEXT_SEP_1"
CONTEXT_SEP_1.Size = New System.Drawing.Size(178, 6)
'
'CONTEXT_SEP_2
'
CONTEXT_SEP_2.Name = "CONTEXT_SEP_2"
CONTEXT_SEP_2.Size = New System.Drawing.Size(178, 6)
'
'CONTEXT_SEP_3
'
CONTEXT_SEP_3.Name = "CONTEXT_SEP_3"
CONTEXT_SEP_3.Size = New System.Drawing.Size(178, 6)
'
'CONTEXT_OPERATIONS
'
Me.CONTEXT_OPERATIONS.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_DOWN, CONTEXT_SEP_1, Me.BTT_OPEN_POST, Me.BTT_OPEN_USER, Me.BTT_CONTEXT_SHOW_POST_INFO, CONTEXT_SEP_2, Me.BTT_FIND_USER, CONTEXT_SEP_3, Me.BTT_DELETE})
Me.CONTEXT_OPERATIONS.Name = "CONTEXT_OPERATIONS"
Me.CONTEXT_OPERATIONS.Size = New System.Drawing.Size(181, 176)
'
'BTT_DOWN
'
Me.BTT_DOWN.AutoToolTip = True
Me.BTT_DOWN.Image = Global.SCrawler.My.Resources.Resources.StartPic_01_Green_16
Me.BTT_DOWN.Name = "BTT_DOWN"
Me.BTT_DOWN.Size = New System.Drawing.Size(181, 22)
Me.BTT_DOWN.Text = "Download"
Me.BTT_DOWN.ToolTipText = "Try downloading the selected posts again"
'
'BTT_OPEN_POST
'
Me.BTT_OPEN_POST.Image = Global.SCrawler.My.Resources.Resources.GlobeBlue_32
Me.BTT_OPEN_POST.Name = "BTT_OPEN_POST"
Me.BTT_OPEN_POST.Size = New System.Drawing.Size(181, 22)
Me.BTT_OPEN_POST.Text = "Open post"
'
'BTT_OPEN_USER
'
Me.BTT_OPEN_USER.Image = Global.SCrawler.My.Resources.Resources.Folder_32
Me.BTT_OPEN_USER.Name = "BTT_OPEN_USER"
Me.BTT_OPEN_USER.Size = New System.Drawing.Size(181, 22)
Me.BTT_OPEN_USER.Text = "Open user folder"
'
'BTT_FIND_USER
'
Me.BTT_FIND_USER.Image = Global.SCrawler.My.Resources.Resources.InfoPic_32
Me.BTT_FIND_USER.Name = "BTT_FIND_USER"
Me.BTT_FIND_USER.Size = New System.Drawing.Size(181, 22)
Me.BTT_FIND_USER.Text = "Find user"
'
'BTT_DELETE
'
Me.BTT_DELETE.AutoToolTip = True
Me.BTT_DELETE.Image = Global.SCrawler.My.Resources.Resources.Delete
Me.BTT_DELETE.Name = "BTT_DELETE"
Me.BTT_DELETE.Size = New System.Drawing.Size(181, 22)
Me.BTT_DELETE.Text = "Delete post"
Me.BTT_DELETE.ToolTipText = "Remove selected posts from user data"
'
'BTT_CONTEXT_SHOW_POST_INFO
'
Me.BTT_CONTEXT_SHOW_POST_INFO.AutoToolTip = True
Me.BTT_CONTEXT_SHOW_POST_INFO.Image = Global.SCrawler.My.Resources.Resources.InfoPic_32
Me.BTT_CONTEXT_SHOW_POST_INFO.Name = "BTT_CONTEXT_SHOW_POST_INFO"
Me.BTT_CONTEXT_SHOW_POST_INFO.Size = New System.Drawing.Size(180, 22)
Me.BTT_CONTEXT_SHOW_POST_INFO.Text = "Show post info"
Me.BTT_CONTEXT_SHOW_POST_INFO.ToolTipText = "Show information about the missing post"
'
'MissingPostsForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(284, 261)
Me.Controls.Add(CONTAINER_MAIN)
Me.KeyPreview = True
Me.MinimumSize = New System.Drawing.Size(300, 300)
Me.Name = "MissingPostsForm"
Me.ShowIcon = False
Me.Text = "Missing posts"
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
CONTAINER_MAIN.ResumeLayout(False)
CONTAINER_MAIN.PerformLayout()
Me.CONTEXT_OPERATIONS.ResumeLayout(False)
Me.ResumeLayout(False)
End Sub
Private WithEvents LIST_DATA As ListView
Private WithEvents CONTEXT_OPERATIONS As ContextMenuStrip
Private WithEvents BTT_DOWN As ToolStripMenuItem
Private WithEvents BTT_OPEN_POST As ToolStripMenuItem
Private WithEvents BTT_OPEN_USER As ToolStripMenuItem
Private WithEvents BTT_FIND_USER As ToolStripMenuItem
Private WithEvents BTT_DELETE As ToolStripMenuItem
Private WithEvents BTT_CONTEXT_SHOW_POST_INFO As ToolStripMenuItem
End Class
End Namespace

View File

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

View File

@@ -0,0 +1,296 @@
' Copyright (C) 2022 Andy
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports System.ComponentModel
Imports PersonalUtilities.Functions.Messaging
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Toolbars
Imports SCrawler.API.Base
Namespace DownloadObjects
Friend Class MissingPostsForm
#Region "Declarations"
Private WithEvents MyDefs As DefaultFormOptions
Private ReadOnly MUsers As List(Of IUserData)
Private WithEvents BTT_DOWN_ALL As ToolStripButton
Private WithEvents BTT_INFO As ToolStripButton
#End Region
#Region "Initializer"
Friend Sub New()
InitializeComponent()
MUsers = New List(Of IUserData)
MyDefs = New DefaultFormOptions(Me, Settings.Design)
BTT_DOWN_ALL = New ToolStripButton With {
.Text = "Download ALL",
.ToolTipText = String.Empty,
.AutoToolTip = False,
.Image = My.Resources.StartPic_01_Green_16,
.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText
}
BTT_INFO = New ToolStripButton With {
.Text = "Info",
.ToolTipText = "Show information about the missing post (F1)",
.AutoToolTip = True,
.Image = My.Resources.InfoPic_32,
.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText
}
End Sub
#End Region
#Region "Form handlers"
Private Sub MissingPostsForm_Load(sender As Object, e As EventArgs) Handles Me.Load
With MyDefs
.MyViewInitialize()
.AddEditToolbarPlus({EditToolbar.ControlItem.Separator, BTT_DOWN_ALL, BTT_INFO})
.EndLoaderOperations(False)
End With
RefillList()
End Sub
Private Sub MissingPostsForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
e.Cancel = True
Hide()
End Sub
Private Sub MissingPostsForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
MUsers.Clear()
End Sub
Private Sub MissingPostsForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If e.KeyCode = Keys.F1 Then ShowPostInformation() : e.Handled = True
End Sub
#End Region
#Region "RefillList"
Private Overloads Sub RefillList() Handles MyDefs.ButtonUpdateClick
RefillList(True)
End Sub
Friend Overloads Sub RefillList(ByVal User As IUserData)
If MUsers.Count = 0 OrElse Not MUsers.Contains(User) Then MUsers.Add(User) : RefillList(False)
End Sub
Friend Overloads Sub RefillList(ByVal Reload As Boolean)
Try
If Reload Then MUsers.Clear()
LIST_DATA.Items.Clear()
LIST_DATA.Groups.Clear()
If Reload And Settings.Users.Count > 0 Then
MUsers.ListAddList(Settings.Users.SelectMany(Function(ByVal user As IUserData) As IEnumerable(Of IUserData)
DirectCast(user, UserDataBase).LoadContentInformation()
If user.IsCollection Then
With DirectCast(user, API.UserDataBind)
If .Count > 0 Then Return .Where(Function(u) DirectCast(u, UserDataBase).ContentMissingExists)
End With
ElseIf DirectCast(user, UserDataBase).ContentMissingExists Then
Return {user}
End If
Return New IUserData() {}
End Function), LAP.IgnoreICopier)
End If
If MUsers.Count > 0 Then
Dim gName$ = String.Empty
Dim g As ListViewGroup = Nothing
Dim i% = -1
Dim cm As List(Of UserMedia)
For Each uu As UserDataBase In MUsers
i += 1
cm = uu.ContentMissing
If cm.Count > 0 Then
gName = String.Empty
If uu.IncludedInCollection Then gName = $"{uu.CollectionName} - "
gName &= $"{uu.User.Name} ({uu.Site})"
ControlInvoke(LIST_DATA, Sub()
LIST_DATA.Groups.Add(New ListViewGroup(gName) With {.Tag = uu.LVIKey})
g = LIST_DATA.Groups(LIST_DATA.Groups.Count - 1)
End Sub)
For i% = 0 To cm.Count - 1 : ControlInvoke(LIST_DATA, Sub() LIST_DATA.Items.Add(New ListViewItem(cm(i).Post.ID, g))) : Next
End If
Next
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendInLog, ex, "[DownloadObjects.MissingPostsForm.RefillList]")
End Try
End Sub
#End Region
#Region "Post actions"
Private Sub BTT_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_DOWN.Click
'Try
' If LIST_DATA.SelectedItems.Count > 0 Then
' Dim users As List(Of IUserData) = LIST_DATA.SelectedItems.ToObjectsList.ListCast(Of ListViewItem)().
' Select(Function(d) Settings.GetUser(CStr(d.Group.Tag))).ListWithRemove(Function(d) d Is Nothing)
' If users.ListExists Then
' If MsgBoxE({"The following users will be added to the download queue:" & vbCr & vbCr &
' users.Select(Function(u) u.ToString).ListToString(vbNewLine), "Download users"},,,, {"Process", "Cancel"}) = 0 Then
' users.ForEach(Sub(u) u.DownloadMissingOnly = True)
' Downloader.AddRange(users)
' users.Clear()
' End If
' End If
' Else
' MsgBoxE("No selected posts")
' End If
'Catch ex As Exception
' ErrorsDescriber.Execute(EDP.SendInLog, ex, "[DownloadObjects.MissingPostsForm.Download]")
'End Try
End Sub
Private Sub BTT_OPEN_POST_Click(sender As Object, e As EventArgs) Handles BTT_OPEN_POST.Click
Try
If LIST_DATA.SelectedItems.Count > 0 Then
If LIST_DATA.SelectedItems.Count = 1 OrElse
MsgBoxE({$"Are you sure you want to open {LIST_DATA.SelectedItems.Count} posts?", "Open multiple posts"}, vbExclamation + vbYesNo) = vbYes Then
Dim data As List(Of ListViewItem) = LIST_DATA.SelectedItems.ToObjectsList.ListCast(Of ListViewItem)
If data.ListExists Then
Dim uKey$, url$
Dim u As IUserData = Nothing
Dim i%
Dim cm As List(Of UserMedia)
For Each _d In data
uKey = _d.Group.Tag
If u Is Nothing OrElse Not u.Key = uKey Then u = Settings.GetUser(uKey)
If Not u Is Nothing Then
i = -1
With DirectCast(u, UserDataBase)
cm = .ContentMissing
If cm.Count > 0 Then i = cm.FindIndex(Function(c) c.Post.ID = _d.Text)
If i >= 0 Then
url = UserDataBase.GetPostUrl(u, cm(i))
If Not url.IsEmptyString Then
Try : Process.Start(url) : Catch : End Try
End If
End If
End With
End If
Next
End If
End If
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendInLog, ex, "[DownloadObjects.MissingPostsForm.OpenPost]")
End Try
End Sub
Private Sub BTT_OPEN_USER_Click(sender As Object, e As EventArgs) Handles BTT_OPEN_USER.Click
Try
If LIST_DATA.SelectedItems.Count > 0 Then
Dim users As List(Of IUserData) = LIST_DATA.SelectedItems.ToObjectsList.ListCast(Of ListViewItem)().
Select(Function(d) Settings.GetUser(CStr(d.Group.Tag))).ListWithRemove(Function(d) d Is Nothing)
If users.ListExists Then users.ForEach(Sub(u) u.OpenFolder())
Else
MsgBoxE("No selected posts")
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendInLog, ex, $"[DownloadObjects.MissingPostsForm.OpenUser]")
End Try
End Sub
Private Sub ShowPostInformation() Handles BTT_INFO.Click, BTT_CONTEXT_SHOW_POST_INFO.Click, LIST_DATA.DoubleClick
Try
If LIST_DATA.SelectedItems.Count > 0 Then
Dim data As ListViewItem = LIST_DATA.SelectedItems.ToObjectsList.ListCast(Of ListViewItem)().First
Dim uKey$, url$
Dim u As IUserData = Nothing
Dim i%
Dim cm As List(Of UserMedia)
Dim m As UserMedia
uKey = data.Group.Tag
If Not uKey.IsEmptyString Then u = Settings.GetUser(uKey)
If Not u Is Nothing Then
i = -1
With DirectCast(u, UserDataBase)
cm = .ContentMissing
If cm.Count > 0 Then i = cm.FindIndex(Function(c) c.Post.ID = data.Text)
If i >= 0 Then
m = cm(i)
url = UserDataBase.GetPostUrl(u, m)
Dim msg As New MMessage("", "Post information") With {.Editable = True}
Dim b As New List(Of MsgBoxButton)
If Not url.IsEmptyString Then b.Add(New MsgBoxButton("Open") With {.IsDialogResultButton = False,
.ToolTip = "Open post in browser",
.KeyCode = Keys.F1,
.CallBack = Sub(result, message, button)
Try : Process.Start(url) : Catch : End Try
End Sub})
b.Add(New MsgBoxButton("OK"))
With msg
.Buttons = b
.DefaultButton = If(b.Count = 2, 1, 0)
.CancelButton = .DefaultButton
.Text = $"Type: {m.Type}"
.Text.StringAppendLine($"Address: {url}")
If m.Post.Date.HasValue Then .Text.StringAppendLine($"Date: {m.Post.Date.Value.ToStringDate(ADateTime.Formats.BaseDateTime)}")
.Text &= vbNewLine.StringDup(2)
If u.IncludedInCollection Then .Text.StringAppendLine($"User collection: {u.CollectionName}")
.Text.StringAppendLine($"User site: {u.Site}")
.Text.StringAppendLine($"User name: {IIf(Not u.FriendlyName.IsEmptyString And Not u.IncludedInCollection, u.FriendlyName, u.Name)}")
End With
MsgBoxE(msg)
b.Clear()
cm.Clear()
End If
End With
End If
Else
MsgBoxE("No selected posts")
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendInLog, ex, "[DownloadObjects.MissingPostsForm.ShowPostInformation]")
End Try
End Sub
Private Sub BTT_FIND_USER_Click(sender As Object, e As EventArgs) Handles BTT_FIND_USER.Click
Try
If LIST_DATA.SelectedItems.Count > 0 Then
Dim user As IUserData = LIST_DATA.SelectedItems.ToObjectsList.ListCast(Of ListViewItem)().
Select(Function(d) Settings.GetUser(CStr(d.Group.Tag))).ListWithRemove(Function(d) d Is Nothing).DefaultIfEmpty(Nothing).First
If Not user Is Nothing Then MainFrameObj.FocusUser(user.Key, True)
Else
MsgBoxE("No selected posts")
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendInLog, ex, $"[DownloadObjects.MissingPostsForm.FindUser]")
End Try
End Sub
Private Sub DeletePost() Handles MyDefs.ButtonDeleteClickE, BTT_DELETE.Click
Const MsgTitle$ = "Remove missing posts"
Dim UsersToUpdate As New List(Of UserDataBase)
Try
Dim data As List(Of ListViewItem) = LIST_DATA.SelectedItems.ToObjectsList.ListCast(Of ListViewItem)
If data.ListExists Then
Dim lp As New ListAddParams(LAP.NotContainsOnly)
Dim usersCount% = ListAddList(Nothing, data.Select(Function(d) d.Group.Name), LAP.NotContainsOnly).ListIfNothing.Count
If MsgBoxE({"Are you sure you want to delete the selected missing posts?" & vbCr &
$"Number of affected users: {usersCount}." & vbCr &
$"Number of posts to be deleted: {data.Count}.", MsgTitle}, vbExclamation,,, {"Process", "Cancel"}) = 0 Then
Dim uKey$
Dim u As UserDataBase = Nothing
Dim cm As List(Of UserMedia)
Dim i%
For Each _d In data
uKey = _d.Group.Tag
If u Is Nothing OrElse Not u.LVIKey = uKey Then u = Settings.GetUser(uKey)
If Not u Is Nothing Then
i = -1
cm = u.ContentMissing
If cm.Count > 0 Then i = cm.FindIndex(Function(c) c.Post.ID = _d.Text)
If i >= 0 Then u.RemoveMedia(cm(i), UserMedia.States.Missing) : UsersToUpdate.ListAddValue(u, lp)
End If
Next
MsgBoxE({"The selected posts have been successfully deleted", MsgTitle})
Else
MsgBoxE({"Operation canceled", MsgTitle})
End If
Else
MsgBoxE({"No selected posts", MsgTitle})
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendInLog, ex, "[DownloadObjects.MissingPostsForm.DeletePost]")
Finally
UpdateUsers(UsersToUpdate)
UsersToUpdate.Clear()
End Try
End Sub
Private Sub UpdateUsers(ByVal UserList As List(Of UserDataBase))
Try
If UserList.ListExists Then UserList.ForEach(Sub(u) u.UpdateContentInformation())
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendInLog, ex, "[DownloadObjects.MissingPostsForm.UpdateUsers]")
End Try
End Sub
#End Region
End Class
End Namespace

View File

@@ -13,10 +13,6 @@ Imports System.Threading
Namespace DownloadObjects
Friend Class Scheduler : Implements IEnumerable(Of AutoDownloader), IMyEnumerator(Of AutoDownloader), IDisposable
Friend Const Name_Plan As String = "Plan"
Friend Event UserFind As AutoDownloader.UserFindEventHandler
Private Sub OnUserFind(ByVal Key As String, ByVal Activate As Boolean)
RaiseEvent UserFind(Key, Activate)
End Sub
Private ReadOnly Plans As List(Of AutoDownloader)
Private ReadOnly File As SFile = $"Settings\AutoDownload.xml"
Private ReadOnly PlanWorking As Predicate(Of AutoDownloader) = Function(Plan) Plan.Working
@@ -36,10 +32,7 @@ Namespace DownloadObjects
End If
End Using
End If
If Plans.Count > 0 Then Plans.ForEach(Sub(p)
p.Source = Me
AddHandler p.UserFind, AddressOf OnUserFind
End Sub)
If Plans.Count > 0 Then Plans.ForEach(Sub(p) p.Source = Me)
End Sub
Default Friend ReadOnly Property Item(ByVal Index As Integer) As AutoDownloader Implements IMyEnumerator(Of AutoDownloader).MyEnumeratorObject
Get
@@ -56,7 +49,6 @@ Namespace DownloadObjects
End Function
Friend Sub Add(ByVal Plan As AutoDownloader)
Plan.Source = Me
AddHandler Plan.UserFind, AddressOf OnUserFind
Plans.Add(Plan)
Update()
End Sub

View File

@@ -22,27 +22,28 @@ Namespace DownloadObjects
Private components As System.ComponentModel.IContainer
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
Me.LIST_PLANS = New System.Windows.Forms.ListBox()
Me.CONTAINER_MAIN.ContentPanel.SuspendLayout()
Me.CONTAINER_MAIN.SuspendLayout()
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
CONTAINER_MAIN.ContentPanel.SuspendLayout()
CONTAINER_MAIN.SuspendLayout()
Me.SuspendLayout()
'
'CONTAINER_MAIN
'
Me.CONTAINER_MAIN.BottomToolStripPanelVisible = False
CONTAINER_MAIN.BottomToolStripPanelVisible = False
'
'CONTAINER_MAIN.ContentPanel
'
Me.CONTAINER_MAIN.ContentPanel.Controls.Add(Me.LIST_PLANS)
Me.CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(414, 316)
Me.CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
Me.CONTAINER_MAIN.LeftToolStripPanelVisible = False
Me.CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
Me.CONTAINER_MAIN.Name = "CONTAINER_MAIN"
Me.CONTAINER_MAIN.RightToolStripPanelVisible = False
Me.CONTAINER_MAIN.Size = New System.Drawing.Size(414, 341)
Me.CONTAINER_MAIN.TabIndex = 0
CONTAINER_MAIN.ContentPanel.Controls.Add(Me.LIST_PLANS)
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(414, 316)
CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
CONTAINER_MAIN.LeftToolStripPanelVisible = False
CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
CONTAINER_MAIN.Name = "CONTAINER_MAIN"
CONTAINER_MAIN.RightToolStripPanelVisible = False
CONTAINER_MAIN.Size = New System.Drawing.Size(414, 341)
CONTAINER_MAIN.TabIndex = 0
'
'LIST_PLANS
'
@@ -58,20 +59,18 @@ Namespace DownloadObjects
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(414, 341)
Me.Controls.Add(Me.CONTAINER_MAIN)
Me.Controls.Add(CONTAINER_MAIN)
Me.KeyPreview = True
Me.MinimumSize = New System.Drawing.Size(430, 380)
Me.Name = "SchedulerEditorForm"
Me.ShowIcon = False
Me.Text = "Scheduler"
Me.CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
Me.CONTAINER_MAIN.ResumeLayout(False)
Me.CONTAINER_MAIN.PerformLayout()
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
CONTAINER_MAIN.ResumeLayout(False)
CONTAINER_MAIN.PerformLayout()
Me.ResumeLayout(False)
End Sub
Private WithEvents CONTAINER_MAIN As ToolStripContainer
Private WithEvents LIST_PLANS As ListBox
End Class
End Namespace

View File

@@ -117,4 +117,7 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="CONTAINER_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
</root>

View File

@@ -9,18 +9,13 @@
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Toolbars
Namespace DownloadObjects
Friend Class SchedulerEditorForm : Implements IEditToolbar
Private ReadOnly MyDefs As DefaultFormOptions
Friend Class SchedulerEditorForm
Private WithEvents MyDefs As DefaultFormOptions
Private WithEvents BTT_SKIP As ToolStripButton
Private WithEvents BTT_START As ToolStripButton
Friend Sub New()
InitializeComponent()
MyDefs = New DefaultFormOptions
End Sub
Private Sub SchedulerEditorForm_Load(sender As Object, e As EventArgs) Handles Me.Load
With MyDefs
.MyViewInitialize(Me, Settings.Design)
.AddEditToolbar()
MyDefs = New DefaultFormOptions(Me, Settings.Design)
BTT_SKIP = New ToolStripButton With {
.Text = "Skip",
.ToolTipText = "Skip next run",
@@ -33,18 +28,19 @@ Namespace DownloadObjects
.ToolTipText = "Run selected plan",
.AutoToolTip = True
}
.MyEditToolbar.ToolStrip.Items.AddRange({BTT_START, BTT_SKIP})
End Sub
Private Sub SchedulerEditorForm_Load(sender As Object, e As EventArgs) Handles Me.Load
With MyDefs
.MyViewInitialize()
.AddEditToolbarPlus({BTT_START, BTT_SKIP})
Refill()
.EndLoaderOperations(False)
End With
End Sub
Private Sub SchedulerEditorForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
BTT_SKIP.Dispose()
End Sub
Private Sub SchedulerEditorForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If e.KeyCode = Keys.Escape Then Close()
End Sub
Private Sub Refill() Implements IEditToolbar.Update
Private Sub Refill() Handles MyDefs.ButtonUpdateClick
Try
LIST_PLANS.Items.Clear()
If Settings.Automation.Count > 0 Then
@@ -57,7 +53,7 @@ Namespace DownloadObjects
ErrorsDescriber.Execute(EDP.SendInLog, ex)
End Try
End Sub
Private Sub Add() Implements IEditToolbar.Add
Private Sub MyDefs_ButtonAddClick(ByVal Sender As Object, ByVal e As EditToolbarEventArgs) Handles MyDefs.ButtonAddClick
Dim a As New AutoDownloader(True)
Using f As New AutoDownloaderEditorForm(a)
f.ShowDialog()
@@ -69,7 +65,7 @@ Namespace DownloadObjects
End If
End Using
End Sub
Private Sub Edit() Implements IEditToolbar.Edit
Private Sub Edit() Handles MyDefs.ButtonEditClick
If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then
Using f As New AutoDownloaderEditorForm(Settings.Automation(_LatestSelected)) : f.ShowDialog() : End Using
Refill()
@@ -78,14 +74,16 @@ Namespace DownloadObjects
End If
End Sub
Private _DeleteInProgress As Boolean = False
Private Async Sub Delete() Implements IEditToolbar.Delete
Private Async Sub MyDefs_ButtonDeleteClickE(ByVal Sender As Object, ByVal e As EditToolbarEventArgs) Handles MyDefs.ButtonDeleteClickE
If Not _DeleteInProgress Then
If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then
_DeleteInProgress = True
Dim n$ = Settings.Automation(_LatestSelected).Name
If MsgBoxE({$"Are you sure you want to delete the [{n}] plan?", "Deleting a plan..."}, vbExclamation + vbYesNo) = vbYes Then
Await Settings.Automation.RemoveAt(_LatestSelected)
Refill()
MsgBoxE($"Plan [{n}] deleted")
End If
_DeleteInProgress = False
Else
MsgBoxE("You have not selected a plan to delete.", vbExclamation)

View File

@@ -7,22 +7,53 @@
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports System.Threading
Imports PersonalUtilities.Forms.Toolbars
Imports EOptions = PersonalUtilities.Forms.Toolbars.IMyProgress.EnableOptions
Imports SCrawler.API
Imports PersonalUtilities.Tools
Imports SCrawler.API.Base
Imports SCrawler.Plugin.Hosts
Imports Download = SCrawler.Plugin.ISiteSettings.Download
Namespace DownloadObjects
Friend Class TDownloader : Implements IDisposable
#Region "Events"
Friend Event OnJobsChange(ByVal JobsCount As Integer)
Friend Event OnDownloadCountChange()
Friend Event OnDownloading(ByVal Value As Boolean)
Friend Event JobsChange(ByVal JobsCount As Integer)
Friend Event DownloadCountChange()
Friend Event Downloading(ByVal Value As Boolean)
Friend Event SendNotification As NotificationEventHandler
Friend Event OnReconfigured()
Friend Event Reconfigured()
Friend Event FeedFilesChanged(ByVal Added As Boolean)
#End Region
#Region "Declarations"
#Region "Files"
Friend Structure UserMediaD : Implements IComparable(Of UserMediaD), IEquatable(Of UserMediaD)
Friend ReadOnly User As IUserData
Friend ReadOnly Data As UserMedia
Friend ReadOnly [Date] As Date
Friend ReadOnly Session As Integer
Friend Sub New(ByVal Data As UserMedia, ByVal User As IUserData, ByVal Session As Integer)
Me.Data = Data
Me.User = User
[Date] = Now
Me.Session = Session
End Sub
Private Function CompareTo(ByVal Other As UserMediaD) As Integer Implements IComparable(Of UserMediaD).CompareTo
If Not Session = Other.Session Then
Return Session.CompareTo(Other.Session) * -1
ElseIf Not If(User?.GetHashCode, 0) = If(Other.User?.GetHashCode, 0) Then
Return If(User?.GetHashCode, 0).CompareTo(If(Other.User?.GetHashCode, 0))
Else
Return [Date].Ticks.CompareTo(Other.Date.Ticks) * -1
End If
End Function
Private Overloads Function Equals(ByVal Other As UserMediaD) As Boolean Implements IEquatable(Of UserMediaD).Equals
Return Data.File = Other.Data.File
End Function
Public Overloads Overrides Function Equals(ByVal Obj As Object) As Boolean
Return Equals(DirectCast(Obj, UserMedia))
End Function
End Structure
Friend ReadOnly Property Files As List(Of UserMediaD)
Friend Property FilesChanged As Boolean = False
Private ReadOnly FilesLP As New ListAddParams(LAP.NotContainsOnly)
#End Region
Friend ReadOnly Property Downloaded As List(Of IUserData)
Private ReadOnly NProv As IFormatProvider
#End Region
@@ -34,7 +65,7 @@ Namespace DownloadObjects
End Property
Friend ReadOnly Property Count As Integer
Get
If Pool.Count = 0 Then Return 0 Else Return Pool.Sum(Function(j) j.Count)
Return If(Pool.Count = 0, 0, Pool.Sum(Function(j) j.Count))
End Get
End Property
#End Region
@@ -49,34 +80,15 @@ Namespace DownloadObjects
End Set
End Property
Friend Sub InvokeDownloadsChangeEvent()
RaiseEvent OnDownloadCountChange()
RaiseEvent DownloadCountChange()
End Sub
#End Region
#Region "Jobs"
Friend Class Job : Implements IDisposable
Friend Event OnItemsCountChange(ByVal Sender As Job, ByVal Count As Integer)
Friend Class Job : Inherits JobThread(Of IUserData)
Private ReadOnly Hosts As List(Of SettingsHost)
Private ReadOnly Keys As List(Of String)
Private ReadOnly RemovingKeys As List(Of String)
Private TokenSource As CancellationTokenSource
Friend Token As CancellationToken
Private [Thread] As Thread
Private _Working As Boolean
Friend ReadOnly Property Items As List(Of IUserData)
Friend ReadOnly Property [Type] As Download
Friend ReadOnly Property Count As Integer
Get
Return Items.Count
End Get
End Property
Friend Sub Clear()
Items.Clear()
End Sub
Friend ReadOnly Property Working As Boolean
Get
Return _Working OrElse If(Thread?.IsAlive, False)
End Get
End Property
Friend ReadOnly Property IsSeparated As Boolean
Get
Return Hosts.Count = 1 AndAlso Hosts(0).IsSeparatedTasks
@@ -102,21 +114,19 @@ Namespace DownloadObjects
Return Nothing
End Get
End Property
Friend Property Progress As MyProgress
Friend Sub New(ByVal JobType As Download)
Hosts = New List(Of SettingsHost)
RemovingKeys = New List(Of String)
Keys = New List(Of String)
Items = New List(Of IUserData)
[Type] = JobType
End Sub
Friend Function Add(ByVal User As IUserData) As Boolean
Public Overrides Function Add(ByVal User As IUserData) As Boolean
With DirectCast(User, UserDataBase)
If Keys.Count > 0 Then
Dim i% = Keys.IndexOf(.User.Plugin)
If i >= 0 Then
Items.Add(User)
RaiseEvent OnItemsCountChange(Me, Count)
OnItemsCountChange(Me, Count)
Return True
Else
If RemovingKeys.Count > 0 Then Return RemovingKeys.IndexOf(.User.Plugin) >= 0
@@ -151,29 +161,13 @@ Namespace DownloadObjects
Return False
End If
End Function
Friend Sub ThrowIfCancellationRequested()
Token.ThrowIfCancellationRequested()
End Sub
Friend ReadOnly Property IsCancellationRequested As Boolean
Get
Return Token.IsCancellationRequested
End Get
End Property
Friend Sub [Start](ByVal [ThreadStart] As ThreadStart)
Thread = New Thread(ThreadStart) With {.IsBackground = True}
Thread.SetApartmentState(ApartmentState.MTA)
Thread.Start()
End Sub
Friend Sub [Start]()
Public Overrides Sub Start()
If Hosts.Count > 0 Then Hosts.ForEach(Sub(h) h.DownloadStarted([Type]))
TokenSource = New CancellationTokenSource
Token = TokenSource.Token
_Working = True
End Sub
Friend Sub [Stop]()
If Not TokenSource Is Nothing Then TokenSource.Cancel()
End Sub
Friend Sub Stopped()
Public Overrides Sub Stopped()
_Working = False
TokenSource = Nothing
Try
@@ -186,25 +180,13 @@ Namespace DownloadObjects
If Hosts.Count > 0 Then Hosts.ForEach(Sub(h) h.DownloadDone([Type]))
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
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If Not disposedValue And disposing Then
Hosts.Clear()
Keys.Clear()
RemovingKeys.Clear()
Items.Clear()
End If
disposedValue = True
End If
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub
Friend Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
MyBase.Dispose(disposing)
End Sub
#End Region
End Class
@@ -212,6 +194,7 @@ Namespace DownloadObjects
#End Region
#Region "Initializer"
Friend Sub New()
Files = New List(Of UserMediaD)
Downloaded = New List(Of IUserData)
NProv = New ANumbers With {.FormatOptions = ANumbers.Options.GroupIntegral}
Pool = New List(Of Job)
@@ -232,27 +215,32 @@ Namespace DownloadObjects
End If
Next
End If
RaiseEvent OnReconfigured()
RaiseEvent Reconfigured()
End If
End Sub
#End Region
#Region "Thread"
Private CheckerThread As Thread
Private MissingPostsDetected As Boolean = False
Private Session As Integer = 0
Private Sub [Start]()
If Not AutoDownloaderWorking AndAlso MyProgressForm.ReadyToOpen AndAlso Pool.LongCount(Function(p) p.Count > 0) > 1 Then MyProgressForm.Show() : MainFrameObj.Focus()
If Not If(CheckerThread?.IsAlive, False) Then
MainProgress.Enabled = True
MainProgress.Visible = True
If Not AutoDownloaderWorking AndAlso InfoForm.ReadyToOpen Then InfoForm.Show() : MainFrameObj.Focus()
MissingPostsDetected = False
Session += 1
CheckerThread = New Thread(New ThreadStart(AddressOf JobsChecker))
CheckerThread.SetApartmentState(ApartmentState.MTA)
CheckerThread.Start()
End If
End Sub
Private Sub JobsChecker()
RaiseEvent OnDownloading(True)
Dim fBefore% = Files.Count
RaiseEvent Downloading(True)
Try
MainProgress.TotalCount = 0
MainProgress.CurrentCounter = 0
MainProgress.Maximum = 0
MainProgress.Value = 0
MyProgressForm.DisableProgressChange = False
Do While Pool.Exists(Function(p) p.Count > 0 Or p.Working)
For Each j As Job In Pool
@@ -263,16 +251,23 @@ Namespace DownloadObjects
Catch
Finally
With MainProgress
.TotalCount = 0
.CurrentCounter = 0
.Maximum = 0
.Value = 0
.InformationTemporary = "All data downloaded"
.Enabled(EOptions.ProgressBar) = False
.Visible(, False) = False
End With
MyProgressForm.DisableProgressChange = True
If Pool.Count > 0 Then Pool.ForEach(Sub(p) If Not p.Progress Is Nothing Then p.Progress.TotalCount = 0)
If Pool.Count > 0 Then Pool.ForEach(Sub(p) If Not p.Progress Is Nothing Then p.Progress.Maximum = 0)
ExecuteCommand(Settings.DownloadsCompleteCommand)
UpdateJobsLabel()
RaiseEvent OnDownloading(False)
If MissingPostsDetected And Settings.AddMissingToLog Then
MyMainLOG = "Some posts didn't download. You can see them in the 'Missing posts' form."
MainFrameObj.UpdateLogButton()
End If
Files.Sort()
FilesChanged = Not fBefore = Files.Count
RaiseEvent Downloading(False)
If FilesChanged Then RaiseEvent FeedFilesChanged(True)
End Try
End Sub
Private Sub StartDownloading(ByRef _Job As Job)
@@ -285,9 +280,9 @@ Namespace DownloadObjects
End Function
Try
_Job.Start()
_Job.Progress.TotalCount = 0
_Job.Progress.CurrentCounter = 0
_Job.Progress.Enabled = True
_Job.Progress.Maximum = 0
_Job.Progress.Value = 0
_Job.Progress.Visible = True
Dim SiteChecked As Boolean = False
Do While _Job.Count > 0
_Job.ThrowIfCancellationRequested()
@@ -312,7 +307,7 @@ Namespace DownloadObjects
If Pool.Count > 0 Then Pool.ForEach(Sub(j) If j.Working Then j.Stop())
End Sub
Private Sub UpdateJobsLabel()
RaiseEvent OnJobsChange(Count)
RaiseEvent JobsChange(Count)
End Sub
Private Sub DownloadData(ByRef _Job As Job, ByVal Token As CancellationToken)
Try
@@ -340,7 +335,7 @@ Namespace DownloadObjects
Next
If t.Count > 0 Or Keys.Count > 0 Then
With _Job.Progress
.Enabled(EOptions.All) = True
.Visible = True
.Information = IIf(_Job.IsSeparated, $"{_Job.Name} d", "D")
.Information &= $"ownloading {t.Count.NumToString(nf, NProv)}/{_Job.Items.Count.NumToString(nf, NProv)} profiles' data"
.InformationTemporary = .Information
@@ -352,9 +347,13 @@ Namespace DownloadObjects
i = _Job.Items.FindIndex(Function(ii) ii.Key = k)
If i >= 0 Then
With _Job.Items(i)
If DirectCast(.Self, UserDataBase).ContentMissingExists Then MissingPostsDetected = True
host.AfterDownload(_Job.Items(i), Download.Main)
If Not .Disposed AndAlso Not .IsCollection AndAlso .DownloadedTotal(False) > 0 Then
If Not Downloaded.Contains(.Self) Then Downloaded.Add(GetUserFromMainCollection(.Self))
If Not Downloaded.Contains(.Self) Then Downloaded.Add(Settings.GetUser(.Self))
With DirectCast(.Self, UserDataBase)
If .LatestData.Count > 0 Then Files.ListAddList(.LatestData.Select(Function(d) New UserMediaD(d, .Self, Session)), FilesLP)
End With
dcc = True
End If
End With
@@ -365,7 +364,7 @@ Namespace DownloadObjects
Keys.Clear()
_Job.Items.RemoveAll(Function(ii) ii.Disposed)
If dcc Then Downloaded.RemoveAll(Function(u) u Is Nothing)
If dcc And Downloaded.Count > 0 Then RaiseEvent OnDownloadCountChange()
If dcc And Downloaded.Count > 0 Then RaiseEvent DownloadCountChange()
t.Clear()
End If
End If
@@ -381,30 +380,6 @@ Namespace DownloadObjects
End Sub))
End Try
End Sub
Friend Shared Function GetUserFromMainCollection(ByVal User As IUserData) As IUserData
Dim uSimple As Predicate(Of IUserData) = Function(u) u.Equals(DirectCast(User, UserDataBase))
Dim uCol As Predicate(Of IUserData) = Function(ByVal u As IUserData) As Boolean
If u.IsCollection Then
Return DirectCast(u, UserDataBind).Collections.Exists(uSimple)
Else
Return False
End If
End Function
Dim uu As Predicate(Of IUserData)
If User.IncludedInCollection Then uu = uCol Else uu = uSimple
Dim i% = Settings.Users.FindIndex(uu)
If i >= 0 Then
If Settings.Users(i).IsCollection Then
With DirectCast(Settings.Users(i), UserDataBind)
i = .Collections.FindIndex(uSimple)
If i >= 0 Then Return .Collections(i)
End With
Else
Return Settings.Users(i)
End If
End If
Return Nothing
End Function
#End Region
#Region "Add"
Private Sub AddItem(ByVal Item As IUserData, ByVal _UpdateJobsLabel As Boolean)
@@ -444,7 +419,8 @@ Namespace DownloadObjects
Return False
End Function
Friend Sub UserRemove(ByVal _Item As IUserData)
If Downloaded.Count > 0 AndAlso Downloaded.Contains(_Item) Then Downloaded.Remove(_Item) : RaiseEvent OnDownloadCountChange()
If Downloaded.Count > 0 AndAlso Downloaded.Contains(_Item) Then Downloaded.Remove(_Item) : RaiseEvent DownloadCountChange()
If Files.Count > 0 AndAlso Files.RemoveAll(Function(f) Not f.User Is Nothing AndAlso f.User.Equals(_Item)) > 0 Then RaiseEvent FeedFilesChanged(False)
End Sub
#End Region
#Region "IDisposable Support"
@@ -454,6 +430,7 @@ Namespace DownloadObjects
If disposing Then
[Stop]()
Pool.ListClearDispose
Files.Clear()
Downloaded.Clear()
End If
disposedValue = True

View File

@@ -16,11 +16,13 @@
Private Sub InitializeComponent()
Dim SEP_1 As System.Windows.Forms.ToolStripSeparator
Dim SEP_2 As System.Windows.Forms.ToolStripSeparator
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(VideosDownloaderForm))
Me.ToolbarTOP = New System.Windows.Forms.ToolStrip()
Me.BTT_ADD = New System.Windows.Forms.ToolStripButton()
Me.BTT_ADD_LIST = New System.Windows.Forms.ToolStripButton()
Me.BTT_DELETE = New System.Windows.Forms.ToolStripButton()
Me.BTT_DOWN = New System.Windows.Forms.ToolStripButton()
Me.BTT_STOP = New System.Windows.Forms.ToolStripButton()
Me.BTT_OPEN_PATH = New System.Windows.Forms.ToolStripButton()
Me.ToolbarBOTTOM = New System.Windows.Forms.StatusStrip()
Me.PR_V = New System.Windows.Forms.ToolStripProgressBar()
@@ -45,7 +47,7 @@
'ToolbarTOP
'
Me.ToolbarTOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden
Me.ToolbarTOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_ADD, Me.BTT_ADD_LIST, Me.BTT_DELETE, SEP_1, Me.BTT_DOWN, SEP_2, Me.BTT_OPEN_PATH})
Me.ToolbarTOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_ADD, Me.BTT_ADD_LIST, Me.BTT_DELETE, SEP_1, Me.BTT_DOWN, Me.BTT_STOP, SEP_2, Me.BTT_OPEN_PATH})
Me.ToolbarTOP.Location = New System.Drawing.Point(0, 0)
Me.ToolbarTOP.Name = "ToolbarTOP"
Me.ToolbarTOP.Size = New System.Drawing.Size(524, 25)
@@ -87,6 +89,16 @@
Me.BTT_DOWN.Size = New System.Drawing.Size(104, 22)
Me.BTT_DOWN.Text = "Download (F5)"
'
'BTT_STOP
'
Me.BTT_STOP.AutoToolTip = False
Me.BTT_STOP.Enabled = False
Me.BTT_STOP.Image = CType(resources.GetObject("BTT_STOP.Image"), System.Drawing.Image)
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"
'
'BTT_OPEN_PATH
'
Me.BTT_OPEN_PATH.AutoToolTip = False
@@ -156,5 +168,6 @@
Private WithEvents LIST_VIDEOS As ListBox
Private WithEvents BTT_DOWN As ToolStripButton
Private WithEvents BTT_OPEN_PATH As ToolStripButton
Private WithEvents BTT_STOP As ToolStripButton
End Class
End Namespace

View File

@@ -126,6 +126,36 @@
<metadata name="ToolbarTOP.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="BTT_STOP.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAVCSURBVEhLjZVtTFNXGMcLQmdHO6CdhGSlc4gDBAr2Qrmo
GJygFFuBtoLKiJpRcUXFF5QoRmM00SgmS/Zh+7B92DKTmblEl2VzgEDmBBJgoBPDm4qlLX0vXOaWLNCz
/ynFl1g2nuSX9p7zP//nyXPOPZdHo7+gIKItPv6L9tjYkSaZ7PMtUuk7GA7zT/5PDCuV7BOZ7M5obGzf
jYQEPYYiQIh/ksYDo1HYXVBwfbi+noxduUIe1dX5mli2NVskWonp8DlV8BhkmHXWHTuecpcukenGRvKk
rMz9aVJSjSwyMhrTc0laV6z4bOjIEfL47FkyduYMMUNsOn6c3GLZO3KR6H1IgiYZzcn5AOYm7vJlwmEt
19BApk+fJsMajecHqfQTSMQgjNcukZip+eO6OvL05ElihmjiwgUyXl/va1Iqf0sTiRIhfCUJ2rLJWl5u
ppVT82mYc8eOkWkU5q2sJG0xMQOQsUDEa4mLuzpSVUXGkMAEzCdOECsW2M+fJxa0q4VlO1OFwiSI/UmG
FYpNE2Vl5qmLFwmHYqZRFId104cPk8l9+8htpdK5SyL5DtIiIOZply9/91Zm5p3RPXt84xBZwASqsWNP
XGiZ4+hR0o4kq4XC5N8ZpsCi11unzp3zt4RDxRzay9XWkimYt2dluRMFgq9hbAByQDecF85IJElI0mna
tYtYDxwgtv37if3QIeJEMg+M8Ozrysm5N1ZcbOZOnfJXzGGOg5arqZkzZxh3skBwFX5VICVgHgr8wV8t
Fif/olB0mCoqfLbqauIALqORuGHgRTLvwYNkCtVOUWM8c3j2m6O9HSzrkQuF1JxWvgosBS+OaiD4SrF4
VUt6eqd12zbi2L2buIDHYCBeVDiJhJPYwMniYuLdsIF4c3KIG3RkZ3szRKJrWL8X0MoF4DXz+eBnRUen
3JbLO81q9Yx7+3biUqmIi2GIUyolTpGIOMPDiXPJEmITCn0t8fEeNiqKbmg1SAVvggXN58Pfrm65vH8C
hjaY2YEDUGM/YWHkoULxtz4p6SfoPwZpYFHm/rBWVhqta9eabALB6+aAjo0nJMy0aTSPkuPiirEkEizO
3GswHHVu3Oi0ofqFzC3gKTClpJA+rXZg55o1GVj6n9eKP1wGQ4Nj82aXLSLiNXMHek/bRc3HwEhoKHkA
BjMyfP063UM9y9I2LZzEs3fvSUdhoTtY5Q6JhIwXFv5jSUz0UfPhgHkv6AD3GWYWSQZ2LpQER7EB5h6c
DL/xK22JiSGDRUV/nlu/vqtXrZ4wJSeTP2DaA+6CX0Eb6MvKmu3W6+9tlMvpBfniqndXVdU7VCqPPZj5
smVkqKjoWQ3DtEC6vzA19cOBkpJHg+j9vHkraAa3QLdSOdul0/V+pdHQjeeDEJ67tNRsj4oKWjk1r1Yo
miE0ArqR4kN5eWv7tdrRe2lpz81/Bj+Cm6A/N3emR6sdgnY54PPsOt2gWyYLWrmRYW5DVBMwn/9S8Q/n
57N9Ot1oT1qa72Xz70NCSM+6dTPtarUFugIQzeuqqNgxoVa7XDB9qfK/DgQ3nw9+bV5eNjZ2pDs9ndwI
mN/Nzp79VqUaL1q58kto5hIgljaXlZ0yb93qsbOsb0ilelabmdmK8YXM54NvyM1V0HZ0Yx1u29nrKpXl
LYGgEXOlYK5FiBAmPj6yV6v95nFJieNafj5OX2gtxhkgpPNUtEDwb5aXf3S/tNRyV6NxFiYm0m+BFkgB
Pa7P19I/USATbAn8Lvb1fwPQo0lPjhq8B4K+cEsArZh+rOkvfV5M0CLo/f92AJowUBiP9y9PzdvIaubv
/QAAAABJRU5ErkJggg==
</value>
</data>
<metadata name="ToolbarBOTTOM.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>124, 17</value>
</metadata>

View File

@@ -8,27 +8,26 @@
' but WITHOUT ANY WARRANTY
Imports System.ComponentModel
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Tools
Namespace DownloadObjects
Friend Class VideosDownloaderForm
#Region "Declarations"
Private MyView As FormsView
Private ReadOnly MyPR As Toolbars.MyProgress
Private ReadOnly UrlList As List(Of String)
Private ReadOnly DownloadingUrlsFile As SFile = $"{SettingsFolderName}\VideosUrls.txt"
Private ReadOnly MyJob As JobThread(Of String)
#End Region
#Region "Initializer"
Friend Sub New()
InitializeComponent()
UrlList = New List(Of String)
MyPR = New Toolbars.MyProgress(ToolbarBOTTOM, PR_V, LBL_STATUS, "Downloading video")
MyJob = New JobThread(Of String) With {.Progress = New Toolbars.MyProgress(ToolbarBOTTOM, PR_V, LBL_STATUS, "Downloading video")}
If DownloadingUrlsFile.Exists Then _
UrlList.ListAddList(DownloadingUrlsFile.GetText.StringToList(Of String, List(Of String))(Environment.NewLine), LAP.NotContainsOnly)
MyJob.Items.ListAddList(DownloadingUrlsFile.GetText.StringToList(Of String, List(Of String))(Environment.NewLine), LAP.NotContainsOnly)
End Sub
Private Sub VideosDownloaderForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
MyView = New FormsView(Me)
MyView.ImportFromXML(Settings.Design)
MyView.SetMeSize()
RefillList(False)
Catch ex As Exception
End Try
End Sub
Private Sub VideosDownloaderForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
e.Cancel = True
@@ -36,95 +35,120 @@ Namespace DownloadObjects
End Sub
Private Sub VideosDownloaderForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
If Not MyView Is Nothing Then MyView.Dispose(Settings.Design)
If UrlList.Count > 0 Then UpdateUrlsFile()
UrlList.Clear()
If MyJob.Count > 0 Then UpdateUrlsFile()
MyJob.Dispose()
End Sub
Private Sub VideosDownloaderForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
Dim b As Boolean = True
Select Case e.KeyCode
Case Keys.Insert : AddVideo()
Case Keys.F5 : DownloadVideos()
Case Keys.F8 : BTT_DELETE_Click(Nothing, EventArgs.Empty)
Case Keys.Insert : AddItem()
Case Keys.F5 : StartDownloading()
Case Keys.F8 : DeleteItem()
Case Else : b = False
End Select
If b Then e.Handled = True
End Sub
#End Region
#Region "Refill, Update file"
Private Sub RefillList(Optional ByVal Update As Boolean = True)
Try
Dim a As Action = Sub()
With LIST_VIDEOS
.Items.Clear()
If UrlList.Count > 0 Then UrlList.ForEach(Sub(u) .Items.Add(u))
If .Items.Count > 0 And _LatestSelected >= 0 And _LatestSelected <= .Items.Count - 1 Then .SelectedIndex = _LatestSelected
If MyJob.Count > 0 Then MyJob.Items.ForEach(Sub(u) .Items.Add(u))
If _LatestSelected.ValueBetween(0, .Items.Count - 1) Then .SelectedIndex = _LatestSelected
If Update Then UpdateUrlsFile()
End With
End Sub
If LIST_VIDEOS.InvokeRequired Then LIST_VIDEOS.Invoke(a) Else a.Invoke
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Error on list refill")
ErrorsDescriber.Execute(EDP.SendInLog, ex, "Error on list refill")
End Try
End Sub
Private Sub UpdateUrlsFile()
If UrlList.Count > 0 Then
TextSaver.SaveTextToFile(UrlList.ListToString(Environment.NewLine), DownloadingUrlsFile, True,, EDP.SendInLog)
If MyJob.Count > 0 Then
TextSaver.SaveTextToFile(MyJob.ListToString(Environment.NewLine), DownloadingUrlsFile, True,, EDP.SendInLog)
Else
DownloadingUrlsFile.Delete(, Settings.DeleteMode, EDP.SendInLog)
End If
End Sub
Private Sub BTT_ADD_Click(sender As Object, e As EventArgs) Handles BTT_ADD.Click
AddVideo()
End Sub
Private Sub AddVideo()
#End Region
#Region "Add, Delete"
Private Sub AddItem() Handles BTT_ADD.Click
Dim URL$ = GetNewVideoURL()
If Not URL.IsEmptyString Then
If Not UrlList.Contains(URL) Then
UrlList.Add(URL)
If Not MyJob.Contains(URL) Then
MyJob.Add(URL)
RefillList()
Else
MsgBoxE("This URL already added to list")
MsgBoxE("This URL has already been added to the list")
End If
End If
End Sub
Private Sub BTT_ADD_LIST_Click(sender As Object, e As EventArgs) Handles BTT_ADD_LIST.Click
Private Sub AddItemsRange() Handles BTT_ADD_LIST.Click
Dim l$ = InputBoxE("Enter URLs (new line as delimiter):", "URLs list", GetCurrentBuffer(),,,,,, True)
If Not l.IsEmptyString Then
Dim ub% = UrlList.Count
UrlList.ListAddList(l.StringFormatLines.StringToList(Of String, List(Of String))(vbCrLf).ListForEach(Function(u, i) u.Trim,, False))
If Not UrlList.Count = ub Then RefillList()
Dim ub% = MyJob.Count
MyJob.Items.ListAddList(l.StringFormatLines.StringToList(Of String, List(Of String))(vbCrLf).ListForEach(Function(u, i) u.Trim,, False))
If Not MyJob.Count = ub Then RefillList()
End If
End Sub
Private Sub BTT_DELETE_Click(sender As Object, e As EventArgs) Handles BTT_DELETE.Click
If _LatestSelected >= 0 And _LatestSelected <= UrlList.Count - 1 Then
If MsgBoxE({$"Do you really want to delete video URL:{vbCr}{UrlList(_LatestSelected)}", "Deleting URL..."},
MsgBoxStyle.Exclamation + MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
UrlList.RemoveAt(_LatestSelected)
Private Sub DeleteItem() Handles BTT_DELETE.Click
If _LatestSelected.ValueBetween(0, MyJob.Count - 1) Then
If MsgBoxE({$"Are you sure you want to delete the video URL:{vbCr}{MyJob(_LatestSelected)}", "Deleting URL..."}, vbExclamation + vbYesNo) = vbYes Then
MyJob.Items.RemoveAt(_LatestSelected)
RefillList()
End If
Else
MsgBoxE("URL does not selected", MsgBoxStyle.Exclamation)
MsgBoxE("URL not selected", MsgBoxStyle.Exclamation)
End If
End Sub
#End Region
#Region "Start, Stop"
Private Sub BTT_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_DOWN.Click
DownloadVideos()
StartDownloading()
End Sub
Private Sub BTT_STOP_Click(sender As Object, e As EventArgs) Handles BTT_STOP.Click
ControlInvoke(ToolbarTOP, BTT_STOP, Sub() BTT_STOP.Enabled = False)
MyJob.Stop()
End Sub
#End Region
#Region "Downloading"
Private Sub StartDownloading()
If Not MyJob.Working And MyJob.Count > 0 Then
ControlInvoke(ToolbarTOP, BTT_DOWN, Sub() BTT_DOWN.Enabled = False)
ControlInvoke(ToolbarTOP, BTT_STOP, Sub() BTT_STOP.Enabled = True)
MyJob.Start(AddressOf DownloadVideos, Threading.ApartmentState.STA)
End If
End Sub
Private Sub DownloadVideos()
If UrlList.Count > 0 Then
MyPR.TotalCount = UrlList.Count
MyPR.Enabled = True
MyJob.Start()
If MyJob.Count > 0 Then
MyJob.Progress.Maximum = MyJob.Count
MyJob.Progress.Visible = True
Dim IsFirst As Boolean = True
For i% = UrlList.Count - 1 To 0 Step -1
If DownloadVideoByURL(UrlList(i), IsFirst, True) Then UrlList.RemoveAt(i)
MyPR.Perform()
For i% = MyJob.Count - 1 To 0 Step -1
If MyJob.IsCancellationRequested Then Exit For
If DownloadVideoByURL(MyJob(i), IsFirst, True) Then MyJob.Items.RemoveAt(i)
MyJob.Progress.Perform()
IsFirst = False
Next
MyPR.Done()
MyJob.Progress.Done()
RefillList()
MyPR.Enabled = False
Else
MsgBoxE("No one video added", MsgBoxStyle.Exclamation)
MyJob.Progress.Visible = False
End If
ControlInvoke(ToolbarTOP, BTT_DOWN, Sub() BTT_DOWN.Enabled = True)
ControlInvoke(ToolbarTOP, BTT_STOP, Sub() BTT_STOP.Enabled = False)
MyJob.Stopped()
End Sub
#End Region
#Region "List handlers"
Private _LatestSelected As Integer = -1
Private Sub LIST_VIDEOS_SelectedIndexChanged(sender As Object, e As EventArgs) Handles LIST_VIDEOS.SelectedIndexChanged
_LatestSelected = LIST_VIDEOS.SelectedIndex
End Sub
#End Region
#Region "Open path"
Private Sub BTT_OPEN_PATH_Click(sender As Object, e As EventArgs) Handles BTT_OPEN_PATH.Click
With Settings.LatestSavingPath
If Not .Value.IsEmptyString Then
@@ -134,9 +158,10 @@ Namespace DownloadObjects
MsgBoxE($"Path [{ .Value}] does not exists!", MsgBoxStyle.Exclamation)
End If
Else
MsgBoxE("Saving path does not set!", MsgBoxStyle.Exclamation)
MsgBoxE("Save path not specified!", MsgBoxStyle.Exclamation)
End If
End With
End Sub
#End Region
End Class
End Namespace

View File

@@ -14,13 +14,14 @@
Private components As System.ComponentModel.IContainer
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(CollectionEditorForm))
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
Me.CMB_COLLECTIONS = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
Me.CONTAINER_MAIN.ContentPanel.SuspendLayout()
Me.CONTAINER_MAIN.SuspendLayout()
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
CONTAINER_MAIN.ContentPanel.SuspendLayout()
CONTAINER_MAIN.SuspendLayout()
CType(Me.CMB_COLLECTIONS, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
@@ -29,17 +30,17 @@
'
'CONTAINER_MAIN.ContentPanel
'
Me.CONTAINER_MAIN.ContentPanel.Controls.Add(Me.CMB_COLLECTIONS)
Me.CONTAINER_MAIN.ContentPanel.Padding = New System.Windows.Forms.Padding(2, 0, 2, 0)
Me.CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(454, 251)
Me.CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
Me.CONTAINER_MAIN.LeftToolStripPanelVisible = False
Me.CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
Me.CONTAINER_MAIN.Name = "CONTAINER_MAIN"
Me.CONTAINER_MAIN.RightToolStripPanelVisible = False
Me.CONTAINER_MAIN.Size = New System.Drawing.Size(454, 251)
Me.CONTAINER_MAIN.TabIndex = 0
Me.CONTAINER_MAIN.TopToolStripPanelVisible = False
CONTAINER_MAIN.ContentPanel.Controls.Add(Me.CMB_COLLECTIONS)
CONTAINER_MAIN.ContentPanel.Padding = New System.Windows.Forms.Padding(2, 0, 2, 0)
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(454, 251)
CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
CONTAINER_MAIN.LeftToolStripPanelVisible = False
CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
CONTAINER_MAIN.Name = "CONTAINER_MAIN"
CONTAINER_MAIN.RightToolStripPanelVisible = False
CONTAINER_MAIN.Size = New System.Drawing.Size(454, 251)
CONTAINER_MAIN.TabIndex = 0
CONTAINER_MAIN.TopToolStripPanelVisible = False
'
'CMB_COLLECTIONS
'
@@ -63,7 +64,7 @@
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(454, 251)
Me.Controls.Add(Me.CONTAINER_MAIN)
Me.Controls.Add(CONTAINER_MAIN)
Me.KeyPreview = True
Me.MinimizeBox = False
Me.MinimumSize = New System.Drawing.Size(470, 290)
@@ -71,15 +72,13 @@
Me.ShowIcon = False
Me.ShowInTaskbar = False
Me.Text = "Collection"
Me.CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
Me.CONTAINER_MAIN.ResumeLayout(False)
Me.CONTAINER_MAIN.PerformLayout()
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
CONTAINER_MAIN.ResumeLayout(False)
CONTAINER_MAIN.PerformLayout()
CType(Me.CMB_COLLECTIONS, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
End Sub
Private WithEvents CONTAINER_MAIN As ToolStripContainer
Private WithEvents CMB_COLLECTIONS As PersonalUtilities.Forms.Controls.ComboBoxExtended
End Class
End Namespace

View File

@@ -117,6 +117,9 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="CONTAINER_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="ActionButton1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>

View File

@@ -8,15 +8,14 @@
' but WITHOUT ANY WARRANTY
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Controls.Base
Imports PersonalUtilities.Forms.Toolbars
Namespace Editors
Friend Class CollectionEditorForm : Implements IOkCancelToolbar
Private ReadOnly MyDefs As DefaultFormOptions
Friend Class CollectionEditorForm
Private WithEvents MyDefs As DefaultFormOptions
Private ReadOnly Collections As List(Of String)
Friend Property [Collection] As String = String.Empty
Friend Sub New()
InitializeComponent()
MyDefs = New DefaultFormOptions
MyDefs = New DefaultFormOptions(Me, Settings.Design)
Collections = New List(Of String)
End Sub
Friend Sub New(ByVal CollectionName As String)
@@ -26,8 +25,9 @@ Namespace Editors
Private Sub CollectionEditorForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
With MyDefs
.MyViewInitialize(Me, Settings.Design)
.MyViewInitialize()
.AddOkCancelToolbar()
Collections.ListAddList(Settings.LastCollections)
Collections.ListAddList((From c In Settings.Users Where c.IsCollection Select c.CollectionName), LAP.NotContainsOnly, EDP.ThrowException)
If Collections.ListExists Then Collections.Sort() : CMB_COLLECTIONS.Items.AddRange(From c In Collections Select New ListItem(c))
If Not Collection.IsEmptyString And Collections.Contains(Collection) Then CMB_COLLECTIONS.SelectedIndex = Collections.IndexOf(Collection)
@@ -44,23 +44,24 @@ Namespace Editors
Private Sub CollectionEditorForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If e.KeyCode = Keys.Insert Then AddNewCollection() : e.Handled = True Else e.Handled = False
End Sub
Private Sub OK() Implements IOkCancelToolbar.OK
Private Sub MyDefs_ButtonOkClick() Handles MyDefs.ButtonOkClick
If CMB_COLLECTIONS.SelectedIndex >= 0 Then
Collection = CMB_COLLECTIONS.Value.ToString
With Settings.LastCollections
If .Contains(Collection) Then .Remove(Collection)
If .Count = 0 Then .Add(Collection) Else .Insert(0, Collection)
End With
MyDefs.CloseForm()
Else
MsgBoxE("Collection not selected", MsgBoxStyle.Exclamation)
End If
End Sub
Private Sub Cancel() Implements IOkCancelToolbar.Cancel
MyDefs.CloseForm(DialogResult.Cancel)
End Sub
Private Sub CMB_COLLECTIONS_ActionOnButtonClick(ByVal Sender As ActionButton) Handles CMB_COLLECTIONS.ActionOnButtonClick
Private Sub CMB_COLLECTIONS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles CMB_COLLECTIONS.ActionOnButtonClick
If Sender.DefaultButton = ActionButton.DefaultButtons.Add Then AddNewCollection()
End Sub
Private Sub CMB_COLLECTIONS_ActionOnListDoubleClick(ByVal _Item As ListViewItem) Handles CMB_COLLECTIONS.ActionOnListDoubleClick
_Item.Selected = True
OK()
MyDefs_ButtonOkClick()
End Sub
Private Sub AddNewCollection()
Dim c$ = InputBoxE("Enter new collection name:", "Collection name")

View File

@@ -44,6 +44,10 @@
Dim TP_DOWNLOADING As System.Windows.Forms.TableLayoutPanel
Dim ActionButton9 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton10 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TP_MISSING_DATA As System.Windows.Forms.TableLayoutPanel
Dim TAB_FEED As System.Windows.Forms.TabPage
Dim TP_FEED As System.Windows.Forms.TableLayoutPanel
Dim TP_FEED_IMG_COUNT As System.Windows.Forms.TableLayoutPanel
Me.TXT_GLOBAL_PATH = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_IMAGE_LARGE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_IMAGE_SMALL = New PersonalUtilities.Forms.Controls.TextBoxExtended()
@@ -72,6 +76,8 @@
Me.CH_UDESCR_UP = New System.Windows.Forms.CheckBox()
Me.CH_DOWN_OPEN_INFO_SUSPEND = New System.Windows.Forms.CheckBox()
Me.CH_DOWN_OPEN_PROGRESS_SUSPEND = New System.Windows.Forms.CheckBox()
Me.CH_ADD_MISSING_TO_LOG = New System.Windows.Forms.CheckBox()
Me.CH_ADD_MISSING_ERROS_TO_LOG = New System.Windows.Forms.CheckBox()
Me.TXT_CHANNELS_ROWS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_CHANNELS_COLUMNS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.CH_DOWN_IMAGES_NATIVE = New System.Windows.Forms.CheckBox()
@@ -86,6 +92,11 @@
Me.CH_DOWN_OPEN_PROGRESS = New System.Windows.Forms.CheckBox()
Me.TXT_SCRIPT = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_DOWN_COMPLETE_SCRIPT = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_FEED_ROWS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_FEED_COLUMNS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.CH_FEED_ENDLESS = New System.Windows.Forms.CheckBox()
Me.CH_FEED_ADD_SESSION = New System.Windows.Forms.CheckBox()
Me.CH_FEED_ADD_DATE = New System.Windows.Forms.CheckBox()
Me.TAB_MAIN = New System.Windows.Forms.TabControl()
Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
TP_BASIS = New System.Windows.Forms.TableLayoutPanel()
@@ -106,6 +117,10 @@
TP_OPEN_PROGRESS = New System.Windows.Forms.TableLayoutPanel()
TAB_DOWN = New System.Windows.Forms.TabPage()
TP_DOWNLOADING = New System.Windows.Forms.TableLayoutPanel()
TP_MISSING_DATA = New System.Windows.Forms.TableLayoutPanel()
TAB_FEED = New System.Windows.Forms.TabPage()
TP_FEED = New System.Windows.Forms.TableLayoutPanel()
TP_FEED_IMG_COUNT = New System.Windows.Forms.TableLayoutPanel()
TP_BASIS.SuspendLayout()
CType(Me.TXT_GLOBAL_PATH, System.ComponentModel.ISupportInitialize).BeginInit()
TP_IMAGES.SuspendLayout()
@@ -136,6 +151,12 @@
TP_DOWNLOADING.SuspendLayout()
CType(Me.TXT_SCRIPT, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_DOWN_COMPLETE_SCRIPT, System.ComponentModel.ISupportInitialize).BeginInit()
TP_MISSING_DATA.SuspendLayout()
TAB_FEED.SuspendLayout()
TP_FEED.SuspendLayout()
TP_FEED_IMG_COUNT.SuspendLayout()
CType(Me.TXT_FEED_ROWS, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_FEED_COLUMNS, System.ComponentModel.ISupportInitialize).BeginInit()
Me.TAB_MAIN.SuspendLayout()
Me.CONTAINER_MAIN.ContentPanel.SuspendLayout()
Me.CONTAINER_MAIN.SuspendLayout()
@@ -215,7 +236,7 @@
Me.TXT_IMAGE_LARGE.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_IMAGE_LARGE.Location = New System.Drawing.Point(3, 3)
Me.TXT_IMAGE_LARGE.Name = "TXT_IMAGE_LARGE"
Me.TXT_IMAGE_LARGE.NumberMaximum = New Decimal(New Integer() {1000, 0, 0, 0})
Me.TXT_IMAGE_LARGE.NumberMaximum = New Decimal(New Integer() {256, 0, 0, 0})
Me.TXT_IMAGE_LARGE.NumberMinimum = New Decimal(New Integer() {50, 0, 0, 0})
Me.TXT_IMAGE_LARGE.Size = New System.Drawing.Size(278, 22)
Me.TXT_IMAGE_LARGE.TabIndex = 0
@@ -231,7 +252,7 @@
Me.TXT_IMAGE_SMALL.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_IMAGE_SMALL.Location = New System.Drawing.Point(287, 3)
Me.TXT_IMAGE_SMALL.Name = "TXT_IMAGE_SMALL"
Me.TXT_IMAGE_SMALL.NumberMaximum = New Decimal(New Integer() {500, 0, 0, 0})
Me.TXT_IMAGE_SMALL.NumberMaximum = New Decimal(New Integer() {256, 0, 0, 0})
Me.TXT_IMAGE_SMALL.NumberMinimum = New Decimal(New Integer() {10, 0, 0, 0})
Me.TXT_IMAGE_SMALL.Size = New System.Drawing.Size(278, 22)
Me.TXT_IMAGE_SMALL.TabIndex = 1
@@ -606,6 +627,30 @@
TT_MAIN.SetToolTip(Me.CH_DOWN_OPEN_PROGRESS_SUSPEND, "Do not open the form automatically if it was once closed")
Me.CH_DOWN_OPEN_PROGRESS_SUSPEND.UseVisualStyleBackColor = True
'
'CH_ADD_MISSING_TO_LOG
'
Me.CH_ADD_MISSING_TO_LOG.AutoSize = True
Me.CH_ADD_MISSING_TO_LOG.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_ADD_MISSING_TO_LOG.Location = New System.Drawing.Point(4, 4)
Me.CH_ADD_MISSING_TO_LOG.Name = "CH_ADD_MISSING_TO_LOG"
Me.CH_ADD_MISSING_TO_LOG.Size = New System.Drawing.Size(279, 17)
Me.CH_ADD_MISSING_TO_LOG.TabIndex = 0
Me.CH_ADD_MISSING_TO_LOG.Text = "Add 'missing' information to log"
TT_MAIN.SetToolTip(Me.CH_ADD_MISSING_TO_LOG, resources.GetString("CH_ADD_MISSING_TO_LOG.ToolTip"))
Me.CH_ADD_MISSING_TO_LOG.UseVisualStyleBackColor = True
'
'CH_ADD_MISSING_ERROS_TO_LOG
'
Me.CH_ADD_MISSING_ERROS_TO_LOG.AutoSize = True
Me.CH_ADD_MISSING_ERROS_TO_LOG.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_ADD_MISSING_ERROS_TO_LOG.Location = New System.Drawing.Point(290, 4)
Me.CH_ADD_MISSING_ERROS_TO_LOG.Name = "CH_ADD_MISSING_ERROS_TO_LOG"
Me.CH_ADD_MISSING_ERROS_TO_LOG.Size = New System.Drawing.Size(280, 17)
Me.CH_ADD_MISSING_ERROS_TO_LOG.TabIndex = 1
Me.CH_ADD_MISSING_ERROS_TO_LOG.Text = "Add 'missing' errors to log"
TT_MAIN.SetToolTip(Me.CH_ADD_MISSING_ERROS_TO_LOG, resources.GetString("CH_ADD_MISSING_ERROS_TO_LOG.ToolTip"))
Me.CH_ADD_MISSING_ERROS_TO_LOG.UseVisualStyleBackColor = True
'
'TP_CHANNELS_IMGS
'
TP_CHANNELS_IMGS.ColumnCount = 2
@@ -962,15 +1007,17 @@
TP_DOWNLOADING.Controls.Add(Me.TXT_SCRIPT, 0, 3)
TP_DOWNLOADING.Controls.Add(Me.CH_UDESCR_UP, 0, 0)
TP_DOWNLOADING.Controls.Add(Me.TXT_DOWN_COMPLETE_SCRIPT, 0, 4)
TP_DOWNLOADING.Controls.Add(TP_MISSING_DATA, 0, 5)
TP_DOWNLOADING.Dock = System.Windows.Forms.DockStyle.Fill
TP_DOWNLOADING.Location = New System.Drawing.Point(0, 0)
TP_DOWNLOADING.Name = "TP_DOWNLOADING"
TP_DOWNLOADING.RowCount = 6
TP_DOWNLOADING.RowCount = 7
TP_DOWNLOADING.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_DOWNLOADING.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30.0!))
TP_DOWNLOADING.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30.0!))
TP_DOWNLOADING.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_DOWNLOADING.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_DOWNLOADING.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_DOWNLOADING.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_DOWNLOADING.Size = New System.Drawing.Size(576, 284)
TP_DOWNLOADING.TabIndex = 0
@@ -1012,6 +1059,136 @@
Me.TXT_DOWN_COMPLETE_SCRIPT.Size = New System.Drawing.Size(568, 22)
Me.TXT_DOWN_COMPLETE_SCRIPT.TabIndex = 4
'
'TP_MISSING_DATA
'
TP_MISSING_DATA.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
TP_MISSING_DATA.ColumnCount = 2
TP_MISSING_DATA.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_MISSING_DATA.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_MISSING_DATA.Controls.Add(Me.CH_ADD_MISSING_TO_LOG, 0, 0)
TP_MISSING_DATA.Controls.Add(Me.CH_ADD_MISSING_ERROS_TO_LOG, 1, 0)
TP_MISSING_DATA.Dock = System.Windows.Forms.DockStyle.Fill
TP_MISSING_DATA.Location = New System.Drawing.Point(1, 147)
TP_MISSING_DATA.Margin = New System.Windows.Forms.Padding(0)
TP_MISSING_DATA.Name = "TP_MISSING_DATA"
TP_MISSING_DATA.RowCount = 1
TP_MISSING_DATA.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MISSING_DATA.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 24.0!))
TP_MISSING_DATA.Size = New System.Drawing.Size(574, 25)
TP_MISSING_DATA.TabIndex = 5
'
'TAB_FEED
'
TAB_FEED.Controls.Add(TP_FEED)
TAB_FEED.Location = New System.Drawing.Point(4, 22)
TAB_FEED.Name = "TAB_FEED"
TAB_FEED.Size = New System.Drawing.Size(576, 284)
TAB_FEED.TabIndex = 7
TAB_FEED.Text = "Feed"
'
'TP_FEED
'
TP_FEED.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
TP_FEED.ColumnCount = 1
TP_FEED.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_FEED.Controls.Add(TP_FEED_IMG_COUNT, 0, 0)
TP_FEED.Controls.Add(Me.CH_FEED_ENDLESS, 0, 1)
TP_FEED.Controls.Add(Me.CH_FEED_ADD_SESSION, 0, 2)
TP_FEED.Controls.Add(Me.CH_FEED_ADD_DATE, 0, 3)
TP_FEED.Dock = System.Windows.Forms.DockStyle.Fill
TP_FEED.Location = New System.Drawing.Point(0, 0)
TP_FEED.Name = "TP_FEED"
TP_FEED.RowCount = 5
TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_FEED.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_FEED.Size = New System.Drawing.Size(576, 284)
TP_FEED.TabIndex = 0
'
'TP_FEED_IMG_COUNT
'
TP_FEED_IMG_COUNT.ColumnCount = 2
TP_FEED_IMG_COUNT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_FEED_IMG_COUNT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_FEED_IMG_COUNT.Controls.Add(Me.TXT_FEED_ROWS, 0, 0)
TP_FEED_IMG_COUNT.Controls.Add(Me.TXT_FEED_COLUMNS, 1, 0)
TP_FEED_IMG_COUNT.Dock = System.Windows.Forms.DockStyle.Fill
TP_FEED_IMG_COUNT.Location = New System.Drawing.Point(1, 1)
TP_FEED_IMG_COUNT.Margin = New System.Windows.Forms.Padding(0)
TP_FEED_IMG_COUNT.Name = "TP_FEED_IMG_COUNT"
TP_FEED_IMG_COUNT.RowCount = 1
TP_FEED_IMG_COUNT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_FEED_IMG_COUNT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_FEED_IMG_COUNT.Size = New System.Drawing.Size(574, 28)
TP_FEED_IMG_COUNT.TabIndex = 0
'
'TXT_FEED_ROWS
'
Me.TXT_FEED_ROWS.CaptionText = "Feed rows"
Me.TXT_FEED_ROWS.CaptionToolTipEnabled = True
Me.TXT_FEED_ROWS.CaptionToolTipText = "How many lines of images should be shown in the feed form"
Me.TXT_FEED_ROWS.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown
Me.TXT_FEED_ROWS.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_FEED_ROWS.Location = New System.Drawing.Point(3, 3)
Me.TXT_FEED_ROWS.Name = "TXT_FEED_ROWS"
Me.TXT_FEED_ROWS.NumberMaximum = New Decimal(New Integer() {50, 0, 0, 0})
Me.TXT_FEED_ROWS.NumberMinimum = New Decimal(New Integer() {1, 0, 0, 0})
Me.TXT_FEED_ROWS.Size = New System.Drawing.Size(281, 22)
Me.TXT_FEED_ROWS.TabIndex = 0
Me.TXT_FEED_ROWS.Text = "1"
Me.TXT_FEED_ROWS.TextBoxTextAlign = System.Windows.Forms.HorizontalAlignment.Center
'
'TXT_FEED_COLUMNS
'
Me.TXT_FEED_COLUMNS.CaptionText = "Feed columns"
Me.TXT_FEED_COLUMNS.CaptionToolTipEnabled = True
Me.TXT_FEED_COLUMNS.CaptionToolTipText = "How many columns of images should be shown in the feed form"
Me.TXT_FEED_COLUMNS.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown
Me.TXT_FEED_COLUMNS.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_FEED_COLUMNS.Location = New System.Drawing.Point(290, 3)
Me.TXT_FEED_COLUMNS.Name = "TXT_FEED_COLUMNS"
Me.TXT_FEED_COLUMNS.NumberMaximum = New Decimal(New Integer() {20, 0, 0, 0})
Me.TXT_FEED_COLUMNS.NumberMinimum = New Decimal(New Integer() {1, 0, 0, 0})
Me.TXT_FEED_COLUMNS.Size = New System.Drawing.Size(281, 22)
Me.TXT_FEED_COLUMNS.TabIndex = 1
Me.TXT_FEED_COLUMNS.Text = "1"
Me.TXT_FEED_COLUMNS.TextBoxTextAlign = System.Windows.Forms.HorizontalAlignment.Center
'
'CH_FEED_ENDLESS
'
Me.CH_FEED_ENDLESS.AutoSize = True
Me.CH_FEED_ENDLESS.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_FEED_ENDLESS.Location = New System.Drawing.Point(4, 33)
Me.CH_FEED_ENDLESS.Name = "CH_FEED_ENDLESS"
Me.CH_FEED_ENDLESS.Size = New System.Drawing.Size(568, 19)
Me.CH_FEED_ENDLESS.TabIndex = 1
Me.CH_FEED_ENDLESS.Text = "Endless feed"
Me.CH_FEED_ENDLESS.UseVisualStyleBackColor = True
'
'CH_FEED_ADD_SESSION
'
Me.CH_FEED_ADD_SESSION.AutoSize = True
Me.CH_FEED_ADD_SESSION.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_FEED_ADD_SESSION.Location = New System.Drawing.Point(4, 59)
Me.CH_FEED_ADD_SESSION.Name = "CH_FEED_ADD_SESSION"
Me.CH_FEED_ADD_SESSION.Size = New System.Drawing.Size(568, 19)
Me.CH_FEED_ADD_SESSION.TabIndex = 2
Me.CH_FEED_ADD_SESSION.Text = "Add the session number to the post title"
Me.CH_FEED_ADD_SESSION.UseVisualStyleBackColor = True
'
'CH_FEED_ADD_DATE
'
Me.CH_FEED_ADD_DATE.AutoSize = True
Me.CH_FEED_ADD_DATE.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_FEED_ADD_DATE.Location = New System.Drawing.Point(4, 85)
Me.CH_FEED_ADD_DATE.Name = "CH_FEED_ADD_DATE"
Me.CH_FEED_ADD_DATE.Size = New System.Drawing.Size(568, 19)
Me.CH_FEED_ADD_DATE.TabIndex = 3
Me.CH_FEED_ADD_DATE.Text = "Add the date to the post title"
Me.CH_FEED_ADD_DATE.UseVisualStyleBackColor = True
'
'TAB_MAIN
'
Me.TAB_MAIN.Controls.Add(TAB_BASIS)
@@ -1019,6 +1196,7 @@
Me.TAB_MAIN.Controls.Add(TAB_DEFAULTS)
Me.TAB_MAIN.Controls.Add(TAB_DOWN)
Me.TAB_MAIN.Controls.Add(TAB_DEFS_CHANNELS)
Me.TAB_MAIN.Controls.Add(TAB_FEED)
Me.TAB_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
Me.TAB_MAIN.Location = New System.Drawing.Point(0, 0)
Me.TAB_MAIN.Name = "TAB_MAIN"
@@ -1098,6 +1276,14 @@
TP_DOWNLOADING.PerformLayout()
CType(Me.TXT_SCRIPT, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_DOWN_COMPLETE_SCRIPT, System.ComponentModel.ISupportInitialize).EndInit()
TP_MISSING_DATA.ResumeLayout(False)
TP_MISSING_DATA.PerformLayout()
TAB_FEED.ResumeLayout(False)
TP_FEED.ResumeLayout(False)
TP_FEED.PerformLayout()
TP_FEED_IMG_COUNT.ResumeLayout(False)
CType(Me.TXT_FEED_ROWS, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_FEED_COLUMNS, System.ComponentModel.ISupportInitialize).EndInit()
Me.TAB_MAIN.ResumeLayout(False)
Me.CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
Me.CONTAINER_MAIN.ResumeLayout(False)
@@ -1150,5 +1336,12 @@
Private WithEvents CH_DOWN_OPEN_INFO_SUSPEND As CheckBox
Private WithEvents CH_DOWN_OPEN_PROGRESS_SUSPEND As CheckBox
Private WithEvents CH_DOWN_IMAGES_NATIVE As CheckBox
Private WithEvents CH_ADD_MISSING_TO_LOG As CheckBox
Private WithEvents CH_ADD_MISSING_ERROS_TO_LOG As CheckBox
Private WithEvents TXT_FEED_ROWS As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents TXT_FEED_COLUMNS As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents CH_FEED_ENDLESS As CheckBox
Private WithEvents CH_FEED_ADD_SESSION As CheckBox
Private WithEvents CH_FEED_ADD_DATE As CheckBox
End Class
End Namespace

View File

@@ -210,6 +210,16 @@
<value>This is a global setting for newly added users only.
This parameter specifies how the video will be stored in the users' download path.
If checked, videos will be stored in separate folder; otherwise, videos will be stored along with images.</value>
</data>
<data name="CH_ADD_MISSING_TO_LOG.ToolTip" xml:space="preserve">
<value>Add information about missing posts (that were not downloaded) to the log.
That means that text like "Missing posts exist" will be added to the log.
You can find more detailed information about the missing posts in the form that opens by right-clicking on the 'Info' button in the main window.</value>
</data>
<data name="CH_ADD_MISSING_ERROS_TO_LOG.ToolTip" xml:space="preserve">
<value>Add error information about missing posts (that were not downloaded) to the log.
That means that the error text about the not downloaded post will be added to the log.
You can find more detailed information about the missing posts in the form that opens by right-clicking on the 'Info' button in the main window.</value>
</data>
<metadata name="TP_CHANNELS_IMGS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
@@ -282,6 +292,18 @@ If checked, videos will be stored in separate folder; otherwise, videos will be
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<metadata name="TP_MISSING_DATA.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="TAB_FEED.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="TP_FEED.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="TP_FEED_IMG_COUNT.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAA8AAAAQAAEABAAwOgAA9gAAADAwEAABAAQAaAYAACg7AAAgIBAAAQAEAOgCAACQQQAAGBgQAAEA

View File

@@ -8,24 +8,25 @@
' but WITHOUT ANY WARRANTY
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Controls.Base
Imports PersonalUtilities.Forms.Toolbars
Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons
Namespace Editors
Friend Class GlobalSettingsForm : Implements IOkCancelToolbar
Private ReadOnly MyDefs As DefaultFormOptions
Friend Class GlobalSettingsForm
Private WithEvents MyDefs As DefaultFormOptions
Friend Property FeedParametersChanged As Boolean = False
Friend Sub New()
InitializeComponent()
MyDefs = New DefaultFormOptions
MyDefs = New DefaultFormOptions(Me, Settings.Design)
End Sub
Private Sub GlobalSettingsForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
With MyDefs
.MyViewInitialize(Me, Settings.Design, True)
.MyViewInitialize(True)
.AddOkCancelToolbar()
With Settings
'Basis
TXT_GLOBAL_PATH.Text = .GlobalPath.Value
TXT_IMAGE_LARGE.Value = .MaxLargeImageHeigh.Value
TXT_IMAGE_SMALL.Value = .MaxSmallImageHeigh.Value
TXT_IMAGE_LARGE.Value = .MaxLargeImageHeight.Value
TXT_IMAGE_SMALL.Value = .MaxSmallImageHeight.Value
TXT_COLLECTIONS_PATH.Text = .CollectionsPath
TXT_MAX_JOBS_USERS.Value = .MaxUsersJobsCount.Value
TXT_MAX_JOBS_CHANNELS.Value = .ChannelsMaxJobsCount.Value
@@ -59,10 +60,12 @@ Namespace Editors
TXT_SCRIPT.Text = .ScriptData.Value
TXT_DOWN_COMPLETE_SCRIPT.Text = .DownloadsCompleteCommand
TXT_DOWN_COMPLETE_SCRIPT.Checked = .DownloadsCompleteCommand.Attribute
CH_ADD_MISSING_TO_LOG.Checked = .AddMissingToLog
CH_ADD_MISSING_ERROS_TO_LOG.Checked = .AddMissingErrorsToLog
'Downloading: file names
CH_FILE_NAME_CHANGE.Checked = .FileReplaceNameByDate Or .FileAddDateToFileName Or .FileAddTimeToFileName
OPT_FILE_NAME_REPLACE.Checked = .FileReplaceNameByDate
OPT_FILE_NAME_ADD_DATE.Checked = Not .FileReplaceNameByDate
CH_FILE_NAME_CHANGE.Checked = Not .FileReplaceNameByDate.Value = FileNameReplaceMode.None
OPT_FILE_NAME_REPLACE.Checked = .FileReplaceNameByDate.Value = FileNameReplaceMode.Replace
OPT_FILE_NAME_ADD_DATE.Checked = .FileReplaceNameByDate.Value = FileNameReplaceMode.Add
CH_FILE_DATE.Checked = .FileAddDateToFileName
CH_FILE_TIME.Checked = .FileAddTimeToFileName
OPT_FILE_DATE_START.Checked = Not .FileDateTimePositionEnd
@@ -76,21 +79,27 @@ Namespace Editors
CH_COPY_CHANNEL_USER_IMAGE_ALL.Checked = .ChannelsAddUserImagesFromAllChannels
CH_COPY_CHANNEL_USER_IMAGE_ALL.Enabled = CH_COPY_CHANNEL_USER_IMAGE.Checked
CH_CHANNELS_USERS_TEMP.Checked = .ChannelsDefaultTemporary
'Feed
TXT_FEED_ROWS.Value = .FeedDataRows.Value
TXT_FEED_COLUMNS.Value = .FeedDataColumns.Value
CH_FEED_ENDLESS.Checked = .FeedEndless
CH_FEED_ADD_SESSION.Checked = .FeedAddSessionToCaption
CH_FEED_ADD_DATE.Checked = .FeedAddDateToCaption
End With
.MyFieldsChecker = New FieldsChecker
With DirectCast(.MyFieldsChecker, FieldsChecker)
With .MyFieldsCheckerE
.AddControl(Of String)(TXT_GLOBAL_PATH, TXT_GLOBAL_PATH.CaptionText)
.AddControl(Of String)(TXT_COLLECTIONS_PATH, TXT_COLLECTIONS_PATH.CaptionText)
.EndLoaderOperations()
End With
.EndLoaderOperations()
ChangeFileNameChangersEnabling()
.EndLoaderOperations()
End With
Catch ex As Exception
MyDefs.InvokeLoaderError(ex)
End Try
End Sub
Private Sub OK() Implements IOkCancelToolbar.OK
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
If MyDefs.MyFieldsChecker.AllParamsOK Then
With Settings
Dim a As Func(Of String, Object, Integer) =
@@ -124,8 +133,8 @@ Namespace Editors
'Basis
.GlobalPath.Value = TXT_GLOBAL_PATH.Text
.MaxLargeImageHeigh.Value = CInt(TXT_IMAGE_LARGE.Value)
.MaxSmallImageHeigh.Value = CInt(TXT_IMAGE_SMALL.Value)
.MaxLargeImageHeight.Value = CInt(TXT_IMAGE_LARGE.Value)
.MaxSmallImageHeight.Value = CInt(TXT_IMAGE_SMALL.Value)
.CollectionsPath.Value = TXT_COLLECTIONS_PATH.Text
.MaxUsersJobsCount.Value = CInt(TXT_MAX_JOBS_USERS.Value)
.ChannelsMaxJobsCount.Value = TXT_MAX_JOBS_CHANNELS.Value
@@ -159,16 +168,18 @@ Namespace Editors
.ScriptData.Attribute.Value = TXT_SCRIPT.Checked
.DownloadsCompleteCommand.Value = TXT_DOWN_COMPLETE_SCRIPT.Text
.DownloadsCompleteCommand.Attribute.Value = TXT_DOWN_COMPLETE_SCRIPT.Checked
.AddMissingToLog.Value = CH_ADD_MISSING_TO_LOG.Checked
.AddMissingErrorsToLog.Value = CH_ADD_MISSING_ERROS_TO_LOG.Checked
'Downloading: file names
If CH_FILE_NAME_CHANGE.Checked Then
.FileReplaceNameByDate.Value = OPT_FILE_NAME_REPLACE.Checked
.FileReplaceNameByDate.Value = If(OPT_FILE_NAME_REPLACE.Checked, FileNameReplaceMode.Replace, FileNameReplaceMode.Add)
.FileAddDateToFileName.Value = CH_FILE_DATE.Checked
.FileAddTimeToFileName.Value = CH_FILE_TIME.Checked
.FileDateTimePositionEnd.Value = OPT_FILE_DATE_END.Checked
Else
.FileAddDateToFileName.Value = False
.FileAddTimeToFileName.Value = False
.FileReplaceNameByDate.Value = False
.FileReplaceNameByDate.Value = FileNameReplaceMode.None
End If
'Channels
.ChannelsImagesRows.Value = CInt(TXT_CHANNELS_ROWS.Value)
@@ -178,26 +189,30 @@ Namespace Editors
.FromChannelCopyImageToUser.Value = CH_COPY_CHANNEL_USER_IMAGE.Checked
.ChannelsAddUserImagesFromAllChannels.Value = CH_COPY_CHANNEL_USER_IMAGE_ALL.Checked
.ChannelsDefaultTemporary.Value = CH_CHANNELS_USERS_TEMP.Checked
'Feed
.FeedDataRows.Value = CInt(TXT_FEED_ROWS.Value)
.FeedDataColumns.Value = CInt(TXT_FEED_COLUMNS.Value)
.FeedEndless.Value = CH_FEED_ENDLESS.Checked
.FeedAddSessionToCaption.Value = CH_FEED_ADD_SESSION.Checked
.FeedAddDateToCaption.Value = CH_FEED_ADD_DATE.Checked
FeedParametersChanged = .FeedDataRows.ChangesDetected Or .FeedDataColumns.ChangesDetected Or .FeedEndless.ChangesDetected
.EndUpdate()
End With
MyDefs.CloseForm()
End If
End Sub
Private Sub Cancel() Implements IOkCancelToolbar.Cancel
MyDefs.CloseForm(DialogResult.Cancel)
End Sub
Private Sub TXT_GLOBAL_PATH_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_GLOBAL_PATH.ActionOnButtonClick
If Sender.DefaultButton = ActionButton.DefaultButtons.Open Then
Private Sub TXT_GLOBAL_PATH_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles TXT_GLOBAL_PATH.ActionOnButtonClick
If Sender.DefaultButton = ADB.Open Then
Dim f As SFile = SFile.SelectPath(Settings.GlobalPath.Value)
If Not f.IsEmptyString Then TXT_GLOBAL_PATH.Text = f
End If
End Sub
Private Sub TXT_MAX_JOBS_USERS_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_MAX_JOBS_USERS.ActionOnButtonClick
If Sender.DefaultButton = ActionButton.DefaultButtons.Refresh Then TXT_MAX_JOBS_USERS.Value = SettingsCLS.DefaultMaxDownloadingTasks
Private Sub TXT_MAX_JOBS_USERS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles TXT_MAX_JOBS_USERS.ActionOnButtonClick
If Sender.DefaultButton = ADB.Refresh Then TXT_MAX_JOBS_USERS.Value = SettingsCLS.DefaultMaxDownloadingTasks
End Sub
Private Sub TXT_MAX_JOBS_CHANNELS_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_MAX_JOBS_CHANNELS.ActionOnButtonClick
If Sender.DefaultButton = ActionButton.DefaultButtons.Refresh Then TXT_MAX_JOBS_CHANNELS.Value = SettingsCLS.DefaultMaxDownloadingTasks
Private Sub TXT_MAX_JOBS_CHANNELS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles TXT_MAX_JOBS_CHANNELS.ActionOnButtonClick
If Sender.DefaultButton = ADB.Refresh Then TXT_MAX_JOBS_CHANNELS.Value = SettingsCLS.DefaultMaxDownloadingTasks
End Sub
Private Sub CH_FILE_NAME_CHANGE_CheckedChanged(sender As Object, e As EventArgs) Handles CH_FILE_NAME_CHANGE.CheckedChanged
ChangeFileNameChangersEnabling()
@@ -217,11 +232,12 @@ Namespace Editors
Dim b As Boolean = CH_FILE_NAME_CHANGE.Checked
OPT_FILE_NAME_REPLACE.Enabled = b
OPT_FILE_NAME_ADD_DATE.Enabled = b
If Not OPT_FILE_NAME_REPLACE.Checked And Not OPT_FILE_NAME_ADD_DATE.Checked Then OPT_FILE_NAME_REPLACE.Checked = True
CH_FILE_DATE.Enabled = b
CH_FILE_TIME.Enabled = b
ChangePositionControlsEnabling()
End Sub
Private Sub TXT_SCRIPT_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_SCRIPT.ActionOnButtonClick
Private Sub TXT_SCRIPT_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles TXT_SCRIPT.ActionOnButtonClick
SettingsCLS.ScriptTextBoxButtonClick(TXT_SCRIPT, Sender)
End Sub
Private Sub CH_COPY_CHANNEL_USER_IMAGE_CheckedChanged(sender As Object, e As EventArgs) Handles CH_COPY_CHANNEL_USER_IMAGE.CheckedChanged

Some files were not shown because too many files have changed in this diff Show More