Compare commits

..

11 Commits

Author SHA1 Message Date
Andy
aef4ce1c8f 2024.6.10.0
YT
YouTubeSettings: add 'VideoPlaylist_AddExtractedMP3' property
MediaItem: improve visualization of height and bitrate
YouTubeMediaContainerBase: fix bugs on default post-processing formats; add 'HeightBase' and 'BitrateBase' properties; add extracted MP3 to playlist
VideoListForm: add 'UpdateLogButton' handlers

SCrawler
Feed: add settings to show/hide site name and file type from media title; add move/copy files of a loaded feed/session to another location; add the ability to reset current session
DownloadFeedForm: when moving saved posts files without replacing the profile, some data is lost
FeedVideo: add double-click handler to open video in external player
API.Instagram: update settings
2024-06-10 08:40:40 +03:00
Andy
93ea2a55ac 2024.6.6.0
YT
VideoOptionsForm: file path is cleared when the cancel button is clicked (browse button); remove the context menu when the right clicking on browse button; add 'ButtonRC' class

SCrawler
API.OnlyFans: add check config to the SiteSettings; update config; add 'Keydb_Api' property; reset 'LastDateUpdated' when rules change; add support 'prefix/suffix' and 'start/end' to support other rules formats
DownloadFeedForm: update 'BTT_CURR_SESSION_SET_Click' function
TDownloader: update 'FilesLoadLastSession' function
2024-06-06 05:49:50 +03:00
Andy
2ae8c3acfc 2024.6.4.0
API.Twitter: add communities downloading, change post opening URL
Feed: add the ability to select one of the download sessions and set it as the current session
2024-06-04 03:28:05 +03:00
Andy
53dcb3e2c6 2024.6.2.0
YT
Add 'FileAddDateToFileName', 'FileAddDateToFileName_VideoForm' and 'FileAddDateToFileName_VideoList' properties
Update 'YouTubeMediaContainerBase', 'VideoOptionsForm' and 'MediaItem' (new options)

SCrawler
API.Instagram: update settings values
API.Reddit: fix 'ReparseMissing' function (remove bearer token)
2024-06-02 01:19:41 +03:00
Andy
ca384e54d6 2024.5.29.0
YT
Trim urls to get rid of 'cr' & 'lf'
Get the correct 'music' url for 'url' files

SCrawler
Remove the no longer needed 'MainFrameObj.UpdateLogButton' from the classes
ProfileSaved: swap the 'ReadyToDownload' and 'Available' checks; remove the 'DownloadStarted' and 'DownloadDone' calls because they are called in the root function
API.Instagram: improve availability checking
API.Twitter: fix deleting user directory when redownloading missing posts
AutoDownloader: improve statuses; move the check thread to the scheduler; add highlighting of scheduler plans (working, stopped, pending, etc.); replace 'ListBox' with 'ListView'; highlight undownloaded plans in gray
2024-05-29 02:45:37 +03:00
Andy
5a1b5c828a 2024.5.25.0
Move files to another directory
2024-05-25 10:06:50 +03:00
Andy
22c59b41f0 2024.5.19.0
YT
YouTubeSettings: add 'CreateDescriptionFiles_AddUploadDate' and 'CreateDescriptionFiles_CreateWithNoDescription' properties
YouTubeMediaContainerBase: add upload date to description

SCrawler
API.YouTube: 'YTSettings_Internal' is not saved when changed
2024-05-19 22:29:16 +03:00
Andy
444b3521eb 2024.5.18.0
YT
YouTubeSettings: add 'DefaultVideoHighlightFPS_H' and 'DefaultVideoHighlightFPS_L' properties
VideoOption: highlight frame rates higher/lower than this value

SCrawler
SiteSettingsBase: add 'UserAgentDefault' property
API.Facebook, API.Instagram, API.Mastodon, API.OnlyFans, API.ThreadsNet, API.Twitter: add categories
API.Instagram.SiteSettings: add 'DownDetector' validation; remove wrong header
API.Instagram.UserData: fix incorrect definition of pinned posts; add 'DefaultParser_Pinned' and 'DefaultParser_SkipPost' func (for Threads)
API.Threads: fix pinned posts processing
API.Reddit: add 429 bypass; change the naming method of video files (hosted on Reddit) to the 'YYYYMMDD_HHMMSS' pattern; add 'UserAgent' property
API.RedGifs: hide credential controls
API.Twitter: add 'Likes' downloading; change domain from twitter.com to x.com;
API.OnlyFans: set '_AllowUserAgentUpdate' to false
SiteEditorForm: group options by category
GroupListForm: enable 'OK' if it is filter
DownloadGroup: add 'FilterShowAllUsers' property
PropertyValueHost: add 'Category' property
MainFrame: the 'ALL' filter isn't unchecked when loading a filter from a saved one
Update user paths when global paths change
Scheduler: add the ability to clone the scheduler

PluginProvider
PropertyOption attribute: set category name when `IsAuth = True`
ISiteSettings: add 'UserAgentDefault' property
2024-05-18 01:17:29 +03:00
Andy
ec2266f1bf 2024.5.4.0
YT
remove dots from the end of the file name; add a setting to remove specific characters

SCrawler
API.Instagram: simplify the 'Connection closed' error
API.Reddit: update token refresh request; add 'BearerTokenUseCurl' hidden property
API.Threads: fix frong header name ('dnt'); update 'UpdateCredentials' function
AutoDownloader: change 'IndexOutOfRangeException' to 'Exception' in the 'Download' function
TDownloader: fix 'FilesUpdatePendingUsers' function (freeze)
UserSearchForm: add 'FriendlyName' to search results
2024-05-04 07:04:26 +03:00
Andy
7d9255c916 2024.4.26.0
Add 'CookieValueExtractorAttribute' and the ability to immediately populate fields with values that can be extracted from cookies
Feed: add the ability to load the last session of the current day (if it exists) as the current session after restarting SCrawler
UserSearchForm: include friendly name matches in search result
API.Xhamster: saved posts aren't downloading
2024-04-26 17:18:31 +03:00
Andy
5b5857e31d 2024.4.14.0
Delete old notes and comments
API.Facebook: add app-id extraction from page; remove app-id from site requirements; update tokens parsing; update tokens regex
API.Instagram: add default function to parse tokens
2024-04-14 07:44:05 +03:00
110 changed files with 3399 additions and 881 deletions

View File

@@ -1,3 +1,122 @@
# 2024.6.10.0
*2024-06-10*
- Added
- YouTube (standalone app): add option to add extracted MP3 to playlist (`Settings` - `Defaults Video` - `Add extracted MP3 to playlist`)
- Feed
- settings to show/hide site name and file type from media title
- ability to move/copy files of a loaded feed/session to another location
- ability to reset current session
- Fixed
- Minor bugs
# 2024.6.6.0
*2024-06-06*
**ATTENTION!**
1. **To support downloading of DRM protected videos (OnlyFans), please update OF-Scraper to version [3.10](https://github.com/datawhores/OF-Scraper/releases/tag/3.10) (download `zip`, not `exe`).**
2. **If there is a `OFScraperConfigPattern.json` file in the SCrawler settings folder, replace the text of the file with [this text](https://github.com/AAndyProgram/SCrawler/blob/main/SCrawler/API/OnlyFans/OFScraperConfigPattern.json).**
3. **Set the value to `Dynamic rules` (in the site settings) = `https://raw.githubusercontent.com/Growik/onlyfans-dynamic-rules/main/rules.json`.**
- Added
- OnlyFans: new OF-Scraper option (`keydb_api`)
- Minor improvements
- Fixed
- OnlyFans: **data is not downloading**
- Minor bugs
# 2024.6.4.0
*2024-06-04*
**If you were using the [`yt-dlp-TTUser`](https://github.com/bashonly/yt-dlp-TTUser) plugin, you should remove it because this plugin was added to yt-dlp itself! Read more [here](https://github.com/AAndyProgram/SCrawler/wiki/Settings#tiktok-requirements).**
- Added
- Added highlighting of scheduler plans (working, stopped, pending, etc.)
- YouTube (standalone app): add option to add the video upload date before/after the file name (`Settings` - `Defaults` - `Add date to file name`)
- Twitter: **`Communities` downloading**
- Feed: ability to select one of the download sessions and set it as the current session
- Minor improvements
- Updated
- yt-dlp up to version **2024.05.27**
- gallery-dl up to version **1.27.0**
- Fixed
- Twitter: deleting user directory when redownloading missing posts
- Minor bugs
# 2024.5.19.0
*2024-05-19*
- Added
- YouTube (standalone app): add upload date to description (request #192) (`Settings` - `Info` - `Create description files: add upload date`, `Create description files: create without description`).
- Fixed
- YouTube (SCrawler): advanced settings are not saved when changed
# 2024.5.18.0
*2024-05-18*
- Added
- YouTube (standalone app): highlight frame rates higher/lower than this value (`Settings` - `Defaults Video` - `Highlight FPS (higher/lower)`).
- Sites
- Instagram: 'DownDetector' support to determine if the site is accessible
- Reddit: change the naming method of video files (hosted on Reddit) to the `YYYYMMDD_HHMMSS` pattern
- Twitter
- `Likes` downloading *(user settings)*
- **changed domain from twitter.com to x.com**
- Site settings: group options by category
- Minor improvements
- PluginProvider
- `PropertyOption` attribute: set category name when `IsAuth = True`
- `ISiteSettings`: added `UserAgentDefault` property
- Updated
- gallery-dl up to version **1.27.0-dev**
- Fixed
- Sites
- Instagram: incorrect definition of pinned posts
- Threads: new posts are no longer downloaded from profiles with pinned posts
- Reddit: bypass error 429 for saved posts
- Twitter: **data is not downloading due to domain change from twitter.com to x.com**
- Minor bugs
# 2024.5.4.0
*2024-05-04*
- Added
- YouTube (standalone app): setting to remove specific characters (`Defaults` - `Remove characters`)
- Instagram: simplify the `Connection closed` error
- Users search: add `Friendly name` to search results
- Fixed
- YouTube (standalone app): incorrect download processing when the file name ends with a dot (Issue #188)
- The program is freezes when editing users in some cases
- Sites
- Reddit: token update error
- Threads: unable to obtain credentials (`ID`)
# 2024.4.26.0
*2024-04-26*
- Added
- Site settings: the values that can be extracted from cookies immediately populate fields
- Feed: ability to load the last session of the current day (if it exists) as the current session after restarting SCrawler
- Users search: include friendly name matches in search result
- Updated
- gallery-dl up to version **1.26.9**
- Fixed
- xHamster: **saved posts aren't downloading**
# 2024.4.14.0
*2024-04-14*
- Fixed
- Facebook: can't get tokens
# 2024.4.13.0 # 2024.4.13.0
*2024-04-13* *2024-04-13*

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -1,5 +1,5 @@
<!-- # :rainbow_flag: Happy LGBT Pride Month :tada: # 🏳️‍🌈 Happy LGBT Pride Month 🎉
-->
# 🏳️‍🌈 Social networks crawler 🏳️‍🌈 # 🏳️‍🌈 Social networks crawler 🏳️‍🌈
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/AAndyProgram/SCrawler)](https://github.com/AAndyProgram/SCrawler/releases/latest) [![GitHub release (latest by date)](https://img.shields.io/github/v/release/AAndyProgram/SCrawler)](https://github.com/AAndyProgram/SCrawler/releases/latest)
@@ -37,8 +37,8 @@ A program to download photo and video from [any site](#supported-sites) (e.g. Yo
- YouTube videos, shorts, community feeds, users, artists, playlists, music, tracks; - YouTube videos, shorts, community feeds, users, artists, playlists, music, tracks;
- Reddit images, galleries of images, videos, saved posts; - Reddit images, galleries of images, videos, saved posts;
- Redgifs videos (https://www.redgifs.com/); - Redgifs videos (https://www.redgifs.com/);
- Twitter images and videos, saved (bookmarked) posts; - Twitter images and videos, saved (bookmarked) posts, likes, communities;
- OnlyFans images and videos, saved (bookmarked) posts; - OnlyFans images and videos, saved (bookmarked) posts, stories;
- JustForFans images and videos, saved (bookmarked) posts; - JustForFans images and videos, saved (bookmarked) posts;
- Mastodon images and videos, saved (bookmarked) posts; - Mastodon images and videos, saved (bookmarked) posts;
- Instagram images and videos, tagged posts, stories, saved posts; - Instagram images and videos, tagged posts, stories, saved posts;
@@ -79,11 +79,11 @@ A program to download photo and video from [any site](#supported-sites) (e.g. Yo
- **Reddit** - **Reddit**
- **Twitter** - **Twitter**
- **OnlyFans** *(partial support)*[^1] - **OnlyFans** *(partial support)*[^1]
- **Mastodon**
- **Instagram** - **Instagram**
- **Threads** - **Threads**
- **Facebook** - **Facebook**
- JustForFans *(partial support)*[^1] - JustForFans *(partial support)*[^1]
- Mastodon *(out of support)*
- TikTok - TikTok
- RedGifs - RedGifs
- Pinterest - Pinterest

View File

@@ -36,8 +36,22 @@ Namespace Plugin.Attributes
Public Property IsInformationLabel As Boolean = False Public Property IsInformationLabel As Boolean = False
''' <summary>Label text alignment.<br/>Default: <see cref="Drawing.ContentAlignment.TopCenter"/></summary> ''' <summary>Label text alignment.<br/>Default: <see cref="Drawing.ContentAlignment.TopCenter"/></summary>
Public Property LabelTextAlign As Drawing.ContentAlignment = Drawing.ContentAlignment.TopCenter Public Property LabelTextAlign As Drawing.ContentAlignment = Drawing.ContentAlignment.TopCenter
Private _IsAuth As Boolean = False
''' <summary>This is an authorization property</summary> ''' <summary>This is an authorization property</summary>
Public Property IsAuth As Boolean = False Public Property IsAuth As Boolean
Get
Return _IsAuth
End Get
Set(ByVal _IsAuth As Boolean)
Me._IsAuth = _IsAuth
If _IsAuth And String.IsNullOrEmpty(Category) Then
Category = CategoryAuth
ElseIf Not _IsAuth AndAlso Not String.IsNullOrEmpty(Category) AndAlso Category = CategoryAuth Then
Category = String.Empty
End If
End Set
End Property
Public Const CategoryAuth As String = "Authorization"
Public Property Category As String = Nothing Public Property Category As String = Nothing
Public Property InheritanceName As String = Nothing Public Property InheritanceName As String = Nothing
''' <summary>Initialize a new property option attribute</summary> ''' <summary>Initialize a new property option attribute</summary>

View File

@@ -19,6 +19,7 @@ Namespace Plugin
ReadOnly Property Site As String ReadOnly Property Site As String
Property CMDEncoding As String Property CMDEncoding As String
Property EnvironmentPrograms As IEnumerable(Of String) Property EnvironmentPrograms As IEnumerable(Of String)
Property UserAgentDefault As String
Sub EnvironmentProgramsUpdated() Sub EnvironmentProgramsUpdated()
Property AccountName As String Property AccountName As String
Property Temporary As Boolean Property Temporary As Boolean

View File

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

View File

@@ -78,6 +78,12 @@ Namespace API.YouTube.Base
https = 1 https = 1
m3u8 = 2 m3u8 = 2
End Enum End Enum
<Editor(GetType(EnumDropDownEditor), GetType(UITypeEditor))>
Public Enum FileDateMode As Integer
None = 0
Before = 1
After = 2
End Enum
Public Structure MediaObject : Implements IIndexable, IComparable(Of MediaObject) Public Structure MediaObject : Implements IIndexable, IComparable(Of MediaObject)
Public Type As Plugin.UserMediaTypes Public Type As Plugin.UserMediaTypes
Public ID As String Public ID As String

View File

@@ -22,6 +22,7 @@ Namespace API.YouTube.Base
End Sub End Sub
Public Shared Function StandardizeURL(ByVal URL As String) As String Public Shared Function StandardizeURL(ByVal URL As String) As String
Try Try
URL = URL.StringTrim
Dim isMusic As Boolean = False, isShorts As Boolean = False Dim isMusic As Boolean = False, isShorts As Boolean = False
If Info_GetUrlType(URL, isMusic, isShorts) = YouTubeMediaType.Single Then If Info_GetUrlType(URL, isMusic, isShorts) = YouTubeMediaType.Single Then
If Not isMusic And Not isShorts Then If Not isMusic And Not isShorts Then
@@ -45,6 +46,7 @@ Namespace API.YouTube.Base
End Function End Function
Public Shared Function StandardizeURL_Channel(ByVal URL As String, Optional ByVal Process As Boolean = True) As String Public Shared Function StandardizeURL_Channel(ByVal URL As String, Optional ByVal Process As Boolean = True) As String
Try Try
URL = URL.StringTrim
Dim ct As YouTubeChannelTab = YouTubeChannelTab.All Dim ct As YouTubeChannelTab = YouTubeChannelTab.All
Dim isMusic As Boolean = False Dim isMusic As Boolean = False
If Process AndAlso Info_GetUrlType(URL, isMusic,,,, ct) = YouTubeMediaType.Channel AndAlso Not isMusic Then If Process AndAlso Info_GetUrlType(URL, isMusic,,,, ct) = YouTubeMediaType.Channel AndAlso Not isMusic Then
@@ -72,6 +74,7 @@ Namespace API.YouTube.Base
Public Shared Function Info_GetUrlType(ByVal URL As String, Optional ByRef IsMusic As Boolean = False, Optional ByRef IsShorts As Boolean = False, Public Shared Function Info_GetUrlType(ByVal URL As String, Optional ByRef IsMusic As Boolean = False, Optional ByRef IsShorts As Boolean = False,
Optional ByRef IsChannelUser As Boolean = False, Optional ByRef Id As String = Nothing, Optional ByRef IsChannelUser As Boolean = False, Optional ByRef Id As String = Nothing,
Optional ByRef ChannelOptions As YouTubeChannelTab = YouTubeChannelTab.All) As YouTubeMediaType Optional ByRef ChannelOptions As YouTubeChannelTab = YouTubeChannelTab.All) As YouTubeMediaType
URL = URL.StringTrim
If Not URL.IsEmptyString Then If Not URL.IsEmptyString Then
IsMusic = URL.Contains("music.youtube.com") IsMusic = URL.Contains("music.youtube.com")
IsChannelUser = False IsChannelUser = False
@@ -118,6 +121,7 @@ Namespace API.YouTube.Base
Optional ByVal Token As Threading.CancellationToken = Nothing, Optional ByVal Progress As IMyProgress = Nothing, Optional ByVal Token As Threading.CancellationToken = Nothing, Optional ByVal Progress As IMyProgress = Nothing,
Optional ByVal DateAfter As Date? = Nothing, Optional ByVal DateBefore As Date? = Nothing, Optional ByVal DateAfter As Date? = Nothing, Optional ByVal DateBefore As Date? = Nothing,
Optional ByVal ChannelOption As YouTubeChannelTab? = Nothing, Optional ByVal UrlAsIs As Boolean = False) As IYouTubeMediaContainer Optional ByVal ChannelOption As YouTubeChannelTab? = Nothing, Optional ByVal UrlAsIs As Boolean = False) As IYouTubeMediaContainer
URL = URL.StringTrim
If URL.IsEmptyString Then Throw New ArgumentNullException("URL", "URL cannot be null") If URL.IsEmptyString Then Throw New ArgumentNullException("URL", "URL cannot be null")
If Not MyYouTubeSettings.YTDLP.Value.Exists Then Throw New IO.FileNotFoundException("Path to 'yt-dlp.exe' not set or program not found at destination", MyYouTubeSettings.YTDLP.Value.ToString) If Not MyYouTubeSettings.YTDLP.Value.Exists Then Throw New IO.FileNotFoundException("Path to 'yt-dlp.exe' not set or program not found at destination", MyYouTubeSettings.YTDLP.Value.ToString)
Dim urlOrig$ = URL Dim urlOrig$ = URL
@@ -162,7 +166,7 @@ Namespace API.YouTube.Base
If result Then If result Then
container.Parse(Nothing, _CachePathDefault, isMusic, Token, Progress) container.Parse(Nothing, _CachePathDefault, isMusic, Token, Progress)
If Not container.HasError Then container.URL = URL : container.IsShorts = isShorts : Return container If Not container.HasError Then container.URL = URL.ToMusicUrl(isMusic) : container.IsShorts = isShorts : Return container
End If End If
container.Dispose() container.Dispose()
End If End If

View File

@@ -162,6 +162,12 @@ Namespace API.YouTube.Base
<Browsable(True), GridVisible, XMLVN({"Info"}), Category("Info"), DisplayName("Create description files"), <Browsable(True), GridVisible, XMLVN({"Info"}), Category("Info"), DisplayName("Create description files"),
Description("Create video description files. Default: false.")> Description("Create video description files. Default: false.")>
Public ReadOnly Property CreateDescriptionFiles As XMLValue(Of Boolean) Public ReadOnly Property CreateDescriptionFiles As XMLValue(Of Boolean)
<Browsable(True), GridVisible, XMLVN({"Info"}, True), Category("Info"), DisplayName("Create description files: add upload date"),
Description("Add the upload date to the top of the description file. Default: true.")>
Public ReadOnly Property CreateDescriptionFiles_AddUploadDate As XMLValue(Of Boolean)
<Browsable(True), GridVisible, XMLVN({"Info"}, True), Category("Info"), DisplayName("Create description files: create without description"),
Description("Create a description file with the upload date, even if the description does not exist. Default: true.")>
Public ReadOnly Property CreateDescriptionFiles_CreateWithNoDescription As XMLValue(Of Boolean)
<Browsable(True), GridVisible, XMLVN({"Info"}, True), Category("Info"), DisplayName("Create thumbnail files (video)"), <Browsable(True), GridVisible, XMLVN({"Info"}, True), Category("Info"), DisplayName("Create thumbnail files (video)"),
Description("Create video thumbnail files. Default: true.")> Description("Create video thumbnail files. Default: true.")>
Public ReadOnly Property CreateThumbnails_Video As XMLValue(Of Boolean) Public ReadOnly Property CreateThumbnails_Video As XMLValue(Of Boolean)
@@ -243,6 +249,18 @@ Namespace API.YouTube.Base
<Browsable(True), GridVisible(False), XMLVN({"Defaults"}), Category("Defaults"), DisplayName("Program description"), <Browsable(True), GridVisible(False), XMLVN({"Defaults"}), Category("Defaults"), DisplayName("Program description"),
Description("Add some additional info to the program info if you need")> Description("Add some additional info to the program info if you need")>
Friend ReadOnly Property ProgramDescription As XMLValue(Of String) Friend ReadOnly Property ProgramDescription As XMLValue(Of String)
<Browsable(True), GridVisible, XMLVN({"Defaults"}, "%"""), Category("Defaults"), DisplayName("Remove characters"),
Description("Remove specific characters from a file name")>
Public ReadOnly Property FileRemoveCharacters As XMLValue(Of String)
<Browsable(True), GridVisible, XMLVN({"Defaults"}, FileDateMode.None), Category("Defaults"), DisplayName("Add date to file name"),
Description("Add the video upload date before/after the file name")>
Public ReadOnly Property FileAddDateToFileName As XMLValue(Of FileDateMode)
<Browsable(True), GridVisible, XMLVN({"Defaults"}), Category("Defaults"), DisplayName("Add date to title: video form"),
Description("Add video upload date before video title (visual only) in the video form")>
Public ReadOnly Property FileAddDateToFileName_VideoForm As XMLValue(Of Boolean)
<Browsable(True), GridVisible, XMLVN({"Defaults"}), Category("Defaults"), DisplayName("Add date to title: video list"),
Description("Add video upload date before video title (visual only) in the video list")>
Public ReadOnly Property FileAddDateToFileName_VideoList As XMLValue(Of Boolean)
#End Region #End Region
#Region "Defaults ChannelsDownload" #Region "Defaults ChannelsDownload"
<Browsable(True), GridVisible, XMLVN({"Defaults", "Channels"}), Category("Defaults"), DisplayName("Default download tabs for channels"), <Browsable(True), GridVisible, XMLVN({"Defaults", "Channels"}), Category("Defaults"), DisplayName("Default download tabs for channels"),
@@ -358,6 +376,15 @@ Namespace API.YouTube.Base
Throw New NotImplementedException("'GetFormat' is not available in 'FpsFormatProvider'") Throw New NotImplementedException("'GetFormat' is not available in 'FpsFormatProvider'")
End Function End Function
End Class End Class
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, 30), Category("Defaults Video"), DisplayName("Highlight FPS (higher)"),
Description("Highlight frame rates higher than this value." & vbCr & "Default: 30" & vbCr & "-1 to disable")>
Public ReadOnly Property DefaultVideoHighlightFPS_H As XMLValue(Of Integer)
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, -1), Category("Defaults Video"), DisplayName("Highlight FPS (lower)"),
Description("Highlight frame rates lower than this value." & vbCr & "Default: -1" & vbCr & "-1 to disable")>
Public ReadOnly Property DefaultVideoHighlightFPS_L As XMLValue(Of Integer)
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}), Category("Defaults Video"), DisplayName("Add extracted MP3 to playlist"),
Description("If you also extract MP3 when download the video, add the extracted MP3 to the playlist. Default: false.")>
Public ReadOnly Property VideoPlaylist_AddExtractedMP3 As XMLValue(Of Boolean)
#End Region #End Region
#Region "Defaults Audio" #Region "Defaults Audio"
<Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, "AAC"), Category("Defaults Audio"), DisplayName("Default codec"), <Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, "AAC"), Category("Defaults Audio"), DisplayName("Default codec"),

View File

@@ -0,0 +1,23 @@
' Copyright (C) Andy https://github.com/AAndyProgram
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Namespace API.YouTube.Controls
Public Class ButtonRC : Inherits Button
Private Const WM_CONTEXTMENU As Integer = 123 '&H7B
Private Const WM_CANCELMODE As Integer = 31 '&H1F
Private Const WM_INITMENUPOPUP As Integer = 279 '&H117
Private Const SMTO_NOTIMEOUTIFNOTHUNG As Integer = 8
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WM_CONTEXTMENU Or m.Msg = WM_CANCELMODE Or m.Msg = WM_INITMENUPOPUP Or m.Msg = SMTO_NOTIMEOUTIFNOTHUNG Then
m.Result = IntPtr.Zero
Else
MyBase.WndProc(m)
End If
End Sub
End Class
End Namespace

View File

@@ -58,6 +58,11 @@ Namespace API.YouTube.Controls
If Not m.ID.IsEmptyString AndAlso m.ID.StringToLower.Contains(DRC) Then LBL_CODECS.Text &= $"{d}DRC" If Not m.ID.IsEmptyString AndAlso m.ID.StringToLower.Contains(DRC) Then LBL_CODECS.Text &= $"{d}DRC"
If Not SelectedAudio.ID.IsEmptyString Then LBL_CODECS.Text &= $" / {SelectedAudio.Extension}{d}{SelectedAudio.Codec}{d}{SelectedAudio.Bitrate}k" If Not SelectedAudio.ID.IsEmptyString Then LBL_CODECS.Text &= $" / {SelectedAudio.Extension}{d}{SelectedAudio.Codec}{d}{SelectedAudio.Bitrate}k"
If Not SelectedAudio.ID.IsEmptyString AndAlso SelectedAudio.ID.StringToLower.Contains(DRC) Then LBL_CODECS.Text &= $"{d}DRC" If Not SelectedAudio.ID.IsEmptyString AndAlso SelectedAudio.ID.StringToLower.Contains(DRC) Then LBL_CODECS.Text &= $"{d}DRC"
If MyYouTubeSettings.DefaultVideoHighlightFPS_H > 0 AndAlso m.FPS > MyYouTubeSettings.DefaultVideoHighlightFPS_H Then _
BackColor = MyColor.DeleteBack : ForeColor = MyColor.DeleteFore
If MyYouTubeSettings.DefaultVideoHighlightFPS_L > 0 AndAlso m.FPS < MyYouTubeSettings.DefaultVideoHighlightFPS_L Then _
BackColor = MyColor.UpdateBack : ForeColor = MyColor.UpdateFore
End If End If
Dim sv% = m.Size / 1024 Dim sv% = m.Size / 1024

View File

@@ -65,11 +65,11 @@ Namespace API.YouTube.Controls
Me.LBL_TIME = New System.Windows.Forms.Label() Me.LBL_TIME = New System.Windows.Forms.Label()
Me.LBL_URL = New System.Windows.Forms.LinkLabel() Me.LBL_URL = New System.Windows.Forms.LinkLabel()
Me.TXT_FILE = New PersonalUtilities.Forms.Controls.ComboBoxExtended() Me.TXT_FILE = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
Me.BTT_BROWSE = New System.Windows.Forms.Button() Me.BTT_BROWSE = New SCrawler.API.YouTube.Controls.ButtonRC()
Me.BTT_DOWN = New System.Windows.Forms.Button() Me.BTT_DOWN = New System.Windows.Forms.Button()
Me.BTT_CANCEL = New System.Windows.Forms.Button() Me.BTT_CANCEL = New System.Windows.Forms.Button()
Me.CMB_PLS = New PersonalUtilities.Forms.Controls.ComboBoxExtended() Me.CMB_PLS = New PersonalUtilities.Forms.Controls.ComboBoxExtended()
Me.BTT_PLS_BROWSE = New System.Windows.Forms.Button() Me.BTT_PLS_BROWSE = New SCrawler.API.YouTube.Controls.ButtonRC()
Me.OPT_VIDEO = New System.Windows.Forms.RadioButton() Me.OPT_VIDEO = New System.Windows.Forms.RadioButton()
Me.OPT_AUDIO = New System.Windows.Forms.RadioButton() Me.OPT_AUDIO = New System.Windows.Forms.RadioButton()
Me.LBL_AUDIO_CODEC = New System.Windows.Forms.Label() Me.LBL_AUDIO_CODEC = New System.Windows.Forms.Label()
@@ -912,13 +912,13 @@ Namespace API.YouTube.Controls
Private WithEvents TXT_SUBS_ADDIT As PersonalUtilities.Forms.Controls.TextBoxExtended Private WithEvents TXT_SUBS_ADDIT As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents TXT_EXTRA_AUDIO_FORMATS As PersonalUtilities.Forms.Controls.TextBoxExtended Private WithEvents TXT_EXTRA_AUDIO_FORMATS As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents TXT_FILE As PersonalUtilities.Forms.Controls.ComboBoxExtended Private WithEvents TXT_FILE As PersonalUtilities.Forms.Controls.ComboBoxExtended
Private WithEvents BTT_BROWSE As Button Private WithEvents BTT_BROWSE As SCrawler.API.YouTube.Controls.ButtonRC
Private WithEvents BTT_DOWN As Button Private WithEvents BTT_DOWN As Button
Private WithEvents BTT_CANCEL As Button Private WithEvents BTT_CANCEL As Button
Private WithEvents TP_HEADER_INFO_2 As TableLayoutPanel Private WithEvents TP_HEADER_INFO_2 As TableLayoutPanel
Private WithEvents TXT_FPS As PersonalUtilities.Forms.Controls.TextBoxExtended Private WithEvents TXT_FPS As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents CMB_PLS As PersonalUtilities.Forms.Controls.ComboBoxExtended Private WithEvents CMB_PLS As PersonalUtilities.Forms.Controls.ComboBoxExtended
Private WithEvents BTT_PLS_BROWSE As Button Private WithEvents BTT_PLS_BROWSE As SCrawler.API.YouTube.Controls.ButtonRC
Private WithEvents TXT_AUDIO_BITRATE As PersonalUtilities.Forms.Controls.TextBoxExtended Private WithEvents TXT_AUDIO_BITRATE As PersonalUtilities.Forms.Controls.TextBoxExtended
End Class End Class
End Namespace End Namespace

View File

@@ -121,7 +121,7 @@ Namespace API.YouTube.Controls
img = ImageRenderer.GetImage(SFile.GetBytesFromNet(imgUrl, EDP.ReturnValue), EDP.ReturnValue) img = ImageRenderer.GetImage(SFile.GetBytesFromNet(imgUrl, EDP.ReturnValue), EDP.ReturnValue)
If Not img Is Nothing Then ICON_VIDEO.Image = img : ICON_VIDEO.InitialImage = img If Not img Is Nothing Then ICON_VIDEO.Image = img : ICON_VIDEO.InitialImage = img
End If End If
LBL_TITLE.Text = .Title LBL_TITLE.Text = $"{If(MyYouTubeSettings.FileAddDateToFileName_VideoForm.Value, $"[{ .DateAdded:yyyy-MM-dd}] ", String.Empty)}{ .Title}"
LBL_TIME.Text = AConvert(Of String)(.Duration, TimeToStringProvider, String.Empty) LBL_TIME.Text = AConvert(Of String)(.Duration, TimeToStringProvider, String.Empty)
TP_HEADER_INFO_2.ColumnStyles(1).Width = MeasureTextDefault(LBL_TIME.Text, LBL_TIME.Font).Width + PaddingE.GetOf({LBL_TIME}).Horizontal TP_HEADER_INFO_2.ColumnStyles(1).Width = MeasureTextDefault(LBL_TIME.Text, LBL_TIME.Font).Width + PaddingE.GetOf({LBL_TIME}).Horizontal
TP_HEADER_INFO_2.Refresh() TP_HEADER_INFO_2.Refresh()
@@ -610,7 +610,7 @@ Namespace API.YouTube.Controls
$"Video|{AvailableVideoFormats.Select(Function(vf) $"*.{vf.ToLower}").ListToString(";")}" & $"Video|{AvailableVideoFormats.Select(Function(vf) $"*.{vf.ToLower}").ListToString(";")}" &
$"|Audio|{AvailableAudioFormats.Select(Function(af) $"*.{af.ToLower}").ListToString(";")}" $"|Audio|{AvailableAudioFormats.Select(Function(af) $"*.{af.ToLower}").ListToString(";")}"
f = SFile.SaveAs(f, "Select the destination of the video file",, ext, sPattern, EDP.ReturnValue) f = SFile.SaveAs(f, "Select the destination of the video file",, ext, sPattern, EDP.ReturnValue)
f.Extension = ext If Not f.IsEmptyString Then f.Extension = ext
End If End If
#Enable Warning #Enable Warning
f = CleanFileName(f) f = CleanFileName(f)

View File

@@ -6,6 +6,7 @@
' '
' This program is distributed in the hope that it will be useful, ' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY ' but WITHOUT ANY WARRANTY
Imports System.Runtime.CompilerServices
Imports PersonalUtilities.Tools Imports PersonalUtilities.Tools
Imports PersonalUtilities.Forms.Toolbars Imports PersonalUtilities.Forms.Toolbars
Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Functions.RegularExpressions
@@ -56,11 +57,18 @@ Namespace API.YouTube
Friend ReadOnly TitleHtmlConverter As Func(Of String, String) = Function(Input) Input.StringRemoveWinForbiddenSymbols().StringTrim() Friend ReadOnly TitleHtmlConverter As Func(Of String, String) = Function(Input) Input.StringRemoveWinForbiddenSymbols().StringTrim()
Friend ReadOnly ProgressProvider As IMyProgressNumberProvider = MyProgressNumberProvider.Percentage Friend ReadOnly ProgressProvider As IMyProgressNumberProvider = MyProgressNumberProvider.Percentage
Public ReadOnly TrueUrlRegEx As RParams = RParams.DM(Base.YouTubeFunctions.TrueUrlPattern, 0, EDP.ReturnValue) Public ReadOnly TrueUrlRegEx As RParams = RParams.DM(Base.YouTubeFunctions.TrueUrlPattern, 0, EDP.ReturnValue)
Friend ReadOnly MusicUrlApply As RParams = RParams.DMS("https://([w\.]*)youtube.com.+", 1, RegexReturn.Replace, EDP.ReturnValue,
CType(Function(input$) "music.", Func(Of String, String)), String.Empty)
<Extension> Friend Function ToMusicUrl(ByVal URL As String, ByVal IsMusic As Boolean) As String
Try : Return If(IsMusic And Not URL.IsEmptyString, CStr(RegexReplace(URL, MusicUrlApply)).IfNullOrEmpty(URL), URL) : Catch : Return URL : End Try
End Function
Friend Function CleanFileName(ByVal f As SFile) As SFile Friend Function CleanFileName(ByVal f As SFile) As SFile
If Not f.IsEmptyString And Not f.Name.IsEmptyString Then If Not f.IsEmptyString And Not f.Name.IsEmptyString Then
Dim ff As SFile = f Dim ff As SFile = f
ff.Name = ff.Name.StringRemoveWinForbiddenSymbols ff.Name = ff.Name.StringRemoveWinForbiddenSymbols.StringTrim
If Not ff.Name.IsEmptyString Then ff.Name = ff.Name.Replace("%", String.Empty) ff.Name = ff.Name.StringTrimEnd(".")
If Not ff.Name.IsEmptyString And Not MyYouTubeSettings.FileRemoveCharacters.IsEmptyString Then _
ff.Name = ff.Name.StringReplaceSymbols(MyYouTubeSettings.FileRemoveCharacters.Value.AsList.ListCast(Of String).ToArray, String.Empty, EDP.ReturnValue)
If ff.Name.IsEmptyString Then ff.Name = "file" If ff.Name.IsEmptyString Then ff.Name = "file"
Return ff Return ff
Else Else

View File

@@ -133,18 +133,25 @@ Namespace DownloadObjects.STDownloader
ICON_SITE.Image = .SiteIcon ICON_SITE.Image = .SiteIcon
LBL_TIME.Text = AConvert(Of String)(.Duration, TimeToStringProvider, String.Empty) LBL_TIME.Text = AConvert(Of String)(.Duration, TimeToStringProvider, String.Empty)
LBL_TITLE.Text = .ToString(True) LBL_TITLE.Text = $"{If(MyYouTubeSettings.FileAddDateToFileName_VideoList.Value, $"[{ .DateAdded:yyyy-MM-dd}] ", String.Empty)}{ .ToString(True)}"
Dim h%, b%
If .Self.GetType Is GetType(YouTubeMediaContainerBase) OrElse (Not .Self.GetType.BaseType Is Nothing AndAlso .Self.GetType.BaseType Is GetType(YouTubeMediaContainerBase)) Then
With DirectCast(.Self, YouTubeMediaContainerBase) : h = .HeightBase : b = .BitrateBase : End With
Else
h = .Height
b = .Bitrate
End If
If Not .SiteKey = YouTubeSiteKey And .ContentType = Plugin.UserMediaTypes.Picture Then If Not .SiteKey = YouTubeSiteKey And .ContentType = Plugin.UserMediaTypes.Picture Then
LBL_INFO.Text = .File.Extension.StringToUpper LBL_INFO.Text = .File.Extension.StringToUpper
ElseIf Not .IsMusic And Not (.MediaType = Plugin.UserMediaTypes.Audio Or .MediaType = Plugin.UserMediaTypes.AudioPre) Then ElseIf Not .IsMusic And Not (.MediaType = Plugin.UserMediaTypes.Audio Or .MediaType = Plugin.UserMediaTypes.AudioPre) Then
If .Height > 0 Then If h > 0 Then
LBL_INFO.Text = $"{ .File.Extension.StringToUpper}{d}{ .Height}p" LBL_INFO.Text = $"{ .File.Extension.StringToUpper}{d}{h}p"
Else Else
LBL_INFO.Text = .File.Extension.StringToUpper LBL_INFO.Text = .File.Extension.StringToUpper
End If End If
Else Else
If .Bitrate > 0 Then If b > 0 Then
LBL_INFO.Text = $"{ .File.Extension.StringToUpper}{d}{ .Bitrate}k" LBL_INFO.Text = $"{ .File.Extension.StringToUpper}{d}{b}k"
Else Else
LBL_INFO.Text = .File.Extension.StringToUpper LBL_INFO.Text = .File.Extension.StringToUpper
End If End If
@@ -221,7 +228,7 @@ Namespace DownloadObjects.STDownloader
t = 0 t = 0
End If End If
LBL_TITLE.Text = MyContainer.ToString(True) LBL_TITLE.Text = $"{If(MyYouTubeSettings.FileAddDateToFileName_VideoList.Value, $"[{ .DateAdded:yyyy-MM-dd}] ", String.Empty)}{ .ToString(True)}"
If Not .SiteKey = YouTubeSiteKey Then BTT_VIEW_SETTINGS.Visible = False If Not .SiteKey = YouTubeSiteKey Then BTT_VIEW_SETTINGS.Visible = False

View File

@@ -57,6 +57,12 @@ Namespace DownloadObjects.STDownloader
End If End If
MyNotificator = New YTNotificator(Me) MyNotificator = New YTNotificator(Me)
MyDownloaderSettings = MyYouTubeSettings MyDownloaderSettings = MyYouTubeSettings
ProgramLogInitialize()
With ProgramLog
AddHandler .TextAdded, AddressOf ProgramLog_TextAdded
AddHandler .TextCleared, AddressOf ProgramLog_TextCleared
End With
UpdateLogButton()
End If End If
With MyView : .Import() : .SetFormSize() : End With With MyView : .Import() : .SetFormSize() : End With
@@ -157,7 +163,7 @@ Namespace DownloadObjects.STDownloader
If PerformClick Then cnt.PerformClick() If PerformClick Then cnt.PerformClick()
If Not DisableDownload And MyDownloaderSettings.DownloadAutomatically Then AddToDownload(cnt, True) If Not DisableDownload And MyDownloaderSettings.DownloadAutomatically Then AddToDownload(cnt, True)
End With End With
End Sub, EDP.None) End Sub, EDP.SendToLog)
End Sub End Sub
#Region "Controls rendering" #Region "Controls rendering"
Private Overloads Sub OffsetControls() Private Overloads Sub OffsetControls()
@@ -247,7 +253,7 @@ Namespace DownloadObjects.STDownloader
Dim useCookiesParse As Boolean? = Nothing Dim useCookiesParse As Boolean? = Nothing
If useCookies Then useCookiesParse = True If useCookies Then useCookiesParse = True
Dim standardizeUrls As Boolean = MyYouTubeSettings.StandardizeURLs Dim standardizeUrls As Boolean = MyYouTubeSettings.StandardizeURLs
Dim standardize As Func(Of String, String) = Function(input) If(standardizeUrls, YouTubeFunctions.StandardizeURL(input), input) Dim standardize As Func(Of String, String) = Function(input) If(standardizeUrls, YouTubeFunctions.StandardizeURL(input), input.StringTrim)
Dim c As IYouTubeMediaContainer = Nothing Dim c As IYouTubeMediaContainer = Nothing
Dim url$ = String.Empty Dim url$ = String.Empty
@@ -449,12 +455,26 @@ Namespace DownloadObjects.STDownloader
End Try End Try
End Sub End Sub
#End Region #End Region
#Region "LOG"
Private Sub BTT_LOG_Click(sender As Object, e As EventArgs) Handles BTT_LOG.Click Private Sub BTT_LOG_Click(sender As Object, e As EventArgs) Handles BTT_LOG.Click
MyMainLOG_ShowForm(DesignXML,,,, AddressOf UpdateLogButton) MyMainLOG_ShowForm(DesignXML,,,, AddressOf UpdateLogButton)
End Sub End Sub
Friend Sub UpdateLogButton() Private Sub UpdateLogButton()
If AppMode Then MyMainLOG_UpdateLogButton(BTT_LOG, TOOLBAR_TOP) If AppMode Then
Try : MyMainLOG_UpdateLogButton(BTT_LOG, TOOLBAR_TOP) : Catch : End Try
End If
End Sub End Sub
Private _LogUpdateButtonSuspended As Boolean = False
Private Sub ProgramLog_TextAdded(ByVal Sender As Object, ByVal e As EventArgs)
If Not _LogUpdateButtonSuspended Then
_LogUpdateButtonSuspended = True
Try : ControlInvokeFast(TOOLBAR_TOP, BTT_LOG, AddressOf UpdateLogButton, EDP.None) : Catch : End Try
End If
End Sub
Private Sub ProgramLog_TextCleared(ByVal Sender As Object, ByVal e As EventArgs)
_LogUpdateButtonSuspended = False
End Sub
#End Region
Private Sub BTT_BUG_REPORT_Click(sender As Object, e As EventArgs) Handles BTT_BUG_REPORT.Click Private Sub BTT_BUG_REPORT_Click(sender As Object, e As EventArgs) Handles BTT_BUG_REPORT.Click
Try Try
With MyYouTubeSettings With MyYouTubeSettings

View File

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

View File

@@ -267,12 +267,11 @@ Namespace API.YouTube.Objects
<XMLEC(CollectionMode:=CollectionModes.String)> <XMLEC(CollectionMode:=CollectionModes.String)>
Friend ReadOnly Property PostProcessing_OutputAudioFormats As List(Of String) Friend ReadOnly Property PostProcessing_OutputAudioFormats As List(Of String)
Friend Sub PostProcessing_OutputAudioFormats_Reset() Friend Sub PostProcessing_OutputAudioFormats_Reset()
PostProcessing_OutputAudioFormats.Clear() With PostProcessing_OutputAudioFormats
PostProcessing_OutputAudioFormats.ListAddList(MyYouTubeSettings.DefaultAudioCodecAddit) .Clear()
If PostProcessing_OutputAudioFormats.Count > 0 Then .ListAddList(MyYouTubeSettings.DefaultAudioCodecAddit)
PostProcessing_OutputAudioFormats.Sort() If .Count > 0 Then .Sort()
PostProcessing_OutputAudioFormats.RemoveAll(Function(s) s = -1) End With
End If
End Sub End Sub
<XMLEC("OutputAudioBitrate")> Protected _OutputAudioBitrate As Integer = -1 <XMLEC("OutputAudioBitrate")> Protected _OutputAudioBitrate As Integer = -1
Friend Property OutputAudioBitrate As Integer Friend Property OutputAudioBitrate As Integer
@@ -322,21 +321,19 @@ Namespace API.YouTube.Objects
<XMLEC(CollectionMode:=CollectionModes.String)> <XMLEC(CollectionMode:=CollectionModes.String)>
Friend ReadOnly Property PostProcessing_OutputSubtitlesFormats As List(Of String) Friend ReadOnly Property PostProcessing_OutputSubtitlesFormats As List(Of String)
Friend Sub PostProcessing_OutputSubtitlesFormats_Reset() Friend Sub PostProcessing_OutputSubtitlesFormats_Reset()
PostProcessing_OutputSubtitlesFormats.Clear() With PostProcessing_OutputSubtitlesFormats
PostProcessing_OutputSubtitlesFormats.ListAddList(MyYouTubeSettings.DefaultSubtitlesFormatAddit) .Clear()
If PostProcessing_OutputSubtitlesFormats.Count > 0 Then .ListAddList(MyYouTubeSettings.DefaultSubtitlesFormatAddit)
PostProcessing_OutputSubtitlesFormats.Sort() If .Count > 0 Then .Sort()
PostProcessing_OutputSubtitlesFormats.RemoveAll(Function(s) s = -1) End With
End If
End Sub End Sub
Friend Sub SubtitlesSelectedIndexesReset() Friend Sub SubtitlesSelectedIndexesReset()
SubtitlesSelectedIndexes.Clear() With SubtitlesSelectedIndexes
Dim subs As List(Of Subtitles) = Subtitles .Clear()
SubtitlesSelectedIndexes.ListAddList(MyYouTubeSettings.DefaultSubtitles.Select(Function(s) subs.FindIndex(Function(ss) ss.ID = s))) Dim subs As List(Of Subtitles) = Subtitles
If SubtitlesSelectedIndexes.Count > 0 Then .ListAddList(MyYouTubeSettings.DefaultSubtitles.Select(Function(s) subs.FindIndex(Function(ss) ss.ID = s)))
SubtitlesSelectedIndexes.Sort() If .Count > 0 Then .Sort() : .RemoveAll(Function(s) s = -1)
SubtitlesSelectedIndexes.RemoveAll(Function(s) s = -1) End With
End If
End Sub End Sub
Private Sub SetElementsSubtitles(ByVal Source As YouTubeMediaContainerBase) Private Sub SetElementsSubtitles(ByVal Source As YouTubeMediaContainerBase)
If Not Source Is Nothing And HasElements Then If Not Source Is Nothing And HasElements Then
@@ -442,6 +439,19 @@ Namespace API.YouTube.Objects
End Get End Get
End Property End Property
<XMLEC> Public Property Height As Integer Implements IYouTubeMediaContainer.Height <XMLEC> Public Property Height As Integer Implements IYouTubeMediaContainer.Height
Friend ReadOnly Property HeightBase As Integer
Get
If Height > 0 Then
Return Height
ElseIf SelectedVideoIndex.ValueBetween(0, MediaObjects.Count - 1) Then
Return SelectedVideo.Height
ElseIf SelectedAudioIndex.ValueBetween(0, MediaObjects.Count - 1) Then
Return SelectedAudio.Height
Else
Return 0
End If
End Get
End Property
Protected _Bitrate As Integer = 0 Protected _Bitrate As Integer = 0
<XMLEC> Public Overridable Property Bitrate As Integer Implements IYouTubeMediaContainer.Bitrate <XMLEC> Public Overridable Property Bitrate As Integer Implements IYouTubeMediaContainer.Bitrate
Get Get
@@ -459,6 +469,20 @@ Namespace API.YouTube.Objects
Me._Bitrate = _Bitrate Me._Bitrate = _Bitrate
End Set End Set
End Property End Property
Friend ReadOnly Property BitrateBase As Integer
Get
If Bitrate > 0 Then
Return Bitrate
ElseIf OutputAudioBitrate > 0 Then
Return OutputAudioBitrate
ElseIf HasElements Then
Try : Return Elements.Average(Function(e) DirectCast(e, YouTubeMediaContainerBase).BitrateBase) : Catch : End Try
ElseIf SelectedAudioIndex.ValueBetween(0, MediaObjects.Count - 1) Then
Return SelectedAudio.Bitrate
End If
Return 0
End Get
End Property
<XMLEC> Public Property DateCreated As Date = Now Implements IYouTubeMediaContainer.DateCreated <XMLEC> Public Property DateCreated As Date = Now Implements IYouTubeMediaContainer.DateCreated
<XMLEC> Public Property DateAdded As Date Implements IYouTubeMediaContainer.DateAdded <XMLEC> Public Property DateAdded As Date Implements IYouTubeMediaContainer.DateAdded
Private Property IUserMedia_PostDate As Date? Implements IUserMedia.PostDate Private Property IUserMedia_PostDate As Date? Implements IUserMedia.PostDate
@@ -656,6 +680,15 @@ Namespace API.YouTube.Objects
End If End If
End Set End Set
End Property End Property
Friend Sub FileDateUpdate()
Dim n$ = _File.Name.StringTrim
Dim s$ = IIf(n.IsEmptyString, String.Empty, " ")
Select Case MyYouTubeSettings.FileAddDateToFileName.Value
Case FileDateMode.Before : n = $"[{DateAdded:yyyy-MM-dd}]{s}{n}"
Case FileDateMode.After : n = $"{n}{s}[{DateAdded:yyyy-MM-dd}]"
End Select
_File.Name = n
End Sub
Public Property FileSettings As SFile Public Property FileSettings As SFile
Private Property IUserMedia_File As String Implements IUserMedia.File Private Property IUserMedia_File As String Implements IUserMedia.File
Get Get
@@ -709,7 +742,7 @@ Namespace API.YouTube.Objects
Bitrate = 0 Bitrate = 0
_MediaType = UMTypes.Undefined _MediaType = UMTypes.Undefined
If SelectedVideoIndex >= 0 Then If SelectedVideoIndex >= 0 Then
'URGENT: 2023.3.4 -> 2023.7.6 '2023.3.4 -> 2023.7.6
'cmd.StringAppend($"bv*[format_id={SelectedVideo.ID}]") 'cmd.StringAppend($"bv*[format_id={SelectedVideo.ID}]")
cmd.StringAppend(SelectedVideo.ID) cmd.StringAppend(SelectedVideo.ID)
_Size = SelectedVideo.Size _Size = SelectedVideo.Size
@@ -726,7 +759,7 @@ Namespace API.YouTube.Objects
End If End If
If SelectedAudioIndex >= 0 Then If SelectedAudioIndex >= 0 Then
Dim atCodec$ Dim atCodec$
'URGENT: 2023.3.4 -> 2023.7.6 '2023.3.4 -> 2023.7.6
'cmd.StringAppend($"ba*[format_id={SelectedAudio.ID}]", "+") 'cmd.StringAppend($"ba*[format_id={SelectedAudio.ID}]", "+")
cmd.StringAppend(SelectedAudio.ID, "+") cmd.StringAppend(SelectedAudio.ID, "+")
If OutputAudioCodec.StringToLower = ac3 Then If OutputAudioCodec.StringToLower = ac3 Then
@@ -769,7 +802,7 @@ Namespace API.YouTube.Objects
subs = $"--write-subs --write-auto-subs --sub-format {OutputSubtitlesFormat.StringToLower} --sub-langs ""{subs}"" --convert-subs {OutputSubtitlesFormat.StringToLower}" subs = $"--write-subs --write-auto-subs --sub-format {OutputSubtitlesFormat.StringToLower} --sub-langs ""{subs}"" --convert-subs {OutputSubtitlesFormat.StringToLower}"
End If End If
If Not cmd.IsEmptyString Then If Not cmd.IsEmptyString Then
'URGENT: 2023.3.4 -> 2023.7.6 '2023.3.4 -> 2023.7.6
'cmd = $"yt-dlp -f ""{cmd}""" 'cmd = $"yt-dlp -f ""{cmd}"""
'cmd = $"yt-dlp -f {cmd}" 'cmd = $"yt-dlp -f {cmd}"
cmd = $"{YTDLP_NAME} -f {cmd}" cmd = $"{YTDLP_NAME} -f {cmd}"
@@ -966,7 +999,7 @@ Namespace API.YouTube.Objects
.Visible = True .Visible = True
.Value = 0 .Value = 0
.Maximum = DownloadGetElemCountSingle() .Maximum = DownloadGetElemCountSingle()
.Information = $"Download {ObjectType}" .Information = "Downloading"
End With End With
End If End If
@@ -1111,7 +1144,7 @@ Namespace API.YouTube.Objects
.Value = 0 .Value = 0
.Maximum = 100 .Maximum = 100
.Provider = ProgressProvider .Provider = ProgressProvider
.Information = $"Download {MediaType}" .Information = "Downloading"
End With End With
End If End If
.MainProcessName = MyYouTubeSettings.YTDLP.Name '"yt-dlp" .MainProcessName = MyYouTubeSettings.YTDLP.Name '"yt-dlp"
@@ -1143,12 +1176,22 @@ Namespace API.YouTube.Objects
If fileUrl.Exists Then AddFile(fileUrl) If fileUrl.Exists Then AddFile(fileUrl)
End If End If
If MyYouTubeSettings.CreateDescriptionFiles And Not Description.IsEmptyString Then With MyYouTubeSettings
Dim fileDesr As SFile = File If .CreateDescriptionFiles And (Not Description.IsEmptyString Or
fileDesr.Extension = "txt" (.CreateDescriptionFiles_CreateWithNoDescription And .CreateDescriptionFiles_AddUploadDate)) Then
TextSaver.SaveTextToFile(Description, fileDesr,,, EDP.None) Dim fileDesr As SFile = File
If fileDesr.Exists Then AddFile(fileDesr) fileDesr.Extension = "txt"
End If Using fileDesrText As New TextSaver(fileDesr)
If .CreateDescriptionFiles_AddUploadDate Then fileDesrText.Append($"Uploaded: {DateAdded:yyyy-MM-dd HH:mm:ss}")
If Not Description.IsEmptyString Then
If Not fileDesrText.IsEmptyString Then fileDesrText.AppendLine.AppendLine()
fileDesrText.Append(Description)
End If
fileDesrText.Save(EDP.None)
End Using
If fileDesr.Exists Then AddFile(fileDesr)
End If
End With
If PlaylistCount > 0 And Not CoverDownloaded And Not PlaylistID.IsEmptyString Then DownloadPlaylistCover(PlaylistID, File, UseCookies) If PlaylistCount > 0 And Not CoverDownloaded And Not PlaylistID.IsEmptyString Then DownloadPlaylistCover(PlaylistID, File, UseCookies)
If prExists Then Progress.InformationTemporary = $"Download {MediaType}: post processing" If prExists Then Progress.InformationTemporary = $"Download {MediaType}: post processing"
@@ -1286,6 +1329,7 @@ Namespace API.YouTube.Objects
If format = mp3 And Not mp3ThumbEmbedded And MyYouTubeSettings.DefaultAudioEmbedThumbnail_ExtractedFiles Then _ If format = mp3 And Not mp3ThumbEmbedded And MyYouTubeSettings.DefaultAudioEmbedThumbnail_ExtractedFiles Then _
embedThumbTo.Invoke(f) : mp3ThumbEmbedded = True embedThumbTo.Invoke(f) : mp3ThumbEmbedded = True
If Not M3U8_PlaylistFiles.ListExists AndAlso f.Exists Then M3U8_Append(f) If Not M3U8_PlaylistFiles.ListExists AndAlso f.Exists Then M3U8_Append(f)
If format = mp3 AndAlso f.Exists AndAlso MyYouTubeSettings.VideoPlaylist_AddExtractedMP3.Value Then M3U8_Append(f)
End If End If
Next Next
End If End If
@@ -1534,7 +1578,7 @@ Namespace API.YouTube.Objects
ID = .Value("id") ID = .Value("id")
Title = TitleHtmlConverter.Invoke(.Value("title")) Title = TitleHtmlConverter.Invoke(.Value("title"))
Description = .Value("description") Description = .Value("description")
URL = .Value("webpage_url") URL = .Value("webpage_url").ToMusicUrl(IsMusic)
PlaylistID = .Value("playlist_id") PlaylistID = .Value("playlist_id")
PlaylistCount = .Value("n_entries").IfNullOrEmpty(.Value("playlist_count")).FromXML(Of Integer)(0) PlaylistCount = .Value("n_entries").IfNullOrEmpty(.Value("playlist_count")).FromXML(Of Integer)(0)
@@ -1572,6 +1616,7 @@ Namespace API.YouTube.Objects
If tValue.HasValue Then Duration = TimeSpan.FromSeconds(tValue.Value) If tValue.HasValue Then Duration = TimeSpan.FromSeconds(tValue.Value)
End If End If
DateAdded = AConvert(Of Date)(.Value("release_date").IfNullOrEmpty(.Value("upload_date")), DateAddedProvider, New Date) DateAdded = AConvert(Of Date)(.Value("release_date").IfNullOrEmpty(.Value("upload_date")), DateAddedProvider, New Date)
If Not IsMusic Then FileDateUpdate()
ParseFormats(.Self) ParseFormats(.Self)

View File

@@ -115,6 +115,9 @@
<ItemGroup> <ItemGroup>
<Compile Include="Attributes\GridVisibleAttribute.vb" /> <Compile Include="Attributes\GridVisibleAttribute.vb" />
<Compile Include="Base\TableControlsProcessor.vb" /> <Compile Include="Base\TableControlsProcessor.vb" />
<Compile Include="Controls\ButtonRC.vb">
<SubType>Component</SubType>
</Compile>
<Compile Include="Controls\ChannelTabsChooserForm.Designer.vb"> <Compile Include="Controls\ChannelTabsChooserForm.Designer.vb">
<DependentUpon>ChannelTabsChooserForm.vb</DependentUpon> <DependentUpon>ChannelTabsChooserForm.vb</DependentUpon>
</Compile> </Compile>

View File

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

View File

@@ -6,6 +6,7 @@
' '
' This program is distributed in the hope that it will be useful, ' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY ' but WITHOUT ANY WARRANTY
Imports System.Runtime.CompilerServices
Imports PersonalUtilities.Forms Imports PersonalUtilities.Forms
Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Functions.RegularExpressions
Namespace API.Base Namespace API.Base
@@ -72,5 +73,12 @@ Namespace API.Base
$"Current query: [{CurrentQuery}]{vbCr}New query: [{NewQuery}]", $"Current query: [{CurrentQuery}]{vbCr}New query: [{NewQuery}]",
"Changing a query"}, vbExclamation,,, {"Process", "Cancel"}) = 0 "Changing a query"}, vbExclamation,,, {"Process", "Cancel"}) = 0
End Function End Function
<Extension> Friend Function GetCookieValue(ByVal Cookies As IEnumerable(Of System.Net.Cookie), ByVal CookieName As String) As String
If Cookies.ListExists Then Return If(Cookies.FirstOrDefault(Function(c) c.Name.ToLower = CookieName.ToLower)?.Value, String.Empty) Else Return String.Empty
End Function
<Extension> Friend Function GetCookieValue(ByVal Cookies As IEnumerable(Of System.Net.Cookie), ByVal CookieName As String,
ByVal PropName As String, ByVal PropNameComp As String) As String
Return If(PropName = PropNameComp, Cookies.GetCookieValue(CookieName), String.Empty)
End Function
End Module End Module
End Namespace End Namespace

View File

@@ -11,6 +11,9 @@ Namespace API.Base
Friend Const Header_Authorization As String = "authorization" Friend Const Header_Authorization As String = "authorization"
Friend Const Header_CSRFToken As String = "x-csrf-token" Friend Const Header_CSRFToken As String = "x-csrf-token"
Friend Const CAT_UserDefs As String = "New user defaults"
Friend Const CAT_Timers As String = "Timers"
Friend Const ConcurrentDownloadsCaption As String = "Concurrent downloads" Friend Const ConcurrentDownloadsCaption As String = "Concurrent downloads"
Friend Const ConcurrentDownloadsToolTip As String = "The number of concurrent downloads." Friend Const ConcurrentDownloadsToolTip As String = "The number of concurrent downloads."
Friend Const SavedPostsUserNameCaption As String = "Saved posts user" Friend Const SavedPostsUserNameCaption As String = "Saved posts user"

View File

@@ -77,7 +77,7 @@ Namespace API.Base
''' </summary> ''' </summary>
Function Delete(Optional ByVal Multiple As Boolean = False, Optional ByVal CollectionValue As Integer = -1) As Integer Function Delete(Optional ByVal Multiple As Boolean = False, Optional ByVal CollectionValue As Integer = -1) As Integer
Function EraseData(ByVal Mode As EraseMode) As Boolean Function EraseData(ByVal Mode As EraseMode) As Boolean
Function MoveFiles(ByVal CollectionName As String, ByVal SpecialCollectionPath As SFile) As Boolean Function MoveFiles(ByVal CollectionName As String, ByVal SpecialCollectionPath As SFile, Optional ByVal NewUser As SplitCollectionUserInfo? = Nothing) As Boolean
Function CopyFiles(ByVal DestinationPath As SFile, Optional ByVal e As ErrorsDescriber = Nothing) As Boolean Function CopyFiles(ByVal DestinationPath As SFile, Optional ByVal e As ErrorsDescriber = Nothing) As Boolean
Sub OpenFolder() Sub OpenFolder()
Property DownloadTopCount As Integer? Property DownloadTopCount As Integer?

View File

@@ -54,9 +54,8 @@ Namespace API.Base
Dim aStr$ = String.Empty Dim aStr$ = String.Empty
If Count > 1 Then aStr = $" ({Number}/{Count})" If Count > 1 Then aStr = $" ({Number}/{Count})"
Try Try
If Host.Source.ReadyToDownload(PDownload.SavedPosts) Then If Host.Available(PDownload.SavedPosts, Multiple Or Count > 1) Then
If Host.Available(PDownload.SavedPosts, Multiple Or Count > 1) Then If Host.Source.ReadyToDownload(PDownload.SavedPosts) Then
Host.DownloadStarted(PDownload.SavedPosts)
If Count > 1 Then Progress.Information = $"{Host.Name} - {Host.AccountName.IfNullOrEmpty(SettingsHost.NameAccountNameDefault)}" If Count > 1 Then Progress.Information = $"{Host.Name} - {Host.AccountName.IfNullOrEmpty(SettingsHost.NameAccountNameDefault)}"
Using user As IUserData = Host.GetInstance(PDownload.SavedPosts, Nothing, False, False) Using user As IUserData = Host.GetInstance(PDownload.SavedPosts, Nothing, False, False)
If Not user Is Nothing Then If Not user Is Nothing Then
@@ -83,11 +82,11 @@ Namespace API.Base
End Using End Using
Else Else
_Unavailable += 1 _Unavailable += 1
Progress.InformationTemporary = $"Host [{Host.Name}{aStr}] is unavailable" Progress.InformationTemporary = $"Host [{Host.Name}{aStr}] is not ready"
End If End If
Else Else
_NotReady += 1 _NotReady += 1
Progress.InformationTemporary = $"Host [{Host.Name}{aStr}] is not ready" Progress.InformationTemporary = $"Host [{Host.Name}{aStr}] is unavailable"
End If End If
Catch oex As OperationCanceledException When Token.IsCancellationRequested Catch oex As OperationCanceledException When Token.IsCancellationRequested
_ErrorCount += 1 _ErrorCount += 1
@@ -96,9 +95,6 @@ Namespace API.Base
_ErrorCount += 1 _ErrorCount += 1
Progress.InformationTemporary = $"{Host.Name}{aStr} downloading error" Progress.InformationTemporary = $"{Host.Name}{aStr} downloading error"
ErrorsDescriber.Execute(EDP.SendToLog, ex, $"[API.Base.ProfileSaved.Download({Host.Key}{aStr})]") ErrorsDescriber.Execute(EDP.SendToLog, ex, $"[API.Base.ProfileSaved.Download({Host.Key}{aStr})]")
Finally
Host.DownloadDone(PDownload.SavedPosts)
MainFrameObj.UpdateLogButton()
End Try End Try
End Sub End Sub
End Class End Class

View File

@@ -34,6 +34,16 @@ Namespace API.Base
Friend Property AccountName As String Implements ISiteSettings.AccountName Friend Property AccountName As String Implements ISiteSettings.AccountName
Friend Property Temporary As Boolean = False Implements ISiteSettings.Temporary Friend Property Temporary As Boolean = False Implements ISiteSettings.Temporary
Friend Property DefaultInstance As ISiteSettings = Nothing Implements ISiteSettings.DefaultInstance Friend Property DefaultInstance As ISiteSettings = Nothing Implements ISiteSettings.DefaultInstance
Protected _UserAgentDefault As String = String.Empty
Friend Overridable Property UserAgentDefault As String Implements ISiteSettings.UserAgentDefault
Get
Return _UserAgentDefault
End Get
Set(ByVal _UserAgentDefault As String)
Me._UserAgentDefault = _UserAgentDefault
If _AllowUserAgentUpdate And Not Responser Is Nothing And Not _UserAgentDefault.IsEmptyString Then Responser.UserAgent = _UserAgentDefault
End Set
End Property
Protected _AllowUserAgentUpdate As Boolean = True Protected _AllowUserAgentUpdate As Boolean = True
Protected _SubscriptionsAllowed As Boolean = False Protected _SubscriptionsAllowed As Boolean = False
Friend ReadOnly Property SubscriptionsAllowed As Boolean Implements ISiteSettings.SubscriptionsAllowed Friend ReadOnly Property SubscriptionsAllowed As Boolean Implements ISiteSettings.SubscriptionsAllowed
@@ -138,7 +148,6 @@ Namespace API.Base
Friend Overridable Sub BeginInit() Implements ISiteSettings.BeginInit Friend Overridable Sub BeginInit() Implements ISiteSettings.BeginInit
End Sub End Sub
Friend Overridable Sub EndInit() Implements ISiteSettings.EndInit Friend Overridable Sub EndInit() Implements ISiteSettings.EndInit
If _AllowUserAgentUpdate And Not DefaultUserAgent.IsEmptyString And Not Responser Is Nothing Then Responser.UserAgent = DefaultUserAgent
If CheckNetscapeCookiesOnEndInit Then Update_SaveCookiesNetscape(, True) If CheckNetscapeCookiesOnEndInit Then Update_SaveCookiesNetscape(, True)
End Sub End Sub
#End Region #End Region

View File

@@ -143,7 +143,7 @@ Namespace API.Base
Protected Const Name_UserID As String = "UserID" Protected Const Name_UserID As String = "UserID"
Protected Const Name_Options As String = "Options" Protected Const Name_Options As String = "Options"
Protected Const Name_Description As String = "Description" Protected Const Name_Description As String = "Description"
Private Const Name_ParseUserMediaOnly As String = "ParseUserMediaOnly" Protected Const Name_ParseUserMediaOnly As String = "ParseUserMediaOnly"
Private Const Name_IsSubscription As String = UserInfo.Name_IsSubscription Private Const Name_IsSubscription As String = UserInfo.Name_IsSubscription
Private Const Name_Temporary As String = "Temporary" Private Const Name_Temporary As String = "Temporary"
Private Const Name_Favorite As String = "Favorite" Private Const Name_Favorite As String = "Favorite"
@@ -950,7 +950,10 @@ BlockNullPicture:
LogError(ex, "user information loading error") LogError(ex, "user information loading error")
End Try End Try
End Sub End Sub
Friend Overridable Sub UpdateUserInformation() Implements IUserData.UpdateUserInformation Friend Overridable Overloads Sub UpdateUserInformation() Implements IUserData.UpdateUserInformation
UpdateUserInformation(False)
End Sub
Friend Overridable Overloads Sub UpdateUserInformation(ByVal DisableUserInfoUpdate As Boolean)
Try Try
UpdateDataFiles() UpdateDataFiles()
MyFileSettings.Exists(SFO.Path) MyFileSettings.Exists(SFO.Path)
@@ -1001,7 +1004,7 @@ BlockNullPicture:
x.Save(MyFileSettings) x.Save(MyFileSettings)
End Using End Using
If Not IsSavedPosts Then Settings.UpdateUsersList(User, True) If Not IsSavedPosts And Not DisableUserInfoUpdate Then Settings.UpdateUsersList(User, True)
Catch ex As Exception Catch ex As Exception
LogError(ex, "user information saving error") LogError(ex, "user information saving error")
End Try End Try
@@ -1934,7 +1937,18 @@ BlockNullPicture:
Return 0 Return 0
End If End If
End Function End Function
Friend Overridable Function MoveFiles(ByVal __CollectionName As String, ByVal __SpecialCollectionPath As SFile) As Boolean Implements IUserData.MoveFiles Friend Function SplitCollectionGetNewUserInfo() As SplitCollectionUserInfo
Dim u As New SplitCollectionUserInfo With {.UserOrig = User, .UserNew = User}
With u.UserNew
.CollectionName = String.Empty
.SpecialCollectionPath = Nothing
.UserModel = UsageModel.Default
.CollectionModel = UsageModel.Default
.UpdateUserFile()
End With
Return u
End Function
Friend Overridable Function MoveFiles(ByVal __CollectionName As String, ByVal __SpecialCollectionPath As SFile, Optional ByVal NewUser As SplitCollectionUserInfo? = Nothing) As Boolean Implements IUserData.MoveFiles
Dim UserBefore As UserInfo = User Dim UserBefore As UserInfo = User
Dim Removed As Boolean = True Dim Removed As Boolean = True
Dim _TurnBack As Boolean = False Dim _TurnBack As Boolean = False
@@ -1950,6 +1964,7 @@ BlockNullPicture:
User.SpecialCollectionPath = String.Empty User.SpecialCollectionPath = String.Empty
User.UserModel = UsageModel.Default User.UserModel = UsageModel.Default
User.CollectionModel = UsageModel.Default User.CollectionModel = UsageModel.Default
If NewUser.HasValue Then User.SpecialPath = NewUser.Value.UserNew.SpecialPath
Else Else
Settings.Users.Remove(Me) Settings.Users.Remove(Me)
Removed = True Removed = True

View File

@@ -0,0 +1,28 @@
' Copyright (C) Andy https://github.com/AAndyProgram
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Namespace API.Base
Friend Structure SplitCollectionUserInfo
Friend UserOrig As UserInfo
Friend UserNew As UserInfo
Friend Changed As Boolean
Friend ReadOnly Property SameDrive As Boolean
Get
Return GetUserDrive(UserOrig) = GetUserDrive(UserNew)
End Get
End Property
Private Shared Function GetUserDrive(ByVal User As UserInfo) As String
Dim u As UserInfo = User
If u.File.IsEmptyString Then u.UpdateUserFile()
Return u.File.Segments.FirstOrDefault.StringToLower
End Function
Public Overrides Function ToString() As String
Return $"[{UserOrig.File.CutPath.PathWithSeparator}] -> [{UserNew.File.CutPath.PathWithSeparator}]"
End Function
End Structure
End Namespace

View File

@@ -0,0 +1,111 @@
' Copyright (C) Andy https://github.com/AAndyProgram
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Namespace API.Base
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Friend Class SplitCollectionUserInfoChangePathsForm : 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 CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
Dim LBL_INFO As System.Windows.Forms.Label
Me.LIST_USERS = New System.Windows.Forms.ListBox()
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
LBL_INFO = New System.Windows.Forms.Label()
CONTAINER_MAIN.ContentPanel.SuspendLayout()
CONTAINER_MAIN.SuspendLayout()
TP_MAIN.SuspendLayout()
Me.SuspendLayout()
'
'CONTAINER_MAIN
'
'
'CONTAINER_MAIN.ContentPanel
'
CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(384, 261)
CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
CONTAINER_MAIN.LeftToolStripPanelVisible = False
CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
CONTAINER_MAIN.Name = "CONTAINER_MAIN"
CONTAINER_MAIN.RightToolStripPanelVisible = False
CONTAINER_MAIN.Size = New System.Drawing.Size(384, 261)
CONTAINER_MAIN.TabIndex = 0
CONTAINER_MAIN.TopToolStripPanelVisible = False
'
'TP_MAIN
'
TP_MAIN.ColumnCount = 1
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
TP_MAIN.Controls.Add(LBL_INFO, 0, 0)
TP_MAIN.Controls.Add(Me.LIST_USERS, 0, 1)
TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
TP_MAIN.Location = New System.Drawing.Point(0, 0)
TP_MAIN.Name = "TP_MAIN"
TP_MAIN.RowCount = 2
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MAIN.Size = New System.Drawing.Size(384, 261)
TP_MAIN.TabIndex = 0
'
'LBL_INFO
'
LBL_INFO.Dock = System.Windows.Forms.DockStyle.Fill
LBL_INFO.Location = New System.Drawing.Point(3, 0)
LBL_INFO.Name = "LBL_INFO"
LBL_INFO.Size = New System.Drawing.Size(378, 50)
LBL_INFO.TabIndex = 0
LBL_INFO.Text = "Check the user destination paths and change them if necessary." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Double-click to c" &
"hange."
LBL_INFO.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
'
'LIST_USERS
'
Me.LIST_USERS.Dock = System.Windows.Forms.DockStyle.Fill
Me.LIST_USERS.FormattingEnabled = True
Me.LIST_USERS.Location = New System.Drawing.Point(3, 53)
Me.LIST_USERS.Name = "LIST_USERS"
Me.LIST_USERS.Size = New System.Drawing.Size(378, 205)
Me.LIST_USERS.TabIndex = 1
'
'SplitCollectionUserInfoChangePathsForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(384, 261)
Me.Controls.Add(CONTAINER_MAIN)
Me.Icon = Global.SCrawler.My.Resources.Resources.UsersIcon_32
Me.KeyPreview = True
Me.MinimumSize = New System.Drawing.Size(400, 300)
Me.Name = "SplitCollectionUserInfoChangePathsForm"
Me.ShowInTaskbar = False
Me.Text = "Collection users"
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
CONTAINER_MAIN.ResumeLayout(False)
CONTAINER_MAIN.PerformLayout()
TP_MAIN.ResumeLayout(False)
Me.ResumeLayout(False)
End Sub
Private WithEvents LIST_USERS As ListBox
End Class
End Namespace

View File

@@ -0,0 +1,129 @@
<?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="TP_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="LBL_INFO.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
</root>

View File

@@ -0,0 +1,78 @@
' Copyright (C) Andy https://github.com/AAndyProgram
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Functions.Messaging
Namespace API.Base
Friend Class SplitCollectionUserInfoChangePathsForm
Private WithEvents MyDefs As DefaultFormOptions
Friend ReadOnly Property Users As List(Of SplitCollectionUserInfo)
''' <summary>
''' Cancel = use initial<br/>
''' Abort = abort operation<br/>
''' OK = use changes
''' </summary>
Friend Sub New(ByVal _Users As IEnumerable(Of SplitCollectionUserInfo))
InitializeComponent()
MyDefs = New DefaultFormOptions(Me, Settings.Design)
Users = New List(Of SplitCollectionUserInfo)(_Users)
End Sub
Private Sub SplitCollectionUserInfoChangePathsForm_Load(sender As Object, e As EventArgs) Handles Me.Load
With MyDefs
.MyViewInitialize()
.AddOkCancelToolbar()
LIST_USERS.Items.AddRange(Users.Cast(Of Object).ToArray)
.EndLoaderOperations()
.MyOkCancel.EnableOK = True
End With
End Sub
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
MyDefs.CloseForm()
End Sub
Private Sub MyDefs_ButtonCancelClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonCancelClick
Dim m As New MMessage("You have canceled the change. Do you want to process user(s) as is or cancel the operation?", "Change user paths",
{New MsgBoxButton("Initial", "Process users as is (IGNORE changes to this form)") With {.CallBackObject = DialogResult.Cancel},
New MsgBoxButton("Process", "Process users as is (INCLUDE changes here)") With {.CallBackObject = DialogResult.OK},
New MsgBoxButton("Abort", "Abort operation") With {.CallBackObject = DialogResult.Abort},
New MsgBoxButton("Cancel", "Continue editing here") With {.CallBackObject = DialogResult.Retry}},
vbExclamation) With {.ButtonsPerRow = 4}
Dim result As DialogResult = CInt(MsgBoxE(m).Button.CallBackObject)
If result = DialogResult.Retry Then
e.Handled = True
Exit Sub
Else
MyDefs.CloseForm(result)
End If
End Sub
Private Sub SplitCollectionUserInfoChangePathsForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
Users.Clear()
End Sub
Private Sub LIST_USERS_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles LIST_USERS.MouseDoubleClick
Try
With LIST_USERS
If .SelectedIndex >= 0 Then
Dim obj As SplitCollectionUserInfo = .Items(.SelectedIndex)
Using f As New SplitCollectionUserInfoPathForm(obj)
f.ShowDialog()
If f.DialogResult = DialogResult.OK Then
obj = f.User
If obj.Changed Then
Users(.SelectedIndex) = obj
.Items(.SelectedIndex) = obj
.Refresh()
End If
End If
End Using
End If
End With
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Change user paths")
End Try
End Sub
End Class
End Namespace

View File

@@ -0,0 +1,134 @@
' Copyright (C) Andy https://github.com/AAndyProgram
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Namespace API.Base
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Friend Class SplitCollectionUserInfoPathForm : 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 CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(SplitCollectionUserInfoPathForm))
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Me.TXT_PATH_CURR = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_PATH_NEW = New PersonalUtilities.Forms.Controls.TextBoxExtended()
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
CONTAINER_MAIN.ContentPanel.SuspendLayout()
CONTAINER_MAIN.SuspendLayout()
TP_MAIN.SuspendLayout()
CType(Me.TXT_PATH_CURR, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_PATH_NEW, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'CONTAINER_MAIN
'
'
'CONTAINER_MAIN.ContentPanel
'
CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(484, 84)
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(484, 84)
CONTAINER_MAIN.TabIndex = 0
CONTAINER_MAIN.TopToolStripPanelVisible = False
'
'TP_MAIN
'
TP_MAIN.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
TP_MAIN.ColumnCount = 1
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
TP_MAIN.Controls.Add(Me.TXT_PATH_CURR, 0, 0)
TP_MAIN.Controls.Add(Me.TXT_PATH_NEW, 0, 1)
TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
TP_MAIN.Location = New System.Drawing.Point(0, 0)
TP_MAIN.Name = "TP_MAIN"
TP_MAIN.RowCount = 3
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MAIN.Size = New System.Drawing.Size(484, 84)
TP_MAIN.TabIndex = 0
'
'TXT_PATH_CURR
'
Me.TXT_PATH_CURR.CaptionText = "Current"
Me.TXT_PATH_CURR.CaptionWidth = 50.0R
Me.TXT_PATH_CURR.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_PATH_CURR.Location = New System.Drawing.Point(4, 4)
Me.TXT_PATH_CURR.Name = "TXT_PATH_CURR"
Me.TXT_PATH_CURR.Size = New System.Drawing.Size(476, 22)
Me.TXT_PATH_CURR.TabIndex = 0
Me.TXT_PATH_CURR.TextBoxReadOnly = True
'
'TXT_PATH_NEW
'
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
ActionButton1.Name = "Refresh"
ActionButton1.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image)
ActionButton2.Name = "Open"
ActionButton2.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
Me.TXT_PATH_NEW.Buttons.Add(ActionButton1)
Me.TXT_PATH_NEW.Buttons.Add(ActionButton2)
Me.TXT_PATH_NEW.CaptionText = "New"
Me.TXT_PATH_NEW.CaptionWidth = 50.0R
Me.TXT_PATH_NEW.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_PATH_NEW.Location = New System.Drawing.Point(4, 33)
Me.TXT_PATH_NEW.Name = "TXT_PATH_NEW"
Me.TXT_PATH_NEW.Size = New System.Drawing.Size(476, 22)
Me.TXT_PATH_NEW.TabIndex = 1
'
'SplitCollectionUserInfoPathForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(484, 84)
Me.Controls.Add(CONTAINER_MAIN)
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
Me.Icon = Global.SCrawler.My.Resources.Resources.UsersIcon_32
Me.KeyPreview = True
Me.MaximizeBox = False
Me.MaximumSize = New System.Drawing.Size(500, 123)
Me.MinimizeBox = False
Me.MinimumSize = New System.Drawing.Size(500, 123)
Me.Name = "SplitCollectionUserInfoPathForm"
Me.ShowInTaskbar = False
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
Me.Text = "User paths"
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
CONTAINER_MAIN.ResumeLayout(False)
CONTAINER_MAIN.PerformLayout()
TP_MAIN.ResumeLayout(False)
CType(Me.TXT_PATH_CURR, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_PATH_NEW, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
End Sub
Private WithEvents TXT_PATH_CURR As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents TXT_PATH_NEW As PersonalUtilities.Forms.Controls.TextBoxExtended
End Class
End Namespace

View File

@@ -0,0 +1,154 @@
<?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="TP_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="ActionButton1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
QVQ4T2P4//8/QczOJyyqHpzfiE0OQwAZC8iqszAzs7CJ69o4BR768V/W2jcGXQ0KB4aFNS3dDQtnrbCb
ePCK48wTN1wXXXzge/jXf/clV55zC4hIIatF0cjIyMikElzc57z0wX+XHd/+2+//99/ywP//xlu//tdb
+eK/4Zp3/1WTOhYzARViNUAluKjTdf37/0ZTTn9TbdhwXblhwwW1/qOP1Ja9+K8w+95/6cm3/6v2Xvkv
qKjniGGAoIqRpW3/4e8S9uGdzFz82gwMDFxAzCxm4ZegtuLDf+VJ1/8rZM25IqLvnM/CximCYYCic1QN
v7x2JIwPwyrJ3XNUylddE9G2TWNmZOBDl4czmJiZMSRBmFdSyYyJgUEQmxwIYxWEYXZBCUls4sgYq6CA
prWNbtG8nXKeaVPR5XiVjSxEzf0yYXy4BBMLO6eQjoOXZvrkbbazrv53Xf/2v4CSbjBMXkhBl1/CMyNZ
qWnvGy5pNQ+YONwAfjXzAOupl/47LLr333L50/96q9/8l23YdES6cO5KuYqVW+R7Tj6SnfP0v4hryjyY
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value>
</data>
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
cMaRN0UdBBkAAAAASUVORK5CYII=
</value>
</data>
</root>

View File

@@ -0,0 +1,68 @@
' Copyright (C) Andy https://github.com/AAndyProgram
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Controls.Base
Imports SCrawler.DownloadObjects.STDownloader
Namespace API.Base
Friend Class SplitCollectionUserInfoPathForm
Private WithEvents MyDefs As DefaultFormOptions
Friend User As SplitCollectionUserInfo
Private ReadOnly UserNewPathDef As String
Friend Sub New(ByVal _User As SplitCollectionUserInfo)
InitializeComponent()
MyDefs = New DefaultFormOptions(Me, Settings.Design)
User = _User
UserNewPathDef = User.UserNew.File.CutPath.PathWithSeparator
End Sub
Private Sub SplitCollectionUserInfoPathForm_Load(sender As Object, e As EventArgs) Handles Me.Load
With MyDefs
.MyViewInitialize()
.AddOkCancelToolbar()
TXT_PATH_CURR.Text = User.UserOrig.File.CutPath.PathWithSeparator
TXT_PATH_NEW.Text = UserNewPathDef
.MyFieldsCheckerE = New FieldsChecker
.MyFieldsCheckerE.AddControl(Of String)(TXT_PATH_NEW, "New path")
.MyFieldsCheckerE.EndLoaderOperations()
.EndLoaderOperations()
End With
End Sub
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
If MyDefs.MyFieldsChecker.AllParamsOK Then MyDefs.CloseForm()
End Sub
Private Sub TXT_PATH_NEW_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_PATH_NEW.ActionOnButtonClick
Select Case e.DefaultButton
Case ActionButton.DefaultButtons.Refresh : TXT_PATH_NEW.Text = UserNewPathDef
Case ActionButton.DefaultButtons.Open
Using ff As New Editors.GlobalLocationsChooserForm With {.MyInitialLocation = TXT_PATH_NEW.Text}
ff.ShowDialog()
If ff.DialogResult = DialogResult.OK Then
Dim dest As DownloadLocation = ff.MyDestination
If Not dest.Path.IsEmptyString Then
Dim ph As PathMoverHandler = Editors.GlobalLocationsChooserForm.ModelHandler(dest.Model)
If Not ph Is Nothing Then TXT_PATH_NEW.Text = ph.Invoke(User.UserNew, dest.Path.CSFileP).ToString
End If
End If
End Using
End Select
End Sub
Private Sub TXT_PATH_NEW_ActionOnTextChanged(sender As Object, e As EventArgs) Handles TXT_PATH_NEW.ActionOnTextChanged
If Not MyDefs.Initializing Then
Dim f As SFile = TXT_PATH_NEW.Text.CSFileP
If Not f.IsEmptyString Then
User.UserNew.SpecialPath = f
User.UserNew.UpdateUserFile()
User.Changed = Not User.UserNew.File.CutPath.PathWithSeparator = UserNewPathDef
End If
End If
End Sub
End Class
End Namespace

View File

@@ -11,9 +11,8 @@ Imports PersonalUtilities.Functions.XML.Base
Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Functions.RegularExpressions
Namespace API.Facebook Namespace API.Facebook
Friend Module Declarations Friend Module Declarations
Friend ReadOnly Regex_UserToken_dtsg As RParams = RParams.DMS("DTSGInitialData.:.?{\s*.token.:\s*""([^""]+)", 1, EDP.ReturnValue)
Friend ReadOnly Regex_UserToken_lsd As RParams = RParams.DMS("LSD.:.?{\s*.token.:\s*""([^""]+)", 1, EDP.ReturnValue)
Friend ReadOnly Regex_UserID As RParams = RParams.DMS("userid.:.(\d+)", 1, RegexOptions.IgnoreCase, EDP.ReturnValue) Friend ReadOnly Regex_UserID As RParams = RParams.DMS("userid.:.(\d+)", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
Friend ReadOnly Regex_AppID As RParams = RParams.DMS("APP_ID.:.(\d+)", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
Friend ReadOnly Regex_Photos_by As RParams = RParams.DMS("photos_by"",""id"":""([^""]+)", 1, EDP.ReturnValue) Friend ReadOnly Regex_Photos_by As RParams = RParams.DMS("photos_by"",""id"":""([^""]+)", 1, EDP.ReturnValue)
Friend ReadOnly Regex_FileName As RParams = RParams.DM("([^/\?]+\..{3,4})(?=(\?|\Z))", 0, EDP.ReturnValue) Friend ReadOnly Regex_FileName As RParams = RParams.DM("([^/\?]+\..{3,4})(?=(\?|\Z))", 0, EDP.ReturnValue)

View File

@@ -11,6 +11,7 @@ Imports SCrawler.Plugin
Imports SCrawler.Plugin.Attributes Imports SCrawler.Plugin.Attributes
Imports PersonalUtilities.Tools.Web.Clients Imports PersonalUtilities.Tools.Web.Clients
Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Functions.RegularExpressions
Imports DN = SCrawler.API.Base.DeclaredNames
Namespace API.Facebook Namespace API.Facebook
<Manifest("AndyProgram_Facebook"), SavedPosts, SeparatedTasks(1), SpecialForm(False)> <Manifest("AndyProgram_Facebook"), SavedPosts, SeparatedTasks(1), SpecialForm(False)>
Friend Class SiteSettings : Inherits ThreadsNet.SiteSettings Friend Class SiteSettings : Inherits ThreadsNet.SiteSettings
@@ -18,7 +19,7 @@ Namespace API.Facebook
#Region "Auth" #Region "Auth"
<PropertyOption(AllowNull:=False, ControlText:="Accept", ControlToolTip:="Header 'Accept'", IsAuth:=True), ControlNumber(21), PXML, PClonable> <PropertyOption(AllowNull:=False, ControlText:="Accept", ControlToolTip:="Header 'Accept'", IsAuth:=True), ControlNumber(21), PXML, PClonable>
Friend ReadOnly Property Header_Accept As PropertyValue Friend ReadOnly Property Header_Accept As PropertyValue
<PropertyOption(ControlText:="x-ig-app-id", AllowNull:=True, IsAuth:=True)> <PropertyOption(ControlText:="x-ig-app-id", AllowNull:=True, IsAuth:=True), HiddenControl>
Friend Overrides ReadOnly Property HH_IG_APP_ID As PropertyValue Friend Overrides ReadOnly Property HH_IG_APP_ID As PropertyValue
Get Get
Return __HH_IG_APP_ID Return __HH_IG_APP_ID
@@ -31,11 +32,11 @@ Namespace API.Facebook
End Property End Property
#End Region #End Region
#Region "Defaults" #Region "Defaults"
<PropertyOption(ControlText:="Download photos", IsAuth:=False), PXML, PClonable> <PropertyOption(ControlText:="Download photos", IsAuth:=False, Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property ParsePhotoBlock As PropertyValue Friend ReadOnly Property ParsePhotoBlock As PropertyValue
<PropertyOption(ControlText:="Download videos", IsAuth:=False), PXML, PClonable> <PropertyOption(ControlText:="Download videos", IsAuth:=False, Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property ParseVideoBlock As PropertyValue Friend ReadOnly Property ParseVideoBlock As PropertyValue
<PropertyOption(ControlText:="Download stories", IsAuth:=False), PXML, PClonable> <PropertyOption(ControlText:="Download stories", IsAuth:=False, Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property ParseStoriesBlock As PropertyValue Friend ReadOnly Property ParseStoriesBlock As PropertyValue
#End Region #End Region
#End Region #End Region
@@ -74,7 +75,7 @@ Namespace API.Facebook
#End Region #End Region
#Region "BaseAuthExists, GetUserUrl, GetUserPostUrl, IsMyUser, IsMyImageVideo" #Region "BaseAuthExists, GetUserUrl, GetUserPostUrl, IsMyUser, IsMyImageVideo"
Friend Overrides Function BaseAuthExists() As Boolean Friend Overrides Function BaseAuthExists() As Boolean
Return Responser.CookiesExists And ACheck(HH_IG_APP_ID.Value) And CBool(DownloadData_Impl.Value) Return Responser.CookiesExists And CBool(DownloadData_Impl.Value) 'And ACheck(HH_IG_APP_ID.Value)
End Function End Function
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
Return DirectCast(User, UserData).GetProfileUrl Return DirectCast(User, UserData).GetProfileUrl

View File

@@ -136,6 +136,7 @@ Namespace API.Facebook
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
If CBool(MySettings.DownloadData_Impl.Value) Then If CBool(MySettings.DownloadData_Impl.Value) Then
Try Try
If Responser.Headers.Value(IG.Header_IG_APP_ID).IsEmptyString Then Responser.Headers.Remove(IG.Header_IG_APP_ID)
ResetBaseTokens() ResetBaseTokens()
GetUserTokens(Token) GetUserTokens(Token)
LoadSavePostsKV(True) LoadSavePostsKV(True)
@@ -529,8 +530,14 @@ Namespace API.Facebook
Dim r$ = resp.GetResponse(URL) Dim r$ = resp.GetResponse(URL)
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
If Responser.CookiesExists Then Responser.Cookies.Update(resp.Cookies) If Responser.CookiesExists Then Responser.Cookies.Update(resp.Cookies)
Token_dtsg = RegexReplace(r, Regex_UserToken_dtsg) ParseTokens(r, 0)
Token_lsd = RegexReplace(r, Regex_UserToken_lsd) Dim app_id$ = RegexReplace(r, Regex_AppID)
If Not app_id.IsEmptyString Then
If Not AEquals(Of String)(MySettings.HH_IG_APP_ID.Value, app_id) Then
MySettings.HH_IG_APP_ID.Value = app_id
Responser.Headers.Add(IG.Header_IG_APP_ID, app_id)
End If
End If
Token_Photosby = RegexReplace(r, Regex_Photos_by) Token_Photosby = RegexReplace(r, Regex_Photos_by)
If StoryBucket.IsEmptyString Then StoryBucket = RegexReplace(r, Regex_StoryBucket) If StoryBucket.IsEmptyString Then StoryBucket = RegexReplace(r, Regex_StoryBucket)
If ID.IsEmptyString Then If ID.IsEmptyString Then
@@ -568,14 +575,14 @@ Namespace API.Facebook
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecFetchSite, "none")) .Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecFetchSite, "none"))
.Add("Sec-Fetch-User", "?1") .Add("Sec-Fetch-User", "?1")
.Add("Upgrade-Insecure-Requests", 1) .Add("Upgrade-Insecure-Requests", 1)
Dim h$ = Responser.Headers.Value(IG.Header_Browser) Dim cloneHeader As Action(Of String) = Sub(ByVal hName As String)
If Not h.IsEmptyString Then .Add(IG.Header_Browser, h) Dim hValue$ = Responser.Headers.Value(hName)
h = Responser.Headers.Value(IG.Header_BrowserExt) If Not hValue.IsEmptyString Then .Add(hName, hValue)
If Not h.IsEmptyString Then .Add(IG.Header_BrowserExt, h) End Sub
h = Responser.Headers.Value(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaPlatform)) cloneHeader.Invoke(IG.Header_Browser)
If Not h.IsEmptyString Then .Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaPlatform, h)) cloneHeader.Invoke(IG.Header_BrowserExt)
h = Responser.Headers.Value(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaPlatformVersion)) cloneHeader.Invoke(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaPlatform).Name)
If Not h.IsEmptyString Then .Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaPlatformVersion, h)) cloneHeader.Invoke(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaPlatformVersion).Name)
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaMobile, "?0")) .Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaMobile, "?0"))
.Add("Sec-Ch-Ua-Model", "") .Add("Sec-Ch-Ua-Model", "")
End With End With

View File

@@ -18,6 +18,8 @@ Namespace API.Instagram
Friend ReadOnly ObtainMedia_SizeFuncPic_RegexP As RParams = RParams.DMS("_p(\d+)x(\d+)", 1, EDP.ReturnValue) Friend ReadOnly ObtainMedia_SizeFuncPic_RegexP As RParams = RParams.DMS("_p(\d+)x(\d+)", 1, EDP.ReturnValue)
Friend ReadOnly ObtainMedia_SizeFuncPic_RegexS As RParams = RParams.DMS("_s(\d+)x(\d+)", 1, EDP.ReturnValue) Friend ReadOnly ObtainMedia_SizeFuncPic_RegexS As RParams = RParams.DMS("_s(\d+)x(\d+)", 1, EDP.ReturnValue)
Friend Const PageTokenRegexPatternDefault As String = "\[\],{""token"":""(.*?)""},\d+\]" Friend Const PageTokenRegexPatternDefault As String = "\[\],{""token"":""(.*?)""},\d+\]"
Friend ReadOnly Regex_UserToken_dtsg As RParams = RParams.DMS("DTSGInitialData["":,.\[\]]*?{\s*.token.:\s*""([^""]+)", 1, EDP.ReturnValue)
Friend ReadOnly Regex_UserToken_lsd As RParams = RParams.DMS("LSD["":,.\[\]]*?{\s*.token.:\s*""([^""]+)", 1, EDP.ReturnValue)
Friend Sub UpdateResponser(ByVal Source As IResponse, ByRef Destination As Responser, ByVal UpdateWwwClaim As Boolean) Friend Sub UpdateResponser(ByVal Source As IResponse, ByRef Destination As Responser, ByVal UpdateWwwClaim As Boolean)
Const r_wwwClaimName$ = "x-ig-set-www-claim" Const r_wwwClaimName$ = "x-ig-set-www-claim"
Const r_tokenName$ = SiteSettings.Header_CSRF_TOKEN_COOKIE Const r_tokenName$ = SiteSettings.Header_CSRF_TOKEN_COOKIE

View File

@@ -14,6 +14,7 @@ Imports PersonalUtilities.Functions.RegularExpressions
Imports PersonalUtilities.Tools.Web.Clients Imports PersonalUtilities.Tools.Web.Clients
Imports PersonalUtilities.Tools.Web.Cookies Imports PersonalUtilities.Tools.Web.Cookies
Imports Download = SCrawler.Plugin.ISiteSettings.Download Imports Download = SCrawler.Plugin.ISiteSettings.Download
Imports DN = SCrawler.API.Base.DeclaredNames
Namespace API.Instagram Namespace API.Instagram
<Manifest(InstagramSiteKey), SeparatedTasks(1), SavedPosts, SpecialForm(False)> <Manifest(InstagramSiteKey), SeparatedTasks(1), SavedPosts, SpecialForm(False)>
Friend Class SiteSettings : Inherits SiteSettingsBase Friend Class SiteSettings : Inherits SiteSettingsBase
@@ -54,6 +55,9 @@ Namespace API.Instagram
End Function End Function
End Class End Class
#End Region #End Region
#Region "Categories"
Private Const CAT_DOWN As String = "Download data"
#End Region
#Region "Authorization properties" #Region "Authorization properties"
Friend Const Header_IG_APP_ID As String = "x-ig-app-id" Friend Const Header_IG_APP_ID As String = "x-ig-app-id"
Friend Const Header_IG_WWW_CLAIM As String = "x-ig-www-claim" Friend Const Header_IG_WWW_CLAIM As String = "x-ig-www-claim"
@@ -65,6 +69,10 @@ Namespace API.Instagram
Friend Const Header_Platform_Verion As String = "Sec-Ch-Ua-Platform-Version" Friend Const Header_Platform_Verion As String = "Sec-Ch-Ua-Platform-Version"
<PropertyOption(ControlText:="x-csrftoken", ControlToolTip:="Can be automatically extracted from cookies", IsAuth:=True, AllowNull:=True), ControlNumber(2), PClonable(Clone:=False)> <PropertyOption(ControlText:="x-csrftoken", ControlToolTip:="Can be automatically extracted from cookies", IsAuth:=True, AllowNull:=True), ControlNumber(2), PClonable(Clone:=False)>
Friend ReadOnly Property HH_CSRF_TOKEN As PropertyValue Friend ReadOnly Property HH_CSRF_TOKEN As PropertyValue
<CookieValueExtractor(NameOf(HH_CSRF_TOKEN))>
Private Function GetValueFromCookies(ByVal PropName As String, ByVal c As CookieKeeper) As String
Return c.GetCookieValue(Header_CSRF_TOKEN_COOKIE, PropName, NameOf(HH_CSRF_TOKEN))
End Function
<PropertyOption(ControlText:="x-ig-app-id", IsAuth:=True, AllowNull:=False), ControlNumber(3), PClonable(Clone:=False)> <PropertyOption(ControlText:="x-ig-app-id", IsAuth:=True, AllowNull:=False), ControlNumber(3), PClonable(Clone:=False)>
Friend ReadOnly Property HH_IG_APP_ID As PropertyValue Friend ReadOnly Property HH_IG_APP_ID As PropertyValue
<PropertyOption(ControlText:="x-asbd-id", IsAuth:=True, AllowNull:=True), ControlNumber(4), PClonable(Clone:=False)> <PropertyOption(ControlText:="x-asbd-id", IsAuth:=True, AllowNull:=True), ControlNumber(4), PClonable(Clone:=False)>
@@ -139,10 +147,19 @@ Namespace API.Instagram
Friend ReadOnly Property USE_GQL As PropertyValue Friend ReadOnly Property USE_GQL As PropertyValue
#End Region #End Region
#Region "Download properties" #Region "Download properties"
<PropertyOption(ControlText:="DownDetector",
ControlToolTip:="Use 'DownDetector' to determine if the site is accessible. -1 to disable." & vbCr &
"The value represents the average number of error reports over the last 4 hours"),
PClonable, PXML, ControlNumber(17)>
Private ReadOnly Property DownDetectorValue As PropertyValue
<Provider(NameOf(DownDetectorValue), FieldsChecker:=True)>
Private ReadOnly Property DownDetectorValueProvider As IFormatProvider
<PropertyOption(ControlText:="Add 'DownDetector' information to the log."), PClonable, PXML, ControlNumber(18), HiddenControl>
Private ReadOnly Property DownDetectorValueAddToLog As PropertyValue
Friend Const TimersUrgentTip As String = vbCr & "It is highly recommended not to change the default value." Friend Const TimersUrgentTip As String = vbCr & "It is highly recommended not to change the default value."
<PropertyOption(ControlText:="Request timer (any)", <PropertyOption(ControlText:="Request timer (any)",
ControlToolTip:="The timer (in milliseconds) that SCrawler should wait before executing the next request." & ControlToolTip:="The timer (in milliseconds) that SCrawler should wait before executing the next request." &
vbCr & "The default value is 1'000." & vbCr & "The minimum value is 0." & TimersUrgentTip, AllowNull:=False), vbCr & "The default value is 1'000." & vbCr & "The minimum value is 0." & TimersUrgentTip, AllowNull:=False, Category:=DN.CAT_Timers),
PXML, ControlNumber(19), PClonable> PXML, ControlNumber(19), PClonable>
Friend ReadOnly Property RequestsWaitTimer_Any As PropertyValue Friend ReadOnly Property RequestsWaitTimer_Any As PropertyValue
<Provider(NameOf(RequestsWaitTimer_Any), FieldsChecker:=True)> <Provider(NameOf(RequestsWaitTimer_Any), FieldsChecker:=True)>
@@ -150,33 +167,33 @@ Namespace API.Instagram
<PropertyOption(ControlText:="Request timer", <PropertyOption(ControlText:="Request timer",
ControlToolTip:="The time value (in milliseconds) that the program will wait before processing the next 'Request time counter' request." & ControlToolTip:="The time value (in milliseconds) that the program will wait before processing the next 'Request time counter' request." &
vbCr & "The default value is 1'000." & vbCr & "The minimum value is 100." & TimersUrgentTip, vbCr & "The default value is 1'000." & vbCr & "The minimum value is 100." & TimersUrgentTip,
AllowNull:=False), PXML, ControlNumber(20), PClonable> AllowNull:=False, Category:=DN.CAT_Timers), PXML, ControlNumber(20), PClonable>
Friend ReadOnly Property RequestsWaitTimer As PropertyValue Friend ReadOnly Property RequestsWaitTimer As PropertyValue
<Provider(NameOf(RequestsWaitTimer), FieldsChecker:=True)> <Provider(NameOf(RequestsWaitTimer), FieldsChecker:=True)>
Private ReadOnly Property RequestsWaitTimerProvider As IFormatProvider Private ReadOnly Property RequestsWaitTimerProvider As IFormatProvider
<PropertyOption(ControlText:="Request timer counter", <PropertyOption(ControlText:="Request timer counter",
ControlToolTip:="How many requests will be sent to Instagram before the program waits 'Request timer'." & ControlToolTip:="How many requests will be sent to Instagram before the program waits 'Request timer'." &
vbCr & "The default value is 1." & vbCr & "The minimum value is 1." & TimersUrgentTip, vbCr & "The default value is 1." & vbCr & "The minimum value is 1." & TimersUrgentTip,
AllowNull:=False, LeftOffset:=120), PXML, ControlNumber(21), PClonable> AllowNull:=False, LeftOffset:=120, Category:=DN.CAT_Timers), PXML, ControlNumber(21), PClonable>
Friend ReadOnly Property RequestsWaitTimerTaskCount As PropertyValue Friend ReadOnly Property RequestsWaitTimerTaskCount As PropertyValue
<Provider(NameOf(RequestsWaitTimerTaskCount), FieldsChecker:=True)> <Provider(NameOf(RequestsWaitTimerTaskCount), FieldsChecker:=True)>
Private ReadOnly Property RequestsWaitTimerTaskCountProvider As IFormatProvider Private ReadOnly Property RequestsWaitTimerTaskCountProvider As IFormatProvider
<PropertyOption(ControlText:="Posts limit timer", <PropertyOption(ControlText:="Posts limit timer",
ControlToolTip:="The time value (in milliseconds) the program will wait before processing the next request after 195 requests." & ControlToolTip:="The time value (in milliseconds) the program will wait before processing the next request after 195 requests." &
vbCr & "The default value is 60'000." & vbCr & "The minimum value is 10'000." & TimersUrgentTip, vbCr & "The default value is 60'000." & vbCr & "The minimum value is 10'000." & TimersUrgentTip,
AllowNull:=False), PXML, ControlNumber(22), PClonable> AllowNull:=False, Category:=DN.CAT_Timers), PXML, ControlNumber(22), PClonable>
Friend ReadOnly Property SleepTimerOnPostsLimit As PropertyValue Friend ReadOnly Property SleepTimerOnPostsLimit As PropertyValue
<Provider(NameOf(SleepTimerOnPostsLimit), FieldsChecker:=True)> <Provider(NameOf(SleepTimerOnPostsLimit), FieldsChecker:=True)>
Private ReadOnly Property SleepTimerOnPostsLimitProvider As IFormatProvider Private ReadOnly Property SleepTimerOnPostsLimitProvider As IFormatProvider
<PropertyOption(ControlText:="Get timeline", ControlToolTip:="Default value for new users"), PXML, ControlNumber(23), PClonable> <PropertyOption(ControlText:="Get timeline", ControlToolTip:="Default value for new users", Category:=DN.CAT_UserDefs), PXML, ControlNumber(23), PClonable>
Friend ReadOnly Property GetTimeline As PropertyValue Friend ReadOnly Property GetTimeline As PropertyValue
<PropertyOption(ControlText:="Get reels", ControlToolTip:="Default value for new users"), PXML, ControlNumber(24), PClonable> <PropertyOption(ControlText:="Get reels", ControlToolTip:="Default value for new users", Category:=DN.CAT_UserDefs), PXML, ControlNumber(24), PClonable>
Friend ReadOnly Property GetReels As PropertyValue Friend ReadOnly Property GetReels As PropertyValue
<PropertyOption(ControlText:="Get stories", ControlToolTip:="Default value for new users"), PXML, ControlNumber(25), PClonable> <PropertyOption(ControlText:="Get stories", ControlToolTip:="Default value for new users", Category:=DN.CAT_UserDefs), PXML, ControlNumber(25), PClonable>
Friend ReadOnly Property GetStories As PropertyValue Friend ReadOnly Property GetStories As PropertyValue
<PropertyOption(ControlText:="Get stories: user", ControlToolTip:="Default value for new users"), PXML, ControlNumber(26), PClonable> <PropertyOption(ControlText:="Get stories: user", ControlToolTip:="Default value for new users", Category:=DN.CAT_UserDefs), PXML, ControlNumber(26), PClonable>
Friend ReadOnly Property GetStoriesUser As PropertyValue Friend ReadOnly Property GetStoriesUser As PropertyValue
<PropertyOption(ControlText:="Get tagged photos", ControlToolTip:="Default value for new users"), PXML, ControlNumber(27), PClonable> <PropertyOption(ControlText:="Get tagged photos", ControlToolTip:="Default value for new users", Category:=DN.CAT_UserDefs), PXML, ControlNumber(27), PClonable>
Friend ReadOnly Property GetTagged As PropertyValue Friend ReadOnly Property GetTagged As PropertyValue
<PropertyOption(ControlText:="Tagged notify limit", <PropertyOption(ControlText:="Tagged notify limit",
ControlToolTip:="If the number of tagged posts exceeds this number you will be notified." & vbCr & ControlToolTip:="If the number of tagged posts exceeds this number you will be notified." & vbCr &
@@ -186,19 +203,19 @@ Namespace API.Instagram
Private ReadOnly Property TaggedNotifyLimitProvider As IFormatProvider Private ReadOnly Property TaggedNotifyLimitProvider As IFormatProvider
#End Region #End Region
#Region "Download ready" #Region "Download ready"
<PropertyOption(ControlText:="Download timeline", ControlToolTip:="Download timeline"), PXML, ControlNumber(10), PClonable> <PropertyOption(ControlText:="Download timeline", ControlToolTip:="Download timeline", Category:=CAT_DOWN), PXML, ControlNumber(10), PClonable>
Friend ReadOnly Property DownloadTimeline As PropertyValue Friend ReadOnly Property DownloadTimeline As PropertyValue
<PXML> Private ReadOnly Property DownloadTimeline_Def As PropertyValue <PXML> Private ReadOnly Property DownloadTimeline_Def As PropertyValue
<PropertyOption(ControlText:="Download reels", ControlToolTip:="Download reels"), PXML, ControlNumber(11), PClonable> <PropertyOption(ControlText:="Download reels", ControlToolTip:="Download reels", Category:=CAT_DOWN), PXML, ControlNumber(11), PClonable>
Friend ReadOnly Property DownloadReels As PropertyValue Friend ReadOnly Property DownloadReels As PropertyValue
<PXML> Private ReadOnly Property DownloadReels_Def As PropertyValue <PXML> Private ReadOnly Property DownloadReels_Def As PropertyValue
<PropertyOption(ControlText:="Download stories", ControlToolTip:="Download stories"), PXML, ControlNumber(12), PClonable> <PropertyOption(ControlText:="Download stories", ControlToolTip:="Download stories", Category:=CAT_DOWN), PXML, ControlNumber(12), PClonable>
Friend ReadOnly Property DownloadStories As PropertyValue Friend ReadOnly Property DownloadStories As PropertyValue
<PXML> Private ReadOnly Property DownloadStories_Def As PropertyValue <PXML> Private ReadOnly Property DownloadStories_Def As PropertyValue
<PropertyOption(ControlText:="Download stories: user", ControlToolTip:="Download stories (user)"), PXML, ControlNumber(13), PClonable> <PropertyOption(ControlText:="Download stories: user", ControlToolTip:="Download stories (user)", Category:=CAT_DOWN), PXML, ControlNumber(13), PClonable>
Friend ReadOnly Property DownloadStoriesUser As PropertyValue Friend ReadOnly Property DownloadStoriesUser As PropertyValue
<PXML> Private ReadOnly Property DownloadStoriesUser_Def As PropertyValue <PXML> Private ReadOnly Property DownloadStoriesUser_Def As PropertyValue
<PropertyOption(ControlText:="Download tagged", ControlToolTip:="Download tagged posts"), PXML, ControlNumber(14), PClonable> <PropertyOption(ControlText:="Download tagged", ControlToolTip:="Download tagged posts", Category:=CAT_DOWN), PXML, ControlNumber(14), PClonable>
Friend ReadOnly Property DownloadTagged As PropertyValue Friend ReadOnly Property DownloadTagged As PropertyValue
<PXML> Private ReadOnly Property DownloadTagged_Def As PropertyValue <PXML> Private ReadOnly Property DownloadTagged_Def As PropertyValue
#End Region #End Region
@@ -348,8 +365,11 @@ Namespace API.Instagram
platform = .Value(Header_Platform_Verion) platform = .Value(Header_Platform_Verion)
End If End If
'.Add(Header_IG_WWW_CLAIM, 0) '.Add(Header_IG_WWW_CLAIM, 0)
.Add("Origin", "https://www.instagram.com")
.Add("authority", "www.instagram.com")
.Add("Dnt", 1) .Add("Dnt", 1)
.Add("Dpr", 1) '.Add("Dpr", 1)
.Remove("Dpr")
.Add("Sec-Ch-Ua-Mobile", "?0") .Add("Sec-Ch-Ua-Mobile", "?0")
.Add("Sec-Ch-Ua-Model", """""") .Add("Sec-Ch-Ua-Model", """""")
.Add("Sec-Ch-Ua-Platform", """Windows""") .Add("Sec-Ch-Ua-Platform", """Windows""")
@@ -392,6 +412,9 @@ Namespace API.Instagram
DownloadTagged = New PropertyValue(False) DownloadTagged = New PropertyValue(False)
DownloadTagged_Def = New PropertyValue(DownloadTagged.Value, GetType(Boolean)) DownloadTagged_Def = New PropertyValue(DownloadTagged.Value, GetType(Boolean))
DownDetectorValue = New PropertyValue(20)
DownDetectorValueProvider = New TimersChecker(-1)
DownDetectorValueAddToLog = New PropertyValue(False)
RequestsWaitTimer_Any = New PropertyValue(1000) RequestsWaitTimer_Any = New PropertyValue(1000)
RequestsWaitTimer_AnyProvider = New TimersChecker(0) RequestsWaitTimer_AnyProvider = New TimersChecker(0)
RequestsWaitTimer = New PropertyValue(1000) RequestsWaitTimer = New PropertyValue(1000)
@@ -409,7 +432,7 @@ Namespace API.Instagram
TaggedNotifyLimit = New PropertyValue(200) TaggedNotifyLimit = New PropertyValue(200)
TaggedNotifyLimitProvider = New TaggedNotifyLimitChecker TaggedNotifyLimitProvider = New TaggedNotifyLimitChecker
DownloadingErrorDate = New PropertyValue(Now.AddYears(10), GetType(Date)) DownloadingErrorDate = New PropertyValue(Now.AddYears(-10), GetType(Date))
LastDownloadDate = New PropertyValue(Now.AddDays(-1)) LastDownloadDate = New PropertyValue(Now.AddDays(-1))
LastRequestsCount = New PropertyValue(0) LastRequestsCount = New PropertyValue(0)
LastRequestsCountLabel = New PropertyValue(String.Empty, GetType(String)) LastRequestsCountLabel = New PropertyValue(String.Empty, GetType(String))
@@ -423,6 +446,12 @@ Namespace API.Instagram
Friend Overrides Sub EndInit() Friend Overrides Sub EndInit()
Try : MyLastRequests.Add(LastDownloadDate.Value, LastRequestsCount.Value) : Catch : End Try Try : MyLastRequests.Add(LastDownloadDate.Value, LastRequestsCount.Value) : Catch : End Try
If Not CBool(HH_IG_WWW_CLAIM_USE.Value) Then Responser.Headers.Remove(Header_IG_WWW_CLAIM) If Not CBool(HH_IG_WWW_CLAIM_USE.Value) Then Responser.Headers.Remove(Header_IG_WWW_CLAIM)
If CInt(SettingsVersion.Value) < 2 Then
SettingsVersion.Value = 2
HH_IG_WWW_CLAIM_UPDATE_INTERVAL.Value = 120
HH_IG_WWW_CLAIM_USE_DEFAULT_ALGO.Value = 1
HH_IG_WWW_CLAIM_RESET_EACH_TARGET.Value = 0
End If
MyBase.EndInit() MyBase.EndInit()
End Sub End Sub
#End Region #End Region
@@ -452,17 +481,101 @@ Namespace API.Instagram
End Function End Function
#End Region #End Region
#Region "Downloading" #Region "Downloading"
Private ____DownloadStarted As Boolean = False
Private ____AvailableRequested As Boolean = False
Private ____AvailableSilent As Boolean = True
Private ____AvailableChecked As Boolean = False
Private ____AvailableResult As Boolean = False
Private Sub ResetDownloadOptions()
If ActiveJobs < 1 Then
____DownloadStarted = False
____AvailableRequested = False
____AvailableChecked = False
____AvailableSilent = True
____AvailableResult = False
If ActiveSessionRequestsExists Then RefreshMyLastRequests(Now)
ActiveSessionRequestsExists = False
_NextWNM = UserData.WNM.Notify
_NextTagged = True
SkipUntilNextSession = False
AvailableText = String.Empty
ActiveJobs = 0
End If
End Sub
Friend Overrides Function Available(ByVal What As Download, ByVal Silent As Boolean) As Boolean
If MyBase.Available(What, Silent) And ActiveJobs < 2 Then
If CInt(DownDetectorValue.Value) >= 0 Then
If ____DownloadStarted Then
____AvailableRequested = True
____AvailableSilent = Silent
Return True
Else
Return AvailableImpl(What, Silent)
End If
Else
Return True
End If
Else
Return False
End If
End Function
#Disable Warning IDE0060
Private Function AvailableImpl(ByVal What As Download, ByVal Silent As Boolean) As Boolean
#Enable Warning
Try
AvailableText = String.Empty
If CInt(DownDetectorValue.Value) = -1 Then
Return True
Else
Dim dl As List(Of DownDetector.Data) = DownDetector.GetData("instagram")
If dl.ListExists Then
dl = dl.Take(4).ToList
Dim avg% = dl.Average(Function(d) d.Value)
If avg > CInt(DownDetectorValue.Value) Then
AvailableText = "Over the past hour, Instagram has received an average of " &
avg.NumToString(New ANumbers With {.FormatOptions = ANumbers.Options.GroupIntegral}) & " outage reports:" & vbCr &
dl.ListToString(vbCr)
If CBool(DownDetectorValueAddToLog.Value) Then MyMainLOG = AvailableText
If Silent Then
Return False
Else
Return MsgBoxE({$"{AvailableText}{vbCr}{vbCr}Do you want to continue parsing Instagram data?",
"There are outage reports on Instagram"}, vbYesNo) = vbYes
End If
End If
End If
Return True
End If
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, "[API.Instagram.SiteSettings.Available]", True)
End Try
End Function
Friend Property SkipUntilNextSession As Boolean = False Friend Property SkipUntilNextSession As Boolean = False
Friend Overrides Function ReadyToDownload(ByVal What As Download) As Boolean Friend Overrides Function ReadyToDownload(ByVal What As Download) As Boolean
Return ActiveJobs < 2 AndAlso Not SkipUntilNextSession AndAlso ReadyForDownload AndAlso BaseAuthExists() AndAlso DownloadTimeline.Value If ActiveJobs < 2 AndAlso Not SkipUntilNextSession AndAlso ReadyForDownload AndAlso BaseAuthExists() AndAlso CBool(DownloadTimeline.Value) Then
If ____DownloadStarted And ____AvailableRequested Then
____AvailableResult = AvailableImpl(What, ____AvailableSilent)
____AvailableChecked = True
____AvailableRequested = False
Return ____AvailableResult
ElseIf ____AvailableChecked Then
Return ____AvailableResult
Else
Return True
End If
Else
Return False
End If
End Function End Function
Private ActiveJobs As Integer = 0 Private ActiveJobs As Integer = 0
Private ActiveSessionDate As Date Private ActiveSessionDate As Date
Private ActiveSessionRequestsExists As Boolean = False
Private _NextWNM As UserData.WNM = UserData.WNM.Notify Private _NextWNM As UserData.WNM = UserData.WNM.Notify
Private _NextTagged As Boolean = True Private _NextTagged As Boolean = True
Friend Overrides Sub DownloadStarted(ByVal What As Download) Friend Overrides Sub DownloadStarted(ByVal What As Download)
ResetDownloadOptions()
ActiveJobs += 1 ActiveJobs += 1
If ActiveJobs = 1 Then ActiveSessionDate = Now If ActiveJobs = 1 Then ____DownloadStarted = True : ActiveSessionDate = Now
If Not HH_IG_WWW_CLAIM_IS_ZERO AndAlso If Not HH_IG_WWW_CLAIM_IS_ZERO AndAlso
( (
(CBool(HH_IG_WWW_CLAIM_USE_DEFAULT_ALGO.Value) AndAlso MyLastRequestsDate.AddMinutes(HH_IG_WWW_CLAIM_UPDATE_INTERVAL.Value) < Now) Or (CBool(HH_IG_WWW_CLAIM_USE_DEFAULT_ALGO.Value) AndAlso MyLastRequestsDate.AddMinutes(HH_IG_WWW_CLAIM_UPDATE_INTERVAL.Value) < Now) Or
@@ -494,6 +607,7 @@ Namespace API.Instagram
If _NextWNM = UserData.WNM.SkipTemp Or _NextWNM = UserData.WNM.SkipCurrent Then _NextWNM = UserData.WNM.Notify If _NextWNM = UserData.WNM.SkipTemp Or _NextWNM = UserData.WNM.SkipCurrent Then _NextWNM = UserData.WNM.Notify
_NextTagged = .TaggedCheckSession _NextTagged = .TaggedCheckSession
MyLastRequestsCount = .RequestsCountSession MyLastRequestsCount = .RequestsCountSession
If .RequestsCountSession > 0 Then ActiveSessionRequestsExists = True
_FieldsChangerSuspended = True _FieldsChangerSuspended = True
HH_IG_WWW_CLAIM.Value = Responser.Headers.Value(Header_IG_WWW_CLAIM) HH_IG_WWW_CLAIM.Value = Responser.Headers.Value(Header_IG_WWW_CLAIM)
HH_CSRF_TOKEN.Value = Responser.Headers.Value(Header_CSRF_TOKEN) HH_CSRF_TOKEN.Value = Responser.Headers.Value(Header_CSRF_TOKEN)
@@ -501,11 +615,8 @@ Namespace API.Instagram
End With End With
End Sub End Sub
Friend Overrides Sub DownloadDone(ByVal What As Download) Friend Overrides Sub DownloadDone(ByVal What As Download)
_NextWNM = UserData.WNM.Notify
_NextTagged = True
RefreshMyLastRequests(Now)
ActiveJobs -= 1 ActiveJobs -= 1
SkipUntilNextSession = False ResetDownloadOptions()
End Sub End Sub
#End Region #End Region
#Region "Settings" #Region "Settings"
@@ -557,7 +668,7 @@ Namespace API.Instagram
If vals.Any(Function(v) Not v.ValueOld = v.ValueNew) OrElse If vals.Any(Function(v) Not v.ValueOld = v.ValueNew) OrElse
Not Responser.Cookies.ListEquals(____Cookies) Then HH_IG_WWW_CLAIM.Value = 0 : credentialsUpdated = True Not Responser.Cookies.ListEquals(____Cookies) Then HH_IG_WWW_CLAIM.Value = 0 : credentialsUpdated = True
If Responser.CookiesExists Then If Responser.CookiesExists Then
Dim csrf$ = If(Responser.Cookies.FirstOrDefault(Function(c) c.Name.StringToLower = Header_CSRF_TOKEN_COOKIE)?.Value, String.Empty) Dim csrf$ = GetValueFromCookies(NameOf(HH_CSRF_TOKEN), Responser.Cookies)
If Not csrf.IsEmptyString Then If Not csrf.IsEmptyString Then
If Not AEquals(Of String)(CStr(HH_CSRF_TOKEN.Value), csrf) Then credentialsUpdated = True If Not AEquals(Of String)(CStr(HH_CSRF_TOKEN.Value), csrf) Then credentialsUpdated = True
HH_CSRF_TOKEN.Value = csrf HH_CSRF_TOKEN.Value = csrf

View File

@@ -297,37 +297,51 @@ Namespace API.Instagram
End With End With
End With End With
Dim r$ = Responser.GetResponse(MySiteSettings.GetUserUrl(Me)) Dim r$ = Responser.GetResponse(MySiteSettings.GetUserUrl(Me))
If Not r.IsEmptyString Then ParseTokens(r, 0)
Dim rr As RParams = RParams.DM(PageTokenRegexPatternDefault, 0, RegexReturn.List, EDP.ReturnValue)
Dim tokens As List(Of String) = RegexReplace(r, rr)
Dim tt$, ttVal$
If tokens.ListExists Then
With rr
.Match = Nothing
.MatchSub = 1
.WhatGet = RegexReturn.Value
End With
For Each tt In tokens
If Not Token_lsd.IsEmptyString And Not Token_dtsg.IsEmptyString Then
Exit For
Else
ttVal = RegexReplace(tt, rr)
If Not ttVal.IsEmptyString Then
If ttVal.Contains(":") Then
If Token_dtsg.IsEmptyString Then Token_dtsg = ttVal
Else
If Token_lsd.IsEmptyString Then Token_lsd = ttVal
End If
End If
End If
Next
End If
End If
Catch ex As Exception Catch ex As Exception
Finally Finally
ChangeResponserMode(_UseGQL, Not _UseGQL) ChangeResponserMode(_UseGQL, Not _UseGQL)
End Try End Try
End Sub End Sub
Protected Sub ParseTokens(ByVal r As String, ByVal Attempt As Integer)
Try
If Not r.IsEmptyString Then
ResetBaseTokens()
Select Case Attempt
Case 0
Dim rr As RParams = RParams.DM(PageTokenRegexPatternDefault, 0, RegexReturn.List, EDP.ReturnValue)
Dim tokens As List(Of String) = RegexReplace(r, rr)
Dim tt$, ttVal$
If tokens.ListExists Then
With rr
.Match = Nothing
.MatchSub = 1
.WhatGet = RegexReturn.Value
End With
For Each tt In tokens
If Not Token_lsd.IsEmptyString And Not Token_dtsg.IsEmptyString Then
Exit For
Else
ttVal = RegexReplace(tt, rr)
If Not ttVal.IsEmptyString Then
If ttVal.Contains(":") Then
If Token_dtsg.IsEmptyString Then Token_dtsg = ttVal
Else
If Token_lsd.IsEmptyString Then Token_lsd = ttVal
End If
End If
End If
Next
End If
Case 1
Token_dtsg = RegexReplace(r, Regex_UserToken_dtsg)
Token_lsd = RegexReplace(r, Regex_UserToken_lsd)
End Select
If Not ValidateBaseTokens() And Attempt = 0 Then ParseTokens(r, Attempt + 1)
End If
Catch
End Try
End Sub
#End Region #End Region
End Class End Class
End Namespace End Namespace

View File

@@ -862,15 +862,20 @@ NextPageBlock:
Protected DefaultParser_IgnorePass As Boolean = False Protected DefaultParser_IgnorePass As Boolean = False
Private ReadOnly DefaultParser_PostUrlCreator_Default As Func(Of PostKV, String) = Function(post) $"https://www.instagram.com/p/{post.Code}/" Private ReadOnly DefaultParser_PostUrlCreator_Default As Func(Of PostKV, String) = Function(post) $"https://www.instagram.com/p/{post.Code}/"
Protected DefaultParser_PostUrlCreator As Func(Of PostKV, String) = Function(post) $"https://www.instagram.com/p/{post.Code}/" Protected DefaultParser_PostUrlCreator As Func(Of PostKV, String) = Function(post) $"https://www.instagram.com/p/{post.Code}/"
Protected DefaultParser_Pinned As Func(Of IEnumerable(Of EContainer), Integer, Boolean) = Nothing
Protected DefaultParser_SkipPost As Func(Of IEnumerable(Of EContainer), Integer, PostKV, Boolean) = Nothing
Protected Function DefaultParser(ByVal Items As IEnumerable(Of EContainer), ByVal Section As Sections, ByVal Token As CancellationToken, Protected Function DefaultParser(ByVal Items As IEnumerable(Of EContainer), ByVal Section As Sections, ByVal Token As CancellationToken,
Optional ByVal SpecFolder As String = Nothing, Optional ByVal State As UStates = UStates.Unknown, Optional ByVal SpecFolder As String = Nothing, Optional ByVal State As UStates = UStates.Unknown,
Optional ByVal Attempts As Integer = 0) As Boolean Optional ByVal Attempts As Integer = 0) As Boolean
ThrowAny(Token) ThrowAny(Token)
If Items.Count > 0 Then If Items.ListExists Then
Dim PostIDKV As PostKV Dim PostIDKV As PostKV
Dim Pinned As Boolean Dim Pinned As Boolean
Dim PostDate$, PostOriginUrl$ Dim PostDate$, PostOriginUrl$
Dim before% Dim i%, before%
Dim usePinFunc As Boolean = Not DefaultParser_Pinned Is Nothing
Dim skipPostFuncExists As Boolean = Not DefaultParser_SkipPost Is Nothing
Dim nn As EContainer
If SpecFolder.IsEmptyString Then If SpecFolder.IsEmptyString Then
Select Case Section Select Case Section
Case Sections.Tagged : SpecFolder = TaggedFolder Case Sections.Tagged : SpecFolder = TaggedFolder
@@ -879,14 +884,21 @@ NextPageBlock:
End Select End Select
End If End If
ProgressPre.ChangeMax(Items.Count) ProgressPre.ChangeMax(Items.Count)
For Each nn In Items For i = 0 To Items.Count - 1
nn = Items(i)
ProgressPre.Perform() ProgressPre.Perform()
With If(Not DefaultParser_ElemNode Is Nothing, nn.ItemF(DefaultParser_ElemNode), nn) With If(Not DefaultParser_ElemNode Is Nothing, nn.ItemF(DefaultParser_ElemNode), nn)
If .ListExists Then If .ListExists Then
PostIDKV = New PostKV(.Value("code"), .Value("id"), Section) PostIDKV = New PostKV(.Value("code"), .Value("id"), Section)
PostOriginUrl = DefaultParser_PostUrlCreator(PostIDKV) PostOriginUrl = DefaultParser_PostUrlCreator(PostIDKV)
Pinned = .Contains("timeline_pinned_user_ids") 'Pinned = .Contains("timeline_pinned_user_ids")
If Not DefaultParser_IgnorePass AndAlso PostKvExists(PostIDKV) Then If usePinFunc Then
Pinned = DefaultParser_Pinned.Invoke(Items, i)
Else
Pinned = If(.Item("timeline_pinned_user_ids")?.Count, 0) > 0
End If
If skipPostFuncExists AndAlso DefaultParser_SkipPost.Invoke(Items, i, PostIDKV) Then
ElseIf Not DefaultParser_IgnorePass AndAlso PostKvExists(PostIDKV) Then
If Not Section = Sections.Timeline OrElse Not Pinned Then Return False If Not Section = Sections.Timeline OrElse Not Pinned Then Return False
Else Else
_TempPostsList.Add(PostIDKV.ID) _TempPostsList.Add(PostIDKV.ID)
@@ -1269,6 +1281,9 @@ NextPageBlock:
ElseIf Responser.StatusCode = 560 Or Responser.StatusCode = HttpStatusCode.InternalServerError Then '560, 500 ElseIf Responser.StatusCode = 560 Or Responser.StatusCode = HttpStatusCode.InternalServerError Then '560, 500
MySiteSettings.SkipUntilNextSession = True MySiteSettings.SkipUntilNextSession = True
Err5xx = Responser.StatusCode Err5xx = Responser.StatusCode
ElseIf Responser.StatusCode = -1 And Responser.Status = -1 Then
MySiteSettings.SkipUntilNextSession = True
Err5xx = Responser.StatusCode
Else Else
MyMainLOG = $"Something is wrong. Your credentials may have expired [{CInt(Responser.StatusCode)}/{CInt(Responser.Status)}]: {ToString()} [{s}]" MyMainLOG = $"Something is wrong. Your credentials may have expired [{CInt(Responser.StatusCode)}/{CInt(Responser.Status)}]: {ToString()} [{s}]"
DisableSection(s) DisableSection(s)

View File

@@ -20,6 +20,10 @@ Namespace API.JustForFans
Friend ReadOnly Property UserID As PropertyValue Friend ReadOnly Property UserID As PropertyValue
<PropertyOption, PXML, PClonable(Clone:=False)> <PropertyOption, PXML, PClonable(Clone:=False)>
Friend ReadOnly Property UserHash4 As PropertyValue Friend ReadOnly Property UserHash4 As PropertyValue
<CookieValueExtractor(NameOf(UserHash4))>
Private Function GetValueFromCookies(ByVal PropName As String, ByVal c As CookieKeeper) As String
Return c.GetCookieValue(UserHash4_CookieName, PropName, NameOf(UserHash4))
End Function
<PropertyOption(ControlText:="Accept", ControlToolTip:="Header 'Accept'"), PClonable> <PropertyOption(ControlText:="Accept", ControlToolTip:="Header 'Accept'"), PClonable>
Friend ReadOnly Property HeaderAccept As PropertyValue Friend ReadOnly Property HeaderAccept As PropertyValue
<PropertyOption(InheritanceName:=SettingsCLS.HEADER_DEF_UserAgent), PClonable, PXML(OnlyForChecked:=True)> <PropertyOption(InheritanceName:=SettingsCLS.HEADER_DEF_UserAgent), PClonable, PXML(OnlyForChecked:=True)>
@@ -61,7 +65,7 @@ Namespace API.JustForFans
Private Sub UpdateUserHash4() Private Sub UpdateUserHash4()
If Responser.CookiesExists Then If Responser.CookiesExists Then
Dim hv_current$ = UserHash4.Value Dim hv_current$ = UserHash4.Value
Dim hv_cookie$ = If(Responser.Cookies.FirstOrDefault(Function(cc) cc.Name.ToLower = UserHash4_CookieName)?.Value, String.Empty) Dim hv_cookie$ = GetValueFromCookies(NameOf(UserHash4), Responser.Cookies)
If Not hv_cookie.IsEmptyString And Not hv_cookie = hv_current And Responser.Cookies.Changed Then UserHash4.Value = hv_cookie If Not hv_cookie.IsEmptyString And Not hv_cookie = hv_current And Responser.Cookies.Changed Then UserHash4.Value = hv_cookie
End If End If
End Sub End Sub

View File

@@ -14,6 +14,7 @@ Namespace API.Mastodon
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadModelProfile As Boolean <PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadModelProfile As Boolean
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadModelSearch As Boolean <PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadModelSearch As Boolean
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadModelForceApply As Boolean <PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadModelForceApply As Boolean
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadModelLikes As Boolean
Friend Sub New(ByVal s As SiteSettings) Friend Sub New(ByVal s As SiteSettings)
MyBase.New(s) MyBase.New(s)
End Sub End Sub

View File

@@ -63,15 +63,15 @@ Namespace API.Mastodon
End Sub End Sub
#End Region #End Region
#Region "Other properties" #Region "Other properties"
<PropertyOption(IsAuth:=False, ControlText:=DN.GifsDownloadCaption), PXML, PClonable> <PropertyOption(IsAuth:=False, ControlText:=DN.GifsDownloadCaption, Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property GifsDownload As PropertyValue Friend ReadOnly Property GifsDownload As PropertyValue
<PropertyOption(IsAuth:=False, ControlText:=DN.GifsSpecialFolderCaption, ControlToolTip:=DN.GifsSpecialFolderToolTip), PXML, PClonable> <PropertyOption(IsAuth:=False, ControlText:=DN.GifsSpecialFolderCaption, ControlToolTip:=DN.GifsSpecialFolderToolTip, Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property GifsSpecialFolder As PropertyValue Friend ReadOnly Property GifsSpecialFolder As PropertyValue
<PropertyOption(IsAuth:=False, ControlText:=DN.GifsPrefixCaption, ControlToolTip:=DN.GifsPrefixToolTip), PXML, PClonable> <PropertyOption(IsAuth:=False, ControlText:=DN.GifsPrefixCaption, ControlToolTip:=DN.GifsPrefixToolTip, Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property GifsPrefix As PropertyValue Friend ReadOnly Property GifsPrefix As PropertyValue
<Provider(NameOf(GifsSpecialFolder), Interaction:=True), Provider(NameOf(GifsPrefix), Interaction:=True)> <Provider(NameOf(GifsSpecialFolder), Interaction:=True), Provider(NameOf(GifsPrefix), Interaction:=True)>
Private ReadOnly Property GifStringChecker As IFormatProvider Private ReadOnly Property GifStringChecker As IFormatProvider
<PropertyOption(IsAuth:=False, ControlText:=DN.UseMD5ComparisonCaption, ControlToolTip:=DN.UseMD5ComparisonToolTip), PXML, PClonable> <PropertyOption(IsAuth:=False, ControlText:=DN.UseMD5ComparisonCaption, ControlToolTip:=DN.UseMD5ComparisonToolTip, Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property UseMD5Comparison As PropertyValue Friend ReadOnly Property UseMD5Comparison As PropertyValue
<PropertyOption(IsAuth:=False, ControlText:="User related to my domain", <PropertyOption(IsAuth:=False, ControlText:="User related to my domain",
ControlToolTip:="Open user profiles and user posts through my domain."), PXML, PClonable> ControlToolTip:="Open user profiles and user posts through my domain."), PXML, PClonable>

View File

@@ -11,5 +11,15 @@ Namespace API.OnlyFans
Friend Module Declarations Friend Module Declarations
Friend ReadOnly DateProvider As New ADateTime("O") Friend ReadOnly DateProvider As New ADateTime("O")
Friend ReadOnly RegExPostID As RParams = RParams.DM("(?<=onlyfans\.com/)(\d+)", 0, EDP.ReturnValue) Friend ReadOnly RegExPostID As RParams = RParams.DM("(?<=onlyfans\.com/)(\d+)", 0, EDP.ReturnValue)
Friend ReadOnly OFScraperConfigPatternFile As SFile = $"{SettingsFolderName}\OFScraperConfigPattern.json"
Friend Function CheckOFSConfig() As Boolean
If Not OFScraperConfigPatternFile.Exists Then
Dim t$ = Text.Encoding.UTF8.GetString(My.Resources.OFResources.OFScraperConfigPattern)
TextSaver.SaveTextToFile(t, OFScraperConfigPatternFile, True)
Return OFScraperConfigPatternFile.Exists
Else
Return True
End If
End Function
End Module End Module
End Namespace End Namespace

View File

@@ -38,14 +38,18 @@
}, },
"advanced_options": { "advanced_options": {
"code-execution": false, "code-execution": false,
"dynamic-mode-default": "deviint", "dynamic-mode-default": "sneaky",
"backend": "aio", "backend": "aio",
"downloadbars": false, "downloadbars": false,
"cache-mode": "sqlite", "cache-mode": "sqlite",
"appendlog": true, "appendlog": true,
"custom": null, "custom": null,
"sanitize_text": false, "sanitize_text": false,
"avatar": true "avatar": true,
"custom_values": {
"SNEAKY": "https://raw.githubusercontent.com/Growik/onlyfans-dynamic-rules/main/rules.json",
"CDRM": "https://old.cdrm-project.com/wv"
}
}, },
"responsetype": { "responsetype": {
"timeline": "Posts", "timeline": "Posts",

View File

@@ -13,18 +13,22 @@ Imports PersonalUtilities.Forms
Imports PersonalUtilities.Tools.Web.Clients Imports PersonalUtilities.Tools.Web.Clients
Imports PersonalUtilities.Tools.Web.Cookies Imports PersonalUtilities.Tools.Web.Cookies
Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Functions.RegularExpressions
Imports DN = SCrawler.API.Base.DeclaredNames
Namespace API.OnlyFans Namespace API.OnlyFans
<Manifest("AndyProgram_OnlyFans"), SavedPosts, SpecialForm(False), SeparatedTasks(1)> <Manifest("AndyProgram_OnlyFans"), SavedPosts, SpecialForm(False), SeparatedTasks(1)>
Friend Class SiteSettings : Inherits SiteSettingsBase Friend Class SiteSettings : Inherits SiteSettingsBase
#Region "Declarations" #Region "Declarations"
#Region "Categories"
Private Const CAT_OFS As String = "OF-Scraper support"
#End Region
#Region "Options" #Region "Options"
<PropertyOption(ControlText:="Download timeline", ControlToolTip:="Download user timeline"), PXML, PClonable> <PropertyOption(ControlText:="Download timeline", ControlToolTip:="Download user timeline", Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property DownloadTimeline As PropertyValue Friend ReadOnly Property DownloadTimeline As PropertyValue
<PropertyOption(ControlText:="Download stories", ControlToolTip:="Download profile stories if they exists"), PXML, PClonable> <PropertyOption(ControlText:="Download stories", ControlToolTip:="Download profile stories if they exists", Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property DownloadStories As PropertyValue Friend ReadOnly Property DownloadStories As PropertyValue
<PropertyOption(ControlText:="Download highlights", ControlToolTip:="Download profile highlights if they exists"), PXML, PClonable> <PropertyOption(ControlText:="Download highlights", ControlToolTip:="Download profile highlights if they exists", Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property DownloadHighlights As PropertyValue Friend ReadOnly Property DownloadHighlights As PropertyValue
<PropertyOption(ControlText:="Download chat", ControlToolTip:="Download unlocked chat media"), PXML, PClonable> <PropertyOption(ControlText:="Download chat", ControlToolTip:="Download unlocked chat media", Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property DownloadChatMedia As PropertyValue Friend ReadOnly Property DownloadChatMedia As PropertyValue
#End Region #End Region
#Region "Headers" #Region "Headers"
@@ -32,16 +36,16 @@ Namespace API.OnlyFans
Private Const HeaderUserID As String = "User-Id" Private Const HeaderUserID As String = "User-Id"
Friend Const HeaderXBC As String = "X-Bc" Friend Const HeaderXBC As String = "X-Bc"
Friend Const HeaderAppToken As String = "App-Token" Friend Const HeaderAppToken As String = "App-Token"
<PropertyOption(ControlText:=HeaderUserID, AllowNull:=False), PClonable(Clone:=False)> <PropertyOption(ControlText:=HeaderUserID, AllowNull:=False, IsAuth:=True), PClonable(Clone:=False)>
Friend ReadOnly Property HH_USER_ID As PropertyValue Friend ReadOnly Property HH_USER_ID As PropertyValue
<PropertyOption(ControlText:=HeaderXBC, AllowNull:=False), PClonable(Clone:=False)> <PropertyOption(ControlText:=HeaderXBC, AllowNull:=False, IsAuth:=True), PClonable(Clone:=False)>
Private ReadOnly Property HH_X_BC As PropertyValue Private ReadOnly Property HH_X_BC As PropertyValue
<PropertyOption(ControlText:=HeaderAppToken, AllowNull:=False), PClonable(Clone:=False)> <PropertyOption(ControlText:=HeaderAppToken, AllowNull:=False, IsAuth:=True), PClonable(Clone:=False)>
Private ReadOnly Property HH_APP_TOKEN As PropertyValue Private ReadOnly Property HH_APP_TOKEN As PropertyValue
<PropertyOption(ControlText:=HeaderBrowser, ControlToolTip:="Can be null", AllowNull:=True, <PropertyOption(ControlText:=HeaderBrowser, ControlToolTip:="Can be null", AllowNull:=True,
InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua), PClonable, PXML(OnlyForChecked:=True)> InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua, IsAuth:=True), PClonable, PXML(OnlyForChecked:=True)>
Private ReadOnly Property HH_BROWSER As PropertyValue Private ReadOnly Property HH_BROWSER As PropertyValue
<PropertyOption(AllowNull:=False, InheritanceName:=SettingsCLS.HEADER_DEF_UserAgent), PClonable, PXML(OnlyForChecked:=True)> <PropertyOption(AllowNull:=False, InheritanceName:=SettingsCLS.HEADER_DEF_UserAgent, IsAuth:=True), PClonable, PXML(OnlyForChecked:=True)>
Friend ReadOnly Property UserAgent As PropertyValue Friend ReadOnly Property UserAgent As PropertyValue
Private Sub UpdateHeader(ByVal PropertyName As String, ByVal Value As String) Private Sub UpdateHeader(ByVal PropertyName As String, ByVal Value As String)
Dim hName$ = String.Empty Dim hName$ = String.Empty
@@ -59,6 +63,16 @@ Namespace API.OnlyFans
Responser.UserAgent = Value Responser.UserAgent = Value
End If End If
End Sub End Sub
<CookieValueExtractor(NameOf(HH_USER_ID)), CookieValueExtractor(NameOf(HH_X_BC))>
Private Function GetValueFromCookies(ByVal PropName As String, ByVal c As CookieKeeper) As String
If c.ListExists Then
Select Case PropName
Case NameOf(HH_USER_ID) : Return c.GetCookieValue("auth_id")
Case NameOf(HH_X_BC) : Return c.GetCookieValue("fp")
End Select
End If
Return String.Empty
End Function
#End Region #End Region
#Region "Rules" #Region "Rules"
<PXML("LastDateUpdated")> Private ReadOnly Property LastDateUpdated_XML As PropertyValue <PXML("LastDateUpdated")> Private ReadOnly Property LastDateUpdated_XML As PropertyValue
@@ -72,20 +86,21 @@ Namespace API.OnlyFans
End Property End Property
<PropertyOption(ControlText:="Use old authorization rules", <PropertyOption(ControlText:="Use old authorization rules",
ControlToolTip:="Use old dynamic rules (from 'DATAHOARDERS') or new ones (from 'DIGITALCRIMINALS')." & vbCr & ControlToolTip:="Use old dynamic rules (from 'DATAHOARDERS') or new ones (from 'DIGITALCRIMINALS')." & vbCr &
"Change this value only if you know what you are doing."), PXML, PClonable> "Change this value only if you know what you are doing.", IsAuth:=True), PXML, PClonable>
Friend ReadOnly Property UseOldAuthRules As PropertyValue Friend ReadOnly Property UseOldAuthRules As PropertyValue
<PropertyOption(ControlText:="Dynamic rules update", ControlToolTip:="'Dynamic rules' update interval (minutes). Default: 1440", LeftOffset:=110), PXML, PClonable> <PropertyOption(ControlText:="Dynamic rules update", ControlToolTip:="'Dynamic rules' update interval (minutes). Default: 1440",
LeftOffset:=110, IsAuth:=True), PXML, PClonable>
Friend ReadOnly Property DynamicRulesUpdateInterval As PropertyValue Friend ReadOnly Property DynamicRulesUpdateInterval As PropertyValue
<Provider(NameOf(DynamicRulesUpdateInterval), FieldsChecker:=True)> <Provider(NameOf(DynamicRulesUpdateInterval), FieldsChecker:=True)>
Private ReadOnly Property DynamicRulesUpdateIntervalProvider As IFormatProvider Private ReadOnly Property DynamicRulesUpdateIntervalProvider As IFormatProvider
<PropertyOption(ControlText:="Dynamic rules", <PropertyOption(ControlText:="Dynamic rules",
ControlToolTip:="Overwrite 'Dynamic rules' with this URL" & vbCr & ControlToolTip:="Overwrite 'Dynamic rules' with this URL" & vbCr &
"Change this value only if you know what you are doing."), PXML, PClonable> "Change this value only if you know what you are doing.", IsAuth:=True), PXML, PClonable>
Friend ReadOnly Property DynamicRules As PropertyValue Friend ReadOnly Property DynamicRules As PropertyValue
#End Region #End Region
#Region "OFScraper" #Region "OFScraper"
<PClonable, PXML("OFScraperPath")> Private ReadOnly Property OFScraperPath_XML As PropertyValue <PClonable, PXML("OFScraperPath")> Private ReadOnly Property OFScraperPath_XML As PropertyValue
<PropertyOption(ControlText:="OF-Scraper path", ControlToolTip:="The path to the 'ofscraper.exe'")> <PropertyOption(ControlText:="OF-Scraper path", ControlToolTip:="The path to the 'ofscraper.exe'", Category:=CAT_OFS)>
Friend ReadOnly Property OFScraperPath As PropertyValue Friend ReadOnly Property OFScraperPath As PropertyValue
Get Get
If Not DefaultInstance Is Nothing Then If Not DefaultInstance Is Nothing Then
@@ -96,7 +111,7 @@ Namespace API.OnlyFans
End Get End Get
End Property End Property
<PClonable, PXML("OFScraperMP4decrypt")> Private ReadOnly Property OFScraperMP4decrypt_XML As PropertyValue <PClonable, PXML("OFScraperMP4decrypt")> Private ReadOnly Property OFScraperMP4decrypt_XML As PropertyValue
<PropertyOption(ControlText:="mp4decrypt path", ControlToolTip:="The path to the 'mp4decrypt.exe'")> <PropertyOption(ControlText:="mp4decrypt path", ControlToolTip:="The path to the 'mp4decrypt.exe'", Category:=CAT_OFS)>
Friend ReadOnly Property OFScraperMP4decrypt As PropertyValue Friend ReadOnly Property OFScraperMP4decrypt As PropertyValue
Get Get
If Not DefaultInstance Is Nothing Then If Not DefaultInstance Is Nothing Then
@@ -108,7 +123,7 @@ Namespace API.OnlyFans
End Property End Property
Friend Const KeyModeDefault_Default As String = "cdrm" Friend Const KeyModeDefault_Default As String = "cdrm"
<PClonable, PXML("KeyModeDefault")> Private ReadOnly Property KeyModeDefault_XML As PropertyValue <PClonable, PXML("KeyModeDefault")> Private ReadOnly Property KeyModeDefault_XML As PropertyValue
<PropertyOption(ControlText:="key-mode-default")> <PropertyOption(ControlText:="key-mode-default", Category:=CAT_OFS)>
Friend ReadOnly Property KeyModeDefault As PropertyValue Friend ReadOnly Property KeyModeDefault As PropertyValue
Get Get
If Not DefaultInstance Is Nothing Then If Not DefaultInstance Is Nothing Then
@@ -118,12 +133,27 @@ Namespace API.OnlyFans
End If End If
End Get End Get
End Property End Property
<PClonable, PXML("keydb_api")> Private ReadOnly Property Keydb_Api_XML As PropertyValue
<PropertyOption(ControlText:="keydb_api", Category:=CAT_OFS)>
Friend ReadOnly Property Keydb_Api As PropertyValue
Get
If Not DefaultInstance Is Nothing Then
Return DirectCast(DefaultInstance, SiteSettings).Keydb_Api_XML
Else
Return Keydb_Api_XML
End If
End Get
End Property
#End Region #End Region
#End Region #End Region
#Region "Initializer" #Region "Initializer"
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean) Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
MyBase.New("OnlyFans", ".onlyfans.com", AccName, Temp, My.Resources.SiteResources.OnlyFansIcon_32, My.Resources.SiteResources.OnlyFansPic_32) MyBase.New("OnlyFans", ".onlyfans.com", AccName, Temp, My.Resources.SiteResources.OnlyFansIcon_32, My.Resources.SiteResources.OnlyFansPic_32)
CheckOFSConfig()
_AllowUserAgentUpdate = False
With Responser With Responser
.Accept = "application/json, text/plain, */*" .Accept = "application/json, text/plain, */*"
.AutomaticDecompression = Net.DecompressionMethods.GZip .AutomaticDecompression = Net.DecompressionMethods.GZip
@@ -175,6 +205,7 @@ Namespace API.OnlyFans
End If End If
OFScraperMP4decrypt_XML = New PropertyValue(String.Empty, GetType(String)) OFScraperMP4decrypt_XML = New PropertyValue(String.Empty, GetType(String))
KeyModeDefault_XML = New PropertyValue(KeyModeDefault_Default) KeyModeDefault_XML = New PropertyValue(KeyModeDefault_Default)
Keydb_Api_XML = New PropertyValue(String.Empty, GetType(String))
UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "onlyfans.com/"), 1, EDP.ReturnValue) UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "onlyfans.com/"), 1, EDP.ReturnValue)
UrlPatternUser = "https://onlyfans.com/{0}" UrlPatternUser = "https://onlyfans.com/{0}"
@@ -187,8 +218,19 @@ Namespace API.OnlyFans
End Function End Function
#End Region #End Region
#Region "Update" #Region "Update"
Private __UseOldAuthRules As Boolean = True
Private __DynamicRules As String = String.Empty
Friend Overrides Sub BeginUpdate()
__UseOldAuthRules = UseOldAuthRules.Value
__DynamicRules = AConvert(Of String)(DynamicRules.Value, String.Empty)
MyBase.BeginUpdate()
End Sub
Friend Overrides Sub Update() Friend Overrides Sub Update()
If _SiteEditorFormOpened Then Responser.Cookies.Changed = False If _SiteEditorFormOpened Then
If Not __UseOldAuthRules = CBool(UseOldAuthRules.Value) Or Not AEquals(Of String)(__DynamicRules, DynamicRules.Value) Then _
LastDateUpdated = Now.AddYears(-1)
Responser.Cookies.Changed = False
End If
MyBase.Update() MyBase.Update()
End Sub End Sub
#End Region #End Region

View File

@@ -549,7 +549,8 @@ Namespace API.OnlyFans
Optional ByVal Round As Integer = 0) As Boolean Optional ByVal Round As Integer = 0) As Boolean
Try Try
If UpdateAuthFile(ForceUpdateAuth) Then If UpdateAuthFile(ForceUpdateAuth) Then
Const nullMsg$ = "The auth parameter is null" Const nullMsg$ = "The auth parameter(s) is null"
Const formatMidPart$ = ":{0}:{1:x}:"
Dim j As EContainer Dim j As EContainer
Try Try
j = JsonDocument.Parse(AuthFile.GetText) j = JsonDocument.Parse(AuthFile.GetText)
@@ -565,8 +566,16 @@ Namespace API.OnlyFans
End Try End Try
If Not j Is Nothing Then If Not j Is Nothing Then
Dim pattern$ = j.Value("format") Dim pattern$ = j.Value("format")
If pattern.IsEmptyString Then Throw New ArgumentNullException("format", nullMsg)
pattern = pattern.Replace("{}", "{0}").Replace("{:x}", "{1:x}") If Not pattern.IsEmptyString Then
pattern = pattern.Replace("{}", "{0}").Replace("{:x}", "{1:x}")
ElseIf Not j.Value("prefix").IsEmptyString And Not j.Value("suffix").IsEmptyString Then
pattern = j.Value("prefix") & formatMidPart & j.Value("suffix")
ElseIf Not j.Value("start").IsEmptyString And Not j.Value("end").IsEmptyString Then
pattern = j.Value("start") & formatMidPart & j.Value("end")
Else
Throw New ArgumentNullException("format", nullMsg)
End If
Dim li%() = j("checksum_indexes").Select(Function(e) CInt(e(0).Value)).ToArray Dim li%() = j("checksum_indexes").Select(Function(e) CInt(e(0).Value)).ToArray
@@ -607,10 +616,14 @@ Namespace API.OnlyFans
Dim r$ = GetWebString(If(ACheck(Of String)(MySettings.DynamicRules.Value), Dim r$ = GetWebString(If(ACheck(Of String)(MySettings.DynamicRules.Value),
CStr(MySettings.DynamicRules.Value), CStr(MySettings.DynamicRules.Value),
IIf(MySettings.UseOldAuthRules.Value, urlOld, urlNew)),, EDP.ReturnValue) IIf(MySettings.UseOldAuthRules.Value, urlOld, urlNew)),, EDP.ReturnValue)
Dim checkFormat As Func(Of EContainer, Boolean) =
Function(jj) Not jj.Value("format").IsEmptyString OrElse
(Not jj.Value("prefix").IsEmptyString And Not jj.Value("suffix").IsEmptyString) OrElse
(Not jj.Value("start").IsEmptyString And Not jj.Value("end").IsEmptyString)
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
Using j As EContainer = JsonDocument.Parse(r, EDP.ReturnValue) Using j As EContainer = JsonDocument.Parse(r, EDP.ReturnValue)
If j.ListExists Then If j.ListExists Then
If Not j.Value("format").IsEmptyString And j("checksum_indexes").ListExists And If checkFormat(j) And j("checksum_indexes").ListExists And
Not j.Value("static_param").IsEmptyString And Not j.Value("checksum_constant").IsEmptyString Then _ Not j.Value("static_param").IsEmptyString And Not j.Value("checksum_constant").IsEmptyString Then _
TextSaver.SaveTextToFile(r, AuthFile, True, False, EDP.ThrowException) : MySettings.LastDateUpdated = Now TextSaver.SaveTextToFile(r, AuthFile, True, False, EDP.ThrowException) : MySettings.LastDateUpdated = Now
End If End If
@@ -658,12 +671,9 @@ Namespace API.OnlyFans
currentCache.Validate() currentCache.Validate()
Dim cacheRoot As SFile = currentCache.NewPath Dim cacheRoot As SFile = currentCache.NewPath
cacheRoot.Exists(SFO.Path, True, EDP.ThrowException) cacheRoot.Exists(SFO.Path, True, EDP.ThrowException)
Dim f As SFile = $"{SettingsFolderName}\OFScraperConfigPattern.json" Dim f As SFile = OFScraperConfigPatternFile
Dim configText$ Dim configText$
If Not f.Exists Then CheckOFSConfig()
configText = Text.Encoding.UTF8.GetString(My.Resources.OFResources.OFScraperConfigPattern)
TextSaver.SaveTextToFile(configText, f, True)
End If
If f.Exists Then If f.Exists Then
Dim replaceValue$ = String.Empty Dim replaceValue$ = String.Empty
Dim rp As RParams = RParams.DMS(String.Empty, 1, RegexReturn.Replace, RegexOptions.IgnoreCase, Dim rp As RParams = RParams.DMS(String.Empty, 1, RegexReturn.Replace, RegexOptions.IgnoreCase,
@@ -684,6 +694,7 @@ Namespace API.OnlyFans
End If End If
If Settings.FfmpegFile.Exists Then updateConf("ffmpeg", Settings.FfmpegFile.File.ToString.Replace("\", "/")) If Settings.FfmpegFile.Exists Then updateConf("ffmpeg", Settings.FfmpegFile.File.ToString.Replace("\", "/"))
updateConf("key-mode-default", CStr(MySettings.KeyModeDefault.Value).IfNullOrEmpty(SiteSettings.KeyModeDefault_Default)) updateConf("key-mode-default", CStr(MySettings.KeyModeDefault.Value).IfNullOrEmpty(SiteSettings.KeyModeDefault_Default))
updateConf("keydb_api", CStr(MySettings.Keydb_Api.Value))
f = currentCache f = currentCache
f.Name = "config" f.Name = "config"
f.Extension = "json" f.Extension = "json"

View File

@@ -287,7 +287,7 @@ Namespace API.Pinterest
End Function End Function
End Class End Class
Private Function GetDataFromGalleryDL(ByVal URL As String, ByVal IsBoardsRequested As Boolean, ByVal Token As CancellationToken) As List(Of String) Private Function GetDataFromGalleryDL(ByVal URL As String, ByVal IsBoardsRequested As Boolean, ByVal Token As CancellationToken) As List(Of String)
Dim command$ = $"gallery-dl --verbose --simulate " Dim command$ = $"""{Settings.GalleryDLFile.File}"" --verbose --simulate "
Try Try
If Not URL.IsEmptyString Then If Not URL.IsEmptyString Then
If MySettings.CookiesNetscapeFile.Exists Then command &= $"--cookies ""{MySettings.CookiesNetscapeFile}"" " If MySettings.CookiesNetscapeFile.Exists Then command &= $"--cookies ""{MySettings.CookiesNetscapeFile}"" "

View File

@@ -29,7 +29,6 @@ Namespace API.PornHub
Private Const Name_DownloadFavorite As String = "DownloadFavorite" Private Const Name_DownloadFavorite As String = "DownloadFavorite"
Private Const Name_DownloadGifs As String = "DownloadGifs" Private Const Name_DownloadGifs As String = "DownloadGifs"
Private Const Name_DownloadPhotoOnlyFromModelHub As String = "DownloadPhotoOnlyFromModelHub" Private Const Name_DownloadPhotoOnlyFromModelHub As String = "DownloadPhotoOnlyFromModelHub"
<Obsolete> Private Const Name_IsUser As String = "IsUser"
#End Region #End Region
#Region "Structures" #Region "Structures"
Private Structure FlashVar : Implements IRegExCreator Private Structure FlashVar : Implements IRegExCreator
@@ -254,14 +253,7 @@ Namespace API.PornHub
DownloadFavorite = .Value(Name_DownloadFavorite).FromXML(Of Boolean)(False) DownloadFavorite = .Value(Name_DownloadFavorite).FromXML(Of Boolean)(False)
DownloadGifs = .Value(Name_DownloadGifs).FromXML(Of Integer)(False) DownloadGifs = .Value(Name_DownloadGifs).FromXML(Of Integer)(False)
DownloadPhotoOnlyFromModelHub = .Value(Name_DownloadPhotoOnlyFromModelHub).FromXML(Of Boolean)(True) DownloadPhotoOnlyFromModelHub = .Value(Name_DownloadPhotoOnlyFromModelHub).FromXML(Of Boolean)(True)
If .Contains(Name_SiteMode) Then SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User)
SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User)
Else
'TODELETE: PornHub 'IsUser' 20231113
#Disable Warning BC40008
SiteMode = IIf(.Value(Name_IsUser).FromXML(Of Boolean)(True), SiteModes.User, SiteModes.Search)
#Enable Warning
End If
UpdateUserOptions() UpdateUserOptions()
Else Else
If UpdateUserOptions() Then .Value(Name_LabelsName) = LabelsString If UpdateUserOptions() Then .Value(Name_LabelsName) = LabelsString
@@ -404,7 +396,6 @@ Namespace API.PornHub
Dim r$ = Responser.GetResponse(URL) Dim r$ = Responser.GetResponse(URL)
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
Dim l As List(Of UserVideo) = RegexFields(Of UserVideo)(r, {RegexUserVideos}, {6, 7, 3, 10}) Dim l As List(Of UserVideo) = RegexFields(Of UserVideo)(r, {RegexUserVideos}, {6, 7, 3, 10})
'URGENT: PornHub: changed list trimming
'If l.ListExists And Not SiteMode = SiteModes.Playlists Then l = l.ListTake(3, l.Count).ToList 'If l.ListExists And Not SiteMode = SiteModes.Playlists Then l = l.ListTake(3, l.Count).ToList
If l.ListExists And Not SiteMode = SiteModes.Playlists Then l = l.ListTake(1, l.Count).ToList If l.ListExists And Not SiteMode = SiteModes.Playlists Then l = l.ListTake(1, l.Count).ToList
If l.ListExists Then If l.ListExists Then

View File

@@ -8,6 +8,7 @@
' but WITHOUT ANY WARRANTY ' but WITHOUT ANY WARRANTY
Imports System.Net Imports System.Net
Imports System.Threading Imports System.Threading
Imports SCrawler.API.Base
Imports SCrawler.API.Reddit.M3U8_Declarations Imports SCrawler.API.Reddit.M3U8_Declarations
Imports PersonalUtilities.Tools Imports PersonalUtilities.Tools
Imports PersonalUtilities.Tools.Web Imports PersonalUtilities.Tools.Web
@@ -61,15 +62,18 @@ Namespace API.Reddit
Private ReadOnly ProgressExists As Boolean Private ReadOnly ProgressExists As Boolean
Private ReadOnly Property ProgressPre As PreProgress Private ReadOnly Property ProgressPre As PreProgress
Private ReadOnly UsePreProgress As Boolean Private ReadOnly UsePreProgress As Boolean
Private ReadOnly Media As UserMedia
#End Region #End Region
Private Sub New(ByVal URL As String, ByVal OutFile As SFile, ByVal Progress As MyProgress, ByVal UsePreProgress As Boolean) Private Sub New(ByVal URL As String, ByVal Media As UserMedia, ByVal OutFile As SFile, ByVal Progress As MyProgress, ByVal UsePreProgress As Boolean)
PlayListURL = URL PlayListURL = URL
Me.Media = Media
BaseURL = RegexReplace(URL, BaseUrlPattern) BaseURL = RegexReplace(URL, BaseUrlPattern)
Video = New List(Of String) Video = New List(Of String)
Audio = New List(Of String) Audio = New List(Of String)
Me.OutFile = OutFile Me.OutFile = OutFile
Me.OutFile.Name = "PlayListFile" Me.OutFile.Name = "PlayListFile"
Me.OutFile.Extension = "mp4" Me.OutFile.Extension = "mp4"
If Media.Post.Date.HasValue Then Me.OutFile.Name = Media.Post.Date.Value.ToString("yyyyMMdd_HHmmss")
Me.Progress = Progress Me.Progress = Progress
ProgressExists = Not Me.Progress Is Nothing ProgressExists = Not Me.Progress Is Nothing
ProgressPre = New PreProgress(Progress) ProgressPre = New PreProgress(Progress)
@@ -202,9 +206,9 @@ Namespace API.Reddit
End Function End Function
#End Region #End Region
#Region "Statics" #Region "Statics"
Friend Shared Function Download(ByVal URL As String, ByVal f As SFile, ByVal Token As CancellationToken, Friend Shared Function Download(ByVal URL As String, ByVal Media As UserMedia, ByVal f As SFile, ByVal Token As CancellationToken,
ByVal Progress As MyProgress, ByVal UsePreProgress As Boolean) As SFile ByVal Progress As MyProgress, ByVal UsePreProgress As Boolean) As SFile
Using m As New M3U8(URL, f, Progress, UsePreProgress) : Return m.Download(Token) : End Using Using m As New M3U8(URL, Media, f, Progress, UsePreProgress) : Return m.Download(Token) : End Using
End Function End Function
#End Region #End Region
#Region "IDisposable Support" #Region "IDisposable Support"

View File

@@ -10,6 +10,7 @@ Imports SCrawler.API.Base
Imports SCrawler.Plugin Imports SCrawler.Plugin
Imports SCrawler.Plugin.Attributes Imports SCrawler.Plugin.Attributes
Imports PersonalUtilities.Tools.Web.Clients Imports PersonalUtilities.Tools.Web.Clients
Imports PersonalUtilities.Tools.Web.Clients.Base
Imports PersonalUtilities.Tools.Web.Documents.JSON Imports PersonalUtilities.Tools.Web.Documents.JSON
Imports PersonalUtilities.Functions.XML Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Functions.RegularExpressions
@@ -34,6 +35,8 @@ Namespace API.Reddit
"You can find different tokens in the responses. Make sure that bearer token belongs to Reddit and not RedGifs." & vbCr & "You can find different tokens in the responses. Make sure that bearer token belongs to Reddit and not RedGifs." & vbCr &
"There is not need to add a token if you are not using cookies to download the timeline.", IsAuth:=True)> "There is not need to add a token if you are not using cookies to download the timeline.", IsAuth:=True)>
Friend ReadOnly Property BearerToken As PropertyValue Friend ReadOnly Property BearerToken As PropertyValue
<PropertyOption(ControlText:="Use 'cUrl' to get a token", IsAuth:=True), PXML, PClonable, HiddenControl>
Private ReadOnly Property BearerTokenUseCurl As PropertyValue
#Region "TokenUpdateInterval" #Region "TokenUpdateInterval"
<PropertyOption(ControlText:="Token refresh interval", ControlToolTip:="Interval (in minutes) to refresh the token", <PropertyOption(ControlText:="Token refresh interval", ControlToolTip:="Interval (in minutes) to refresh the token",
AllowNull:=False, LeftOffset:=120, IsAuth:=True), PXML, PClonable> AllowNull:=False, LeftOffset:=120, IsAuth:=True), PXML, PClonable>
@@ -55,7 +58,6 @@ Namespace API.Reddit
Return {AuthUserName.Value, AuthPassword.Value, ApiClientID.Value, ApiClientSecret.Value}.All(Function(v$) Not v.IsEmptyString) Return {AuthUserName.Value, AuthPassword.Value, ApiClientID.Value, ApiClientSecret.Value}.All(Function(v$) Not v.IsEmptyString)
End Get End Get
End Property End Property
#End Region #End Region
#Region "Other" #Region "Other"
<PropertyOption(ControlText:="Use M3U8", ControlToolTip:="Use M3U8 or mp4 for Reddit videos", IsAuth:=False), PXML, PClonable> <PropertyOption(ControlText:="Use M3U8", ControlToolTip:="Use M3U8 or mp4 for Reddit videos", IsAuth:=False), PXML, PClonable>
@@ -82,6 +84,7 @@ Namespace API.Reddit
ApiClientID = New PropertyValue(String.Empty, GetType(String)) ApiClientID = New PropertyValue(String.Empty, GetType(String))
ApiClientSecret = New PropertyValue(String.Empty, GetType(String)) ApiClientSecret = New PropertyValue(String.Empty, GetType(String))
BearerToken = New PropertyValue(token, GetType(String), Sub(v) Responser.Headers.Add(DeclaredNames.Header_Authorization, v)) BearerToken = New PropertyValue(token, GetType(String), Sub(v) Responser.Headers.Add(DeclaredNames.Header_Authorization, v))
BearerTokenUseCurl = New PropertyValue(True)
TokenUpdateInterval = New PropertyValue(60 * 12) TokenUpdateInterval = New PropertyValue(60 * 12)
TokenUpdateIntervalProvider = New TokenRefreshIntervalProvider TokenUpdateIntervalProvider = New TokenRefreshIntervalProvider
BearerTokenDateUpdate = New PropertyValue(Now.AddYears(-1)) BearerTokenDateUpdate = New PropertyValue(Now.AddYears(-1))
@@ -269,29 +272,51 @@ Namespace API.Reddit
result = False result = False
Dim r$ = String.Empty Dim r$ = String.Empty
Dim c% = 0 Dim c% = 0
Dim _found As Boolean Dim useCurl As Boolean = Settings.CurlFile.Exists And CBool(BearerTokenUseCurl.Value)
Dim curlUsed As Boolean = useCurl
Do Do
c += 1 c += 1
Using resp As New Responser With { Using resp As New Responser With {
.Method = "POST", .Method = "POST",
.ProcessExceptionDecision = Function(status, obj, ee) If(status.StatusCode = 429, EDP.ReturnValue, ee) .ProcessExceptionDecision = Function(ByVal status As IResponserStatus, ByVal nullArg As Object, ByVal currErr As ErrorsDescriber) As ErrorsDescriber
If status.StatusCode = 429 Then
useCurl = False
Return EDP.ReturnValue
ElseIf status.StatusCode = Net.HttpStatusCode.Forbidden And Not useCurl And Settings.CurlFile.Exists Then
useCurl = True
Return EDP.ReturnValue
Else
Return currErr
End If
End Function
} }
With resp With resp
With .PayLoadValues If useCurl Then
.Add("grant_type", "password") If Settings.CurlFile.Exists Then
.Add("username", UserName) curlUsed = True
.Add("password", Password) .Mode = Responser.Modes.Curl
End With .CurlPath = Settings.CurlFile
.CredentialsUserName = ClientID .CurlArgumentsLeft = $"-d ""grant_type=password&username={UserName}&password={Password}"" --user ""{ClientID}:{ClientSecret}"""
.CredentialsPassword = ClientSecret Else
.PreAuthenticate = True Throw New ArgumentNullException("cUrl file", "The path to the cUrl file is not specified")
End If
Else
.Mode = Responser.Modes.Default
With .PayLoadValues
.Add("grant_type", "password")
.Add("username", UserName)
.Add("password", Password)
End With
.CredentialsUserName = ClientID
.CredentialsPassword = ClientSecret
.PreAuthenticate = True
End If
End With End With
r = resp.GetResponse("https://www.reddit.com/api/v1/access_token",, EDP.ThrowException) r = resp.GetResponse("https://www.reddit.com/api/v1/access_token",, EDP.ThrowException)
End Using End Using
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
Using j As EContainer = JsonDocument.Parse(r) Using j As EContainer = JsonDocument.Parse(r)
If j.ListExists Then If j.ListExists Then
_found = True
Dim newToken$ = j.Value("access_token") Dim newToken$ = j.Value("access_token")
If Not newToken.IsEmptyString Then If Not newToken.IsEmptyString Then
BearerToken.Value = $"Bearer {newToken}" BearerToken.Value = $"Bearer {newToken}"
@@ -302,7 +327,7 @@ Namespace API.Reddit
End If End If
End Using End Using
End If End If
Loop While c < 5 And Not _found Loop While c < 5 And Not result
End If End If
Return result Return result
Catch ex As Exception Catch ex As Exception

View File

@@ -225,6 +225,7 @@ Namespace API.Reddit
#End Region #End Region
#Region "Download Overrides" #Region "Download Overrides"
Friend Overrides Sub DownloadData(ByVal Token As CancellationToken) Friend Overrides Sub DownloadData(ByVal Token As CancellationToken)
Err429Count = 0
_CrossPosts.Clear() _CrossPosts.Clear()
If CreatedByChannel And Settings.FromChannelDownloadTopUse And Settings.FromChannelDownloadTop > 0 Then _ If CreatedByChannel And Settings.FromChannelDownloadTopUse And Settings.FromChannelDownloadTop > 0 Then _
DownloadTopCount = Settings.FromChannelDownloadTop.Value DownloadTopCount = Settings.FromChannelDownloadTop.Value
@@ -287,6 +288,7 @@ Namespace API.Reddit
End Sub End Sub
#End Region #End Region
#Region "Download Functions (User, Channel)" #Region "Download Functions (User, Channel)"
Private Err429Count As Integer = 0
Private _TotalPostsDownloaded As Integer = 0 Private _TotalPostsDownloaded As Integer = 0
Private ReadOnly _CrossPosts As List(Of String) Private ReadOnly _CrossPosts As List(Of String)
Private Const SiteGfycatKey As String = "gfycat" Private Const SiteGfycatKey As String = "gfycat"
@@ -375,6 +377,7 @@ Namespace API.Reddit
Loop While Not _completed Loop While Not _completed
End Sub End Sub
Private Sub DownloadDataChannel(ByVal POST As String, ByVal Token As CancellationToken) Private Sub DownloadDataChannel(ByVal POST As String, ByVal Token As CancellationToken)
Const savedPostsSleepTimer% = 2000
Dim eObj% = 0 Dim eObj% = 0
Dim round% = 0 Dim round% = 0
Dim URL$ = String.Empty Dim URL$ = String.Empty
@@ -392,12 +395,14 @@ Namespace API.Reddit
If IsSavedPosts Then If IsSavedPosts Then
URL = $"https://www.reddit.com/user/{TrueName}/saved.json?after={POST}" URL = $"https://www.reddit.com/user/{TrueName}/saved.json?after={POST}"
If Not POST.IsEmptyString Then Thread.Sleep(savedPostsSleepTimer)
Else Else
URL = $"https://reddit.com/r/{TrueName}/{View}.json?allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort={View}&t={Period}&layout=classic" URL = $"https://reddit.com/r/{TrueName}/{View}.json?allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort={View}&t={Period}&layout=classic"
End If End If
ThrowAny(Token) ThrowAny(Token)
Dim r$ = Responser.GetResponse(URL) Dim r$ = Responser.GetResponse(URL)
If IsSavedPosts Then Err429Count = 0
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
Using w As EContainer = JsonDocument.Parse(r).XmlIfNothing Using w As EContainer = JsonDocument.Parse(r).XmlIfNothing
If w.Count > 0 Then If w.Count > 0 Then
@@ -458,8 +463,12 @@ Namespace API.Reddit
End If End If
_completed = True _completed = True
Catch ex As Exception Catch ex As Exception
If ProcessException(ex, Token, $"channel data downloading error [{URL}]",, eObj) = HttpStatusCode.InternalServerError Then Dim errValue% = ProcessException(ex, Token, $"{IIf(IsSavedPosts, "saved posts", "channel")} data downloading error [{URL}]",, eObj)
If errValue = HttpStatusCode.InternalServerError Then
If round = 2 Then eObj = HttpStatusCode.InternalServerError If round = 2 Then eObj = HttpStatusCode.InternalServerError
ElseIf errValue = 429 And round = 0 Then
Thread.Sleep(savedPostsSleepTimer)
round += 1
Else Else
_completed = True _completed = True
End If End If
@@ -905,19 +914,24 @@ Namespace API.Reddit
Dim RedGifsHost As SettingsHost = Settings(RedGifs.RedGifsSiteKey, RedGifsAccount) Dim RedGifsHost As SettingsHost = Settings(RedGifs.RedGifsSiteKey, RedGifsAccount)
If RedGifsHost Is Nothing Then RedGifsHost = Settings(RedGifs.RedGifsSiteKey).Default If RedGifsHost Is Nothing Then RedGifsHost = Settings(RedGifs.RedGifsSiteKey).Default
RedGifsResponser = RedGifsHost.Responser.Copy RedGifsResponser = RedGifsHost.Responser.Copy
Dim respNoHeaders As Responser = Responser.Copy
Dim m As UserMedia, m2 As UserMedia Dim m As UserMedia, m2 As UserMedia
Dim r$ Dim r$, url$
Dim j As EContainer Dim j As EContainer
Dim lastCount%, li% Dim lastCount%, li%
Dim rv As New ErrorsDescriber(EDP.ReturnValue)
respNoHeaders.Headers.Clear()
ProgressPre.ChangeMax(_ContentList.Count) ProgressPre.ChangeMax(_ContentList.Count)
For i% = 0 To _ContentList.Count - 1 For i% = 0 To _ContentList.Count - 1
m = _ContentList(i) m = _ContentList(i)
ProgressPre.Perform() ProgressPre.Perform()
If m.State = UStates.Missing AndAlso Not m.Post.ID.IsEmptyString Then If m.State = UStates.Missing AndAlso Not m.Post.ID.IsEmptyString Then
ThrowAny(Token) ThrowAny(Token)
r = Responser.GetResponse($"https://www.reddit.com/comments/{m.Post.ID.Split("_").LastOrDefault}/.json",, EDP.ReturnValue) url = $"https://www.reddit.com/comments/{m.Post.ID.Split("_").LastOrDefault}/.json"
r = Responser.GetResponse(url,, rv)
If r.IsEmptyString Then r = respNoHeaders.GetResponse(url,, rv)
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
j = JsonDocument.Parse(r, EDP.ReturnValue) j = JsonDocument.Parse(r, rv)
If Not j Is Nothing Then If Not j Is Nothing Then
If j.Count > 0 Then If j.Count > 0 Then
lastCount = _TempMediaList.Count lastCount = _TempMediaList.Count
@@ -975,7 +989,7 @@ Namespace API.Reddit
Dim m As New UserMedia(_URL, t) With {.Post = New UserPost With {.ID = PostID, .UserID = _UserID}} 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 = CreateFileFromUrl(m.URL) Else m.File = Nothing If t = UTypes.Picture Or t = UTypes.GIF Then m.File = CreateFileFromUrl(m.URL) Else m.File = Nothing
If ReplacePreview And m.URL.Contains("preview") And Not t = UTypes.Picture Then m.URL = $"https://i.redd.it/{m.File.File}" If ReplacePreview And m.URL.Contains("preview") And Not t = UTypes.Picture 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 If Not PostDate.IsEmptyString Then m.Post.Date = AConvert(Of Date)(PostDate, DateTrueProvider(IsChannel Or IsSavedPosts), Nothing) Else m.Post.Date = Nothing
Return m Return m
End Function End Function
Private Function TryFile(ByVal URL As String) As Boolean Private Function TryFile(ByVal URL As String) As Boolean
@@ -1027,7 +1041,7 @@ Namespace API.Reddit
Return URL.Contains(SiteRedGifsKey) Return URL.Contains(SiteRedGifsKey)
End Function End Function
Protected Overrides Function DownloadM3U8(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile, ByVal Token As CancellationToken) As SFile Protected Overrides Function DownloadM3U8(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile, ByVal Token As CancellationToken) As SFile
Return M3U8.Download(URL, DestinationFile, Token, Progress, Not IsSingleObjectDownload) Return M3U8.Download(URL, Media, DestinationFile, Token, Progress, Not IsSingleObjectDownload)
End Function End Function
Protected Overrides Function ChangeFileNameByProvider(ByVal f As SFile, ByVal m As UserMedia) As SFile Protected Overrides Function ChangeFileNameByProvider(ByVal f As SFile, ByVal m As UserMedia) As SFile
If Not IsChannel Or Not SaveToCache Then If Not IsChannel Or Not SaveToCache Then
@@ -1057,8 +1071,11 @@ Namespace API.Reddit
ElseIf .StatusCode = HttpStatusCode.InternalServerError Then '500 ElseIf .StatusCode = HttpStatusCode.InternalServerError Then '500
If Not IsNothing(EObj) AndAlso IsNumeric(EObj) AndAlso CInt(EObj) = HttpStatusCode.InternalServerError Then Return 1 If Not IsNothing(EObj) AndAlso IsNumeric(EObj) AndAlso CInt(EObj) = HttpStatusCode.InternalServerError Then Return 1
Return HttpStatusCode.InternalServerError Return HttpStatusCode.InternalServerError
ElseIf .StatusCode = 429 And IsSavedPosts And Err429Count = 0 Then
Err429Count += 1
Return 429
ElseIf .StatusCode = 429 AndAlso ElseIf .StatusCode = 429 AndAlso
((Not IsSavedPosts And CBool(MySiteSettings.UseTokenForTimelines.Value)) Or (IsSavedPosts And MySiteSettings.UseTokenForSavedPosts.Value)) AndAlso ((Not IsSavedPosts And CBool(MySiteSettings.UseTokenForTimelines.Value)) Or (IsSavedPosts And CBool(MySiteSettings.UseTokenForSavedPosts.Value))) AndAlso
Not MySiteSettings.CredentialsExists Then '429 Not MySiteSettings.CredentialsExists Then '429
MyMainLOG = $"{ToStringForLog()}: [{CInt(Responser.StatusCode)}] You should use OAuth authorization or disable " & MyMainLOG = $"{ToStringForLog()}: [{CInt(Responser.StatusCode)}] You should use OAuth authorization or disable " &
IIf(IsSavedPosts, "token usage for downloading saved posts", "the use of token and cookies for downloading timelines") IIf(IsSavedPosts, "token usage for downloading saved posts", "the use of token and cookies for downloading timelines")

View File

@@ -18,9 +18,9 @@ Namespace API.RedGifs
<Manifest(RedGifsSiteKey)> <Manifest(RedGifsSiteKey)>
Friend Class SiteSettings : Inherits SiteSettingsBase Friend Class SiteSettings : Inherits SiteSettingsBase
#Region "Declarations" #Region "Declarations"
<PropertyOption(ControlToolTip:="Bearer token", AllowNull:=False), DependentFields(NameOf(UserAgent)), ControlNumber(1), PClonable(Clone:=False)> <PropertyOption(ControlToolTip:="Bearer token", AllowNull:=False), DependentFields(NameOf(UserAgent)), ControlNumber(1), PClonable(Clone:=False), HiddenControl>
Friend ReadOnly Property Token As PropertyValue Friend ReadOnly Property Token As PropertyValue
<PropertyOption, ControlNumber(2), PClonable> <PropertyOption, ControlNumber(2), PClonable, HiddenControl>
Private ReadOnly Property UserAgent As PropertyValue Private ReadOnly Property UserAgent As PropertyValue
<PXML> Friend ReadOnly Property TokenLastDateUpdated As PropertyValue <PXML> Friend ReadOnly Property TokenLastDateUpdated As PropertyValue
Private Const TokenName As String = "authorization" Private Const TokenName As String = "authorization"
@@ -107,7 +107,9 @@ Namespace API.RedGifs
Friend Overrides Sub Update() Friend Overrides Sub Update()
If _SiteEditorFormOpened Then If _SiteEditorFormOpened Then
Dim NewToken$ = AConvert(Of String)(Token.Value, AModes.Var, String.Empty) Dim NewToken$ = AConvert(Of String)(Token.Value, AModes.Var, String.Empty)
If Not _LastTokenValue = NewToken Then TokenLastDateUpdated.Value = Now If Not _LastTokenValue = NewToken And Not NewToken.IsEmptyString Then TokenLastDateUpdated.Value = Now
If Responser.CookiesExists AndAlso MsgBoxE({"RedGifs doesn't require cookies! Do you still want to use cookies?", "RedGifs cookies"},
vbExclamation,,, {"Use", "Don't use"}) = 1 Then Responser.Cookies.Clear()
End If End If
MyBase.Update() MyBase.Update()
End Sub End Sub

View File

@@ -13,6 +13,7 @@ Imports PersonalUtilities.Tools.Web.Clients
Imports PersonalUtilities.Tools.Web.Cookies Imports PersonalUtilities.Tools.Web.Cookies
Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Functions.RegularExpressions
Imports IG = SCrawler.API.Instagram.SiteSettings Imports IG = SCrawler.API.Instagram.SiteSettings
Imports DN = SCrawler.API.Base.DeclaredNames
Namespace API.ThreadsNet Namespace API.ThreadsNet
<Manifest("AndyProgram_ThreadsNet"), SeparatedTasks(1)> <Manifest("AndyProgram_ThreadsNet"), SeparatedTasks(1)>
Friend Class SiteSettings : Inherits SiteSettingsBase Friend Class SiteSettings : Inherits SiteSettingsBase
@@ -25,6 +26,10 @@ Namespace API.ThreadsNet
Return __HH_CSRF_TOKEN Return __HH_CSRF_TOKEN
End Get End Get
End Property End Property
<CookieValueExtractor(NameOf(HH_CSRF_TOKEN))>
Private Function GetValueFromCookies(ByVal PropName As String, ByVal c As CookieKeeper) As String
Return c.GetCookieValue(IG.Header_CSRF_TOKEN_COOKIE, PropName, NameOf(HH_CSRF_TOKEN))
End Function
<PClonable> Protected ReadOnly __HH_IG_APP_ID As PropertyValue <PClonable> Protected ReadOnly __HH_IG_APP_ID As PropertyValue
<PropertyOption(ControlText:="x-ig-app-id", AllowNull:=False, IsAuth:=True), ControlNumber(10)> <PropertyOption(ControlText:="x-ig-app-id", AllowNull:=False, IsAuth:=True), ControlNumber(10)>
Friend Overridable ReadOnly Property HH_IG_APP_ID As PropertyValue Friend Overridable ReadOnly Property HH_IG_APP_ID As PropertyValue
@@ -36,10 +41,10 @@ Namespace API.ThreadsNet
Friend ReadOnly Property HH_ASBD_ID As PropertyValue Friend ReadOnly Property HH_ASBD_ID As PropertyValue
<PropertyOption(ControlText:="sec-ch-ua", AllowNull:=True, IsAuth:=True, <PropertyOption(ControlText:="sec-ch-ua", AllowNull:=True, IsAuth:=True,
InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua), ControlNumber(30), PClonable, PXML(OnlyForChecked:=True)> InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua), ControlNumber(30), PClonable, PXML(OnlyForChecked:=True)>
Private ReadOnly Property HH_BROWSER As PropertyValue Friend ReadOnly Property HH_BROWSER As PropertyValue
<PropertyOption(ControlText:="sec-ch-ua-full", ControlToolTip:=SettingsCLS.HEADER_DEF_sec_ch_ua_full_version_list, AllowNull:=True, IsAuth:=True, <PropertyOption(ControlText:="sec-ch-ua-full", ControlToolTip:=SettingsCLS.HEADER_DEF_sec_ch_ua_full_version_list, AllowNull:=True, IsAuth:=True,
InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua_full_version_list), ControlNumber(40), PClonable, PXML(OnlyForChecked:=True)> InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua_full_version_list), ControlNumber(40), PClonable, PXML(OnlyForChecked:=True)>
Private ReadOnly Property HH_BROWSER_EXT As PropertyValue Friend ReadOnly Property HH_BROWSER_EXT As PropertyValue
<PropertyOption(ControlText:="sec-ch-ua-platform-ver", ControlToolTip:=SettingsCLS.HEADER_DEF_sec_ch_ua_platform_version, AllowNull:=True, IsAuth:=True, LeftOffset:=135, <PropertyOption(ControlText:="sec-ch-ua-platform-ver", ControlToolTip:=SettingsCLS.HEADER_DEF_sec_ch_ua_platform_version, AllowNull:=True, IsAuth:=True, LeftOffset:=135,
InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua_platform_version), ControlNumber(50), PClonable, PXML(OnlyForChecked:=True)> InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua_platform_version), ControlNumber(50), PClonable, PXML(OnlyForChecked:=True)>
Friend ReadOnly Property HH_PLATFORM_VER As PropertyValue Friend ReadOnly Property HH_PLATFORM_VER As PropertyValue
@@ -71,14 +76,14 @@ Namespace API.ThreadsNet
#Region "Other properties" #Region "Other properties"
<PropertyOption(ControlText:="Request timer (any)", <PropertyOption(ControlText:="Request timer (any)",
ControlToolTip:="The timer (in milliseconds) that SCrawler should wait before executing the next request." & ControlToolTip:="The timer (in milliseconds) that SCrawler should wait before executing the next request." &
vbCr & "The default value is 1'000." & vbCr & "The minimum value is 0." & IG.TimersUrgentTip, AllowNull:=False), vbCr & "The default value is 1'000." & vbCr & "The minimum value is 0." & IG.TimersUrgentTip, AllowNull:=False, Category:=DN.CAT_Timers),
PXML, PClonable> PXML, PClonable>
Friend ReadOnly Property RequestsWaitTimer_Any As PropertyValue Friend ReadOnly Property RequestsWaitTimer_Any As PropertyValue
<Provider(NameOf(RequestsWaitTimer_Any), FieldsChecker:=True)> <Provider(NameOf(RequestsWaitTimer_Any), FieldsChecker:=True)>
Private ReadOnly Property RequestsWaitTimer_AnyProvider As IFormatProvider Private ReadOnly Property RequestsWaitTimer_AnyProvider As IFormatProvider
<PropertyOption(ControlText:="Download data", <PropertyOption(ControlText:="Download data",
ControlToolTip:="The internal value indicates that site data should be downloaded." & vbCr & ControlToolTip:="The internal value indicates that site data should be downloaded." & vbCr &
"It becomes unchecked when the site returns an error."), PXML> "It becomes unchecked when the site returns an error.", Category:="Download"), PXML>
Friend ReadOnly Property DownloadData_Impl As PropertyValue Friend ReadOnly Property DownloadData_Impl As PropertyValue
#End Region #End Region
#End Region #End Region
@@ -103,8 +108,6 @@ Namespace API.ThreadsNet
With Responser With Responser
.Accept = "*/*" .Accept = "*/*"
'URGENT: remove after debug
.DeclaredError = EDP.SendToLog + EDP.ThrowException
If .UserAgentExists Then useragent = .UserAgent If .UserAgentExists Then useragent = .UserAgent
With .Headers With .Headers
If .Count > 0 Then If .Count > 0 Then
@@ -125,7 +128,10 @@ Namespace API.ThreadsNet
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecFetchMode, "cors")) .Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecFetchMode, "cors"))
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecFetchSite, "same-origin")) .Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecFetchSite, "same-origin"))
.Add("Sec-Fetch-User", "?1") .Add("Sec-Fetch-User", "?1")
.Add("dnt", 1)
.Add("drp", 1)
.Add(Instagram.UserData.GQL_HEADER_FB_FRINDLY_NAME, "BarcelonaProfileThreadsTabRefetchableQuery") .Add(Instagram.UserData.GQL_HEADER_FB_FRINDLY_NAME, "BarcelonaProfileThreadsTabRefetchableQuery")
.Remove("dht")
End With End With
.CookiesExtractMode = Responser.CookiesExtractModes.Any .CookiesExtractMode = Responser.CookiesExtractModes.Any
.CookiesUpdateMode = CookieKeeper.UpdateModes.ReplaceByNameAll .CookiesUpdateMode = CookieKeeper.UpdateModes.ReplaceByNameAll
@@ -195,7 +201,7 @@ Namespace API.ThreadsNet
End Sub End Sub
Friend Overrides Sub Update() Friend Overrides Sub Update()
If _SiteEditorFormOpened And Responser.CookiesExists Then If _SiteEditorFormOpened And Responser.CookiesExists Then
Dim csrf$ = If(Responser.Cookies.FirstOrDefault(Function(c) c.Name.StringToLower = IG.Header_CSRF_TOKEN_COOKIE)?.Value, String.Empty) Dim csrf$ = GetValueFromCookies(NameOf(HH_CSRF_TOKEN), Responser.Cookies)
If Not csrf.IsEmptyString Then HH_CSRF_TOKEN.Value = csrf If Not csrf.IsEmptyString Then HH_CSRF_TOKEN.Value = csrf
If Not __Cookies Is Nothing AndAlso Not __Cookies.ListEquals(Responser.Cookies) Then DownloadData_Impl.Value = True If Not __Cookies Is Nothing AndAlso Not __Cookies.ListEquals(Responser.Cookies) Then DownloadData_Impl.Value = True
End If End If

View File

@@ -17,6 +17,10 @@ Imports PersonalUtilities.Tools.Web.Clients.EventArguments
Imports IGS = SCrawler.API.Instagram.SiteSettings Imports IGS = SCrawler.API.Instagram.SiteSettings
Namespace API.ThreadsNet Namespace API.ThreadsNet
Friend Class UserData : Inherits Instagram.UserData Friend Class UserData : Inherits Instagram.UserData
#Region "XML names"
Private Const Name_MaxLastDownDate As String = "MaxLastDownDate"
Private Const Name_FirstLoadingDone As String = "FirstLoadingDone"
#End Region
#Region "Declarations" #Region "Declarations"
Private ReadOnly Property MySettings As SiteSettings Private ReadOnly Property MySettings As SiteSettings
Get Get
@@ -29,9 +33,20 @@ Namespace API.ThreadsNet
Return ValidateBaseTokens() And Not ID.IsEmptyString Return ValidateBaseTokens() And Not ID.IsEmptyString
End Get End Get
End Property End Property
Private Property MaxLastDownDate As Date? = Nothing
Private Property FirstLoadingDone As Boolean = False
#End Region #End Region
#Region "Loader" #Region "Loader"
Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean) Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean)
With Container
If Loading Then
MaxLastDownDate = AConvert(Of Date)(.Value(Name_MaxLastDownDate), DateTimeDefaultProvider, Nothing)
FirstLoadingDone = .Value(Name_FirstLoadingDone).FromXML(Of Boolean)(False)
Else
.Add(Name_MaxLastDownDate, AConvert(Of String)(MaxLastDownDate, DateTimeDefaultProvider, String.Empty))
.Add(Name_FirstLoadingDone, FirstLoadingDone.BoolToInteger)
End If
End With
End Sub End Sub
#End Region #End Region
#Region "Exchange" #Region "Exchange"
@@ -49,6 +64,7 @@ Namespace API.ThreadsNet
DefaultParser_PostUrlCreator = Function(post) $"https://www.threads.net/@{NameTrue}/post/{post.Code}" DefaultParser_PostUrlCreator = Function(post) $"https://www.threads.net/@{NameTrue}/post/{post.Code}"
_ResponserAutoUpdateCookies = True _ResponserAutoUpdateCookies = True
_ResponserAddResponseReceivedHandler = True _ResponserAddResponseReceivedHandler = True
DefaultParser_Pinned = AddressOf IsPinnedPost
End Sub End Sub
#End Region #End Region
#Region "Download functions" #Region "Download functions"
@@ -66,7 +82,27 @@ Namespace API.ThreadsNet
Responser.Method = "POST" Responser.Method = "POST"
LoadSavePostsKV(True) LoadSavePostsKV(True)
ResetBaseTokens() ResetBaseTokens()
Dim setMaxPostDate As Action(Of List(Of UserMedia)) =
Sub(ByVal l As List(Of UserMedia))
With (From c As UserMedia In l Where c.Post.Date.HasValue Select c.Post.Date.Value)
If .ListExists Then MaxLastDownDate = .Max : _ForceSaveUserInfo = True
End With
End Sub
If FirstLoadingDone Then
If Not MaxLastDownDate.HasValue And _ContentList.Count > 0 Then setMaxPostDate.Invoke(_ContentList)
Else
If _ContentList.Count > 0 Then
FirstLoadingDone = True
If Not MaxLastDownDate.HasValue Then setMaxPostDate.Invoke(_ContentList)
End If
End If
If FirstLoadingDone Then
DefaultParser_SkipPost = Nothing
Else
DefaultParser_SkipPost = AddressOf SkipPost
End If
DownloadData(String.Empty, Token) DownloadData(String.Empty, Token)
If _TempMediaList.Count > 0 Then FirstLoadingDone = True : setMaxPostDate.Invoke(_TempMediaList)
Catch ex As Exception Catch ex As Exception
errorFound = True errorFound = True
Throw ex Throw ex
@@ -78,6 +114,21 @@ Namespace API.ThreadsNet
End Try End Try
End If End If
End Sub End Sub
Private Function IsPinnedPost(ByVal Items As IEnumerable(Of EContainer), ByVal Index As Integer) As Boolean
Try
If MaxLastDownDate.HasValue Then
Dim d As Date? = AConvert(Of Date)(Items(Index).ItemF(DefaultParser_ElemNode_Default).Value("taken_at"), UnixDate32Provider, Nothing)
If d.HasValue Then Return d.Value < MaxLastDownDate.Value
End If
Return Not FirstLoadingDone
Catch ex As Exception
LogError(ex, "IsPinnedPost")
Return Not FirstLoadingDone
End Try
End Function
Private Function SkipPost(ByVal Items As IEnumerable(Of EContainer), ByVal Index As Integer, ByVal Post As PostKV) As Boolean
Return PostKvExists(Post)
End Function
Protected Overrides Sub UpdateResponser() Protected Overrides Sub UpdateResponser()
If Not Responser Is Nothing AndAlso Not Responser.Disposed Then If Not Responser Is Nothing AndAlso Not Responser.Disposed Then
RemoveHandler Responser.ResponseReceived, AddressOf Responser_ResponseReceived RemoveHandler Responser.ResponseReceived, AddressOf Responser_ResponseReceived
@@ -157,39 +208,34 @@ Namespace API.ThreadsNet
Private Function UpdateCredentials(Optional ByVal e As ErrorsDescriber = Nothing) As Boolean Private Function UpdateCredentials(Optional ByVal e As ErrorsDescriber = Nothing) As Boolean
Dim URL$ = $"https://www.threads.net/@{NameTrue}" Dim URL$ = $"https://www.threads.net/@{NameTrue}"
ResetBaseTokens() ResetBaseTokens()
Dim headers As New HttpHeaderCollection
headers.AddRange(Responser.Headers)
Try Try
Responser.Method = "GET" With Responser
Responser.Referer = URL .Method = "GET"
Responser.Headers.Remove(GQL_HEADER_FB_LSD) .Referer = URL
With .Headers
.Clear()
.Add("dnt", 1)
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.Authority, "www.threads.net"))
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.Origin, "https://www.threads.net"))
.Add("Sec-Ch-Ua-Model", "")
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaMobile, "?0"))
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecChUaPlatform, """Windows"""))
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecFetchDest, "document"))
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecFetchMode, "navigate"))
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecFetchSite, "none"))
.Add("Upgrade-Insecure-Requests", 1)
.Add("Sec-Fetch-User", "?1")
.Add(IGS.Header_Browser, MySettings.HH_BROWSER.Value)
.Add(IGS.Header_BrowserExt, MySettings.HH_BROWSER_EXT.Value)
End With
End With
WaitTimer() WaitTimer()
Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException) Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException)
Dim rr As RParams
Dim tt$, ttVal$
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
rr = RParams.DM(Instagram.PageTokenRegexPatternDefault, 0, RegexReturn.List, EDP.ReturnValue) ParseTokens(r, 0)
Dim tokens As List(Of String) = RegexReplace(r, rr) If ID.IsEmptyString Then ID = RegexReplace(r, RParams.DMS("""props"":\{""user_id"":""(\d+)""", 1, EDP.ReturnValue))
If tokens.ListExists Then
With rr
.Match = Nothing
.MatchSub = 1
.WhatGet = RegexReturn.Value
End With
For Each tt In tokens
If Not Token_dtsg.IsEmptyString And Not Token_lsd.IsEmptyString Then
Exit For
Else
ttVal = RegexReplace(tt, rr)
If Not ttVal.IsEmptyString Then
If ttVal.Contains(":") Then
If Token_dtsg.IsEmptyString Then Token_dtsg = ttVal
Else
If Token_lsd.IsEmptyString Then Token_lsd = ttVal
End If
End If
End If
Next
End If
If ID.IsEmptyString Then ID = RegexReplace(r, RParams.DMS("""props"":\{""user_id"":""(\d+)""\},", 1, EDP.ReturnValue))
End If End If
Return Valid Return Valid
Catch ex As Exception Catch ex As Exception
@@ -204,6 +250,12 @@ Namespace API.ThreadsNet
'LogError(ex, $"failed to update some{IIf(notFound.IsEmptyString, String.Empty, $" ({notFound})")} credentials", e) 'LogError(ex, $"failed to update some{IIf(notFound.IsEmptyString, String.Empty, $" ({notFound})")} credentials", e)
LogError(eex, String.Empty, e) LogError(eex, String.Empty, e)
Return False Return False
Finally
If headers.ListExists Then
Responser.Headers.Clear()
Responser.Headers.AddRange(headers)
headers.Dispose()
End If
End Try End Try
End Function End Function
#End Region #End Region

View File

@@ -15,6 +15,7 @@ Namespace API.Twitter
Friend Const TwitterSiteKey As String = "AndyProgram_Twitter" Friend Const TwitterSiteKey As String = "AndyProgram_Twitter"
Friend ReadOnly DateProvider As ADateTime = GetDateProvider() Friend ReadOnly DateProvider As ADateTime = GetDateProvider()
Friend ReadOnly VideoSizeRegEx As RParams = RParams.DMS("\d+x(\d+)", 1, EDP.ReturnValue) Friend ReadOnly VideoSizeRegEx As RParams = RParams.DMS("\d+x(\d+)", 1, EDP.ReturnValue)
Friend ReadOnly StatusRegEx As RParams = RParams.DM(".*?(twitter|x)\.com/\S+/status/\d+", 0, EDP.ReturnValue)
Private Function GetDateProvider() As ADateTime Private Function GetDateProvider() As ADateTime
Dim n As DateTimeFormatInfo = CultureInfo.GetCultureInfo("en-us").DateTimeFormat.Clone Dim n As DateTimeFormatInfo = CultureInfo.GetCultureInfo("en-us").DateTimeFormat.Clone
n.FullDateTimePattern = "ddd MMM dd HH:mm:ss +ffff yyyy" n.FullDateTimePattern = "ddd MMM dd HH:mm:ss +ffff yyyy"

View File

@@ -28,16 +28,20 @@ Namespace API.Twitter
Friend Overridable Property MediaModelAllowNonUserTweets As Boolean = False Friend Overridable Property MediaModelAllowNonUserTweets As Boolean = False
<PSetting(Address:=SettingAddress.User, <PSetting(Address:=SettingAddress.User,
Caption:="Download model 'Media'", Caption:="Download model 'Media'",
ToolTip:="Download the data using the 'https://twitter.com/UserName/media' command.", LeftOffset:=DefaultOffset)> ToolTip:="Download the data using the 'https://x.com/UserName/media' command.", LeftOffset:=DefaultOffset)>
Friend Overridable Property DownloadModelMedia As Boolean = False Friend Overridable Property DownloadModelMedia As Boolean = False
<PSetting(Address:=SettingAddress.User, <PSetting(Address:=SettingAddress.User,
Caption:="Download model 'Profile'", Caption:="Download model 'Profile'",
ToolTip:="Download the data using the 'https://twitter.com/UserName' command.", LeftOffset:=DefaultOffset)> ToolTip:="Download the data using the 'https://x.com/UserName' command.", LeftOffset:=DefaultOffset)>
Friend Overridable Property DownloadModelProfile As Boolean = False Friend Overridable Property DownloadModelProfile As Boolean = False
<PSetting(Address:=SettingAddress.User, <PSetting(Address:=SettingAddress.User,
Caption:="Download model 'Search'", Caption:="Download model 'Search'",
ToolTip:="Download the data using the 'https://twitter.com/search?q=from:UserName+include:nativeretweets' command.", LeftOffset:=DefaultOffset)> ToolTip:="Download the data using the 'https://x.com/search?q=from:UserName+include:nativeretweets' command.", LeftOffset:=DefaultOffset)>
Friend Overridable Property DownloadModelSearch As Boolean = False Friend Overridable Property DownloadModelSearch As Boolean = False
<PSetting(Address:=SettingAddress.User,
Caption:="Download model 'Likes'",
ToolTip:="Download the data using the 'https://x.com/UserName/likes' command.", LeftOffset:=DefaultOffset)>
Friend Overridable Property DownloadModelLikes As Boolean = False
<PSetting(Address:=SettingAddress.User, <PSetting(Address:=SettingAddress.User,
Caption:="Force apply", Caption:="Force apply",
ToolTip:="Force overrides the default parameters for the first download." & vbCr & "Applies to first download only.", LeftOffset:=DefaultOffset)> ToolTip:="Force overrides the default parameters for the first download." & vbCr & "Applies to first download only.", LeftOffset:=DefaultOffset)>
@@ -73,6 +77,7 @@ Namespace API.Twitter
DownloadModelMedia = dm.Contains(DModels.Media) DownloadModelMedia = dm.Contains(DModels.Media)
DownloadModelProfile = dm.Contains(DModels.Profile) DownloadModelProfile = dm.Contains(DModels.Profile)
DownloadModelSearch = dm.Contains(DModels.Search) DownloadModelSearch = dm.Contains(DModels.Search)
DownloadModelLikes = dm.Contains(DModels.Likes)
End If End If
End If End If
MySettings = u.HOST.Source MySettings = u.HOST.Source

View File

@@ -16,32 +16,37 @@ Namespace API.Twitter
<Manifest(TwitterSiteKey), SavedPosts, SeparatedTasks, SpecialForm(False)> <Manifest(TwitterSiteKey), SavedPosts, SeparatedTasks, SpecialForm(False)>
Friend Class SiteSettings : Inherits SiteSettingsBase Friend Class SiteSettings : Inherits SiteSettingsBase
#Region "Declarations" #Region "Declarations"
#Region "Categories"
Private Const CAT_DOWN As String = "Downloading"
#End Region
#Region "Other properties" #Region "Other properties"
<PropertyOption(ControlText:="Use the appropriate model", <PropertyOption(ControlText:="Use the appropriate model",
ControlToolTip:="Use the appropriate model for new users." & vbCr & ControlToolTip:="Use the appropriate model for new users." & vbCr &
"If disabled, all download models will be used for the first download. " & "If disabled, all download models will be used for the first download. " &
"Next, the appropriate download model will be automatically selected." & vbCr & "Next, the appropriate download model will be automatically selected." & vbCr &
"Otherwise the appropriate download model will be selected right from the start."), PXML, PClonable> "Otherwise the appropriate download model will be selected right from the start.", Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property UseAppropriateModel As PropertyValue Friend ReadOnly Property UseAppropriateModel As PropertyValue
#Region "End points" #Region "End points"
<PropertyOption(ControlText:="New endpoint: search", ControlToolTip:="Use new endpoint argument (-o search-endpoint=graphql) for the search model."), PXML, PClonable> <PropertyOption(ControlText:="New endpoint: search", ControlToolTip:="Use new endpoint argument (-o search-endpoint=graphql) for the search model.",
Category:=CAT_DOWN), PXML, PClonable>
Friend Property UseNewEndPointSearch As PropertyValue Friend Property UseNewEndPointSearch As PropertyValue
<PropertyOption(ControlText:="New endpoint: profiles", ControlToolTip:="Use new endpoint argument (-o search-endpoint=graphql) for the profile models."), PXML, PClonable> <PropertyOption(ControlText:="New endpoint: profiles", ControlToolTip:="Use new endpoint argument (-o search-endpoint=graphql) for the profile models.",
Category:=CAT_DOWN), PXML, PClonable>
Friend Property UseNewEndPointProfiles As PropertyValue Friend Property UseNewEndPointProfiles As PropertyValue
#End Region #End Region
#Region "Limits" #Region "Limits"
<PropertyOption(ControlText:="Abort on limit", ControlToolTip:="Abort twitter downloading when limit is reached"), PXML, PClonable> <PropertyOption(ControlText:="Abort on limit", ControlToolTip:="Abort twitter downloading when limit is reached", Category:=CAT_DOWN), PXML, PClonable>
Friend Property AbortOnLimit As PropertyValue Friend Property AbortOnLimit As PropertyValue
<PropertyOption(ControlText:="Download already parsed", ControlToolTip:="Download already parsed content on abort"), PXML, PClonable> <PropertyOption(ControlText:="Download already parsed", ControlToolTip:="Download already parsed content on abort", Category:=CAT_DOWN), PXML, PClonable>
Friend Property DownloadAlreadyParsed As PropertyValue Friend Property DownloadAlreadyParsed As PropertyValue
#End Region #End Region
<PropertyOption(ControlText:="Media Model: allow non-user tweets", ControlToolTip:="Allow downloading non-user tweets in the media-model."), PXML, PClonable> <PropertyOption(ControlText:="Media Model: allow non-user tweets", ControlToolTip:="Allow downloading non-user tweets in the media-model.", Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property MediaModelAllowNonUserTweets As PropertyValue Friend ReadOnly Property MediaModelAllowNonUserTweets As PropertyValue
<PropertyOption(ControlText:=DN.GifsDownloadCaption), PXML, PClonable> <PropertyOption(ControlText:=DN.GifsDownloadCaption, Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property GifsDownload As PropertyValue Friend ReadOnly Property GifsDownload As PropertyValue
<PropertyOption(ControlText:=DN.GifsSpecialFolderCaption, ControlToolTip:=DN.GifsSpecialFolderToolTip), PXML, PClonable> <PropertyOption(ControlText:=DN.GifsSpecialFolderCaption, ControlToolTip:=DN.GifsSpecialFolderToolTip, Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property GifsSpecialFolder As PropertyValue Friend ReadOnly Property GifsSpecialFolder As PropertyValue
<PropertyOption(ControlText:=DN.GifsPrefixCaption, ControlToolTip:=DN.GifsPrefixToolTip), PXML, PClonable> <PropertyOption(ControlText:=DN.GifsPrefixCaption, ControlToolTip:=DN.GifsPrefixToolTip, Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property GifsPrefix As PropertyValue Friend ReadOnly Property GifsPrefix As PropertyValue
<Provider(NameOf(GifsSpecialFolder), Interaction:=True), Provider(NameOf(GifsPrefix), Interaction:=True)> <Provider(NameOf(GifsSpecialFolder), Interaction:=True), Provider(NameOf(GifsPrefix), Interaction:=True)>
Private ReadOnly Property GifStringChecker As IFormatProvider Private ReadOnly Property GifStringChecker As IFormatProvider
@@ -63,17 +68,17 @@ Namespace API.Twitter
Throw New NotImplementedException("[GetFormat] is not available in the context of [GifStringProvider]") Throw New NotImplementedException("[GetFormat] is not available in the context of [GifStringProvider]")
End Function End Function
End Class End Class
<PropertyOption(ControlText:=DN.UseMD5ComparisonCaption, ControlToolTip:=DN.UseMD5ComparisonToolTip), PXML, PClonable> <PropertyOption(ControlText:=DN.UseMD5ComparisonCaption, ControlToolTip:=DN.UseMD5ComparisonToolTip, Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property UseMD5Comparison As PropertyValue Friend ReadOnly Property UseMD5Comparison As PropertyValue
<PropertyOption(ControlText:=DN.ConcurrentDownloadsCaption, <PropertyOption(ControlText:=DN.ConcurrentDownloadsCaption,
ControlToolTip:=DN.ConcurrentDownloadsToolTip, AllowNull:=False, LeftOffset:=120), PXML, TaskCounter, PClonable> ControlToolTip:=DN.ConcurrentDownloadsToolTip, AllowNull:=False, LeftOffset:=120, Category:=CAT_DOWN), PXML, TaskCounter, PClonable>
Friend ReadOnly Property ConcurrentDownloads As PropertyValue Friend ReadOnly Property ConcurrentDownloads As PropertyValue
<Provider(NameOf(ConcurrentDownloads), FieldsChecker:=True)> <Provider(NameOf(ConcurrentDownloads), FieldsChecker:=True)>
Private ReadOnly Property MyConcurrentDownloadsProvider As IFormatProvider Private ReadOnly Property MyConcurrentDownloadsProvider As IFormatProvider
#End Region #End Region
#End Region #End Region
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean) Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
MyBase.New(TwitterSite, "twitter.com", AccName, Temp, My.Resources.SiteResources.TwitterIcon_32, My.Resources.SiteResources.TwitterIcon_32.ToBitmap) MyBase.New(TwitterSite, "x.com", AccName, Temp, My.Resources.SiteResources.TwitterIcon_32, My.Resources.SiteResources.TwitterIcon_32.ToBitmap)
LimitSkippedUsers = New List(Of UserDataBase) LimitSkippedUsers = New List(Of UserDataBase)
@@ -96,8 +101,8 @@ Namespace API.Twitter
ConcurrentDownloads = New PropertyValue(1) ConcurrentDownloads = New PropertyValue(1)
MyConcurrentDownloadsProvider = New ConcurrentDownloadsProvider MyConcurrentDownloadsProvider = New ConcurrentDownloadsProvider
UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "/(twitter|x).com/"), 2) UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, $"/(twitter|x).com({CommunitiesUser}|)/"), 3)
UrlPatternUser = "https://twitter.com/{0}" UrlPatternUser = "https://x.com/{0}"
ImageVideoContains = "twitter" ImageVideoContains = "twitter"
CheckNetscapeCookiesOnEndInit = True CheckNetscapeCookiesOnEndInit = True
UseNetscapeCookies = True UseNetscapeCookies = True
@@ -105,8 +110,9 @@ Namespace API.Twitter
Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider
Return New UserData Return New UserData
End Function End Function
Friend Const SinglePostPattern As String = "https://x.com/i/web/status/{0}"
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
Return $"https://twitter.com/{User.Name}/status/{Media.Post.ID}" Return String.Format(SinglePostPattern, Media.Post.ID)
End Function End Function
Friend Overrides Function BaseAuthExists() As Boolean Friend Overrides Function BaseAuthExists() As Boolean
Return Responser.CookiesExists Return Responser.CookiesExists
@@ -146,5 +152,18 @@ Namespace API.Twitter
End If End If
MyBase.Update() MyBase.Update()
End Sub End Sub
Friend Const CommunitiesUser As String = "/i/communities"
Friend Overrides Function IsMyUser(ByVal UserURL As String) As ExchangeOptions
Dim e As ExchangeOptions = MyBase.IsMyUser(UserURL)
If Not e.UserName.IsEmptyString Then
If UserURL.Contains(CommunitiesUser) Then e.Options = CommunitiesUser : e.UserName &= "@c"
Return e
Else
Return Nothing
End If
End Function
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
Return DirectCast(User, UserData).GetUserUrl
End Function
End Class End Class
End Namespace End Namespace

View File

@@ -26,13 +26,30 @@ Namespace API.Twitter
Private Const Name_GifsDownload As String = "GifsDownload" Private Const Name_GifsDownload As String = "GifsDownload"
Private Const Name_GifsSpecialFolder As String = "GifsSpecialFolder" Private Const Name_GifsSpecialFolder As String = "GifsSpecialFolder"
Private Const Name_GifsPrefix As String = "GifsPrefix" Private Const Name_GifsPrefix As String = "GifsPrefix"
Private Const Name_IsCommunity As String = "IsCommunity"
#End Region #End Region
#Region "Declarations" #Region "Declarations"
Private Const Label_Community As String = "Community"
Private _NameTrue As String = String.Empty
Friend Property NameTrue As String
Get
Return _NameTrue.IfNullOrEmpty(Name)
End Get
Set(ByVal NewName As String)
_NameTrue = NewName
End Set
End Property
Friend Overrides ReadOnly Property SpecialLabels As IEnumerable(Of String)
Get
Return {Label_Community}
End Get
End Property
Friend Enum DownloadModels As Integer Friend Enum DownloadModels As Integer
Undefined = 0 Undefined = 0
Media = 1 Media = 1
Profile = 2 Profile = 2
Search = 5 Search = 5
Likes = 10
End Enum End Enum
Private FirstDownloadComplete As Boolean = False Private FirstDownloadComplete As Boolean = False
Friend Property DownloadModelForceApply As Boolean = False Friend Property DownloadModelForceApply As Boolean = False
@@ -41,6 +58,8 @@ Namespace API.Twitter
Friend Property GifsDownload As Boolean = True Friend Property GifsDownload As Boolean = True
Friend Property GifsSpecialFolder As String = String.Empty Friend Property GifsSpecialFolder As String = String.Empty
Friend Property GifsPrefix As String = String.Empty Friend Property GifsPrefix As String = String.Empty
Friend Property IsCommunity As Boolean = False
Private ReadOnly LikesPosts As List(Of String)
Private ReadOnly _DataNames As List(Of String) Private ReadOnly _DataNames As List(Of String)
Private ReadOnly Property MySettings As SiteSettings Private ReadOnly Property MySettings As SiteSettings
Get Get
@@ -55,6 +74,9 @@ Namespace API.Twitter
Private Function RenameGdlFile(ByVal Input As SFile, ByVal i As Integer) As SFile Private Function RenameGdlFile(ByVal Input As SFile, ByVal i As Integer) As SFile
Return SFile.Rename(Input, $"{Input.PathWithSeparator}{i.NumToString(FileNameProvider)}.{Input.Extension}",, EDP.ThrowException) Return SFile.Rename(Input, $"{Input.PathWithSeparator}{i.NumToString(FileNameProvider)}.{Input.Extension}",, EDP.ThrowException)
End Function End Function
Friend Function GetUserUrl() As String
Return $"https://x.com{IIf(IsCommunity, SiteSettings.CommunitiesUser, String.Empty)}/{NameTrue}"
End Function
#End Region #End Region
#Region "Exchange options" #Region "Exchange options"
Friend Overrides Function ExchangeOptionsGet() As Object Friend Overrides Function ExchangeOptionsGet() As Object
@@ -74,6 +96,7 @@ Namespace API.Twitter
If .DownloadModelMedia Then DownloadModel += DownloadModels.Media If .DownloadModelMedia Then DownloadModel += DownloadModels.Media
If .DownloadModelProfile Then DownloadModel += DownloadModels.Profile If .DownloadModelProfile Then DownloadModel += DownloadModels.Profile
If .DownloadModelSearch Then DownloadModel += DownloadModels.Search If .DownloadModelSearch Then DownloadModel += DownloadModels.Search
If .DownloadModelLikes Then DownloadModel += DownloadModels.Likes
End With End With
End If End If
End Sub End Sub
@@ -81,6 +104,7 @@ Namespace API.Twitter
#Region "Initializer, loader" #Region "Initializer, loader"
Friend Sub New() Friend Sub New()
_DataNames = New List(Of String) _DataNames = New List(Of String)
LikesPosts = New List(Of String)
End Sub End Sub
Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean) Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean)
With Container With Container
@@ -117,7 +141,20 @@ Namespace API.Twitter
RemoveExistingDuplicates = .Value(Name_RemoveExistingDuplicates).FromXML(Of Boolean)(False) RemoveExistingDuplicates = .Value(Name_RemoveExistingDuplicates).FromXML(Of Boolean)(False)
StartMD5Checked = .Value(Name_StartMD5Checked).FromXML(Of Boolean)(False) StartMD5Checked = .Value(Name_StartMD5Checked).FromXML(Of Boolean)(False)
MediaModelAllowNonUserTweets = .Value(Name_MediaModelAllowNonUserTweets).FromXML(Of Boolean)(False) MediaModelAllowNonUserTweets = .Value(Name_MediaModelAllowNonUserTweets).FromXML(Of Boolean)(False)
IsCommunity = .Value(Name_IsCommunity).FromXML(Of Boolean)(False)
_NameTrue = .Value(Name_TrueName)
Else Else
If Name.Contains("@") And Not IsCommunity Then
IsCommunity = True
_NameTrue = Name.Split("@")(0)
ID = _NameTrue
ParseUserMediaOnly = False
Labels.ListAddValue(Label_Community, LNC)
Labels.Sort()
.Add(Name_UserID, ID)
.Add(Name_LabelsName, LabelsString)
.Add(Name_ParseUserMediaOnly, ParseUserMediaOnly.BoolToInteger)
End If
.Add(Name_FirstDownloadComplete, FirstDownloadComplete.BoolToInteger) .Add(Name_FirstDownloadComplete, FirstDownloadComplete.BoolToInteger)
.Add(Name_DownloadModelForceApply, DownloadModelForceApply.BoolToInteger) .Add(Name_DownloadModelForceApply, DownloadModelForceApply.BoolToInteger)
.Add(Name_DownloadModel, CInt(DownloadModel)) .Add(Name_DownloadModel, CInt(DownloadModel))
@@ -128,6 +165,8 @@ Namespace API.Twitter
.Add(Name_RemoveExistingDuplicates, RemoveExistingDuplicates.BoolToInteger) .Add(Name_RemoveExistingDuplicates, RemoveExistingDuplicates.BoolToInteger)
.Add(Name_StartMD5Checked, StartMD5Checked.BoolToInteger) .Add(Name_StartMD5Checked, StartMD5Checked.BoolToInteger)
.Add(Name_MediaModelAllowNonUserTweets, MediaModelAllowNonUserTweets.BoolToInteger) .Add(Name_MediaModelAllowNonUserTweets, MediaModelAllowNonUserTweets.BoolToInteger)
.Add(Name_IsCommunity, IsCommunity.BoolToInteger)
.Add(Name_TrueName, _NameTrue)
End If End If
End With End With
End Sub End Sub
@@ -142,21 +181,32 @@ Namespace API.Twitter
} }
End Function End Function
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
If MySettings.LIMIT_ABORT Then Try
Throw New TwitterLimitException(Me) If MySettings.LIMIT_ABORT Then
Else Throw New TwitterLimitException(Me)
If IsSavedPosts Then
If _ContentList.Count > 0 Then _DataNames.ListAddList(_ContentList.Select(Function(c) c.Post.ID), LAP.ClearBeforeAdd, LAP.NotContainsOnly)
DownloadData_SavedPosts(Token)
Else Else
If _ContentList.Count > 0 Then _DataNames.ListAddList(_ContentList.Select(Function(c) c.File.File), LAP.ClearBeforeAdd, LAP.NotContainsOnly) If IsSavedPosts Then
DownloadData_Timeline(Token) If _ContentList.Count > 0 Then _DataNames.ListAddList(_ContentList.Select(Function(c) c.Post.ID), LAP.ClearBeforeAdd, LAP.NotContainsOnly)
DownloadData_SavedPosts(Token)
Else
LikesPosts.Clear()
If _ContentList.Count > 0 Then _DataNames.ListAddList(_ContentList.Select(Function(c) c.File.File), LAP.ClearBeforeAdd, LAP.NotContainsOnly)
DownloadData_Timeline(Token)
If LikesPosts.Count > 0 Then
_ReparseLikes = True
ReparseMissing(Token)
_ReparseLikes = False
End If
End If
End If End If
End If Finally
_ReparseLikes = False
End Try
End Sub End Sub
Private Sub DownloadData_Timeline(ByVal Token As CancellationToken) Private Sub DownloadData_Timeline(ByVal Token As CancellationToken)
Dim URL$ = String.Empty Dim URL$ = String.Empty
Dim tCache As CacheKeeper = Nothing Dim tCache As CacheKeeper = Nothing
Dim likesDetected As Boolean = False
Try Try
Const entry$ = "entry" Const entry$ = "entry"
Dim PostID$ = String.Empty Dim PostID$ = String.Empty
@@ -173,14 +223,15 @@ Namespace API.Twitter
Dim newTwitterNodes() As Object = {0, "content", "items"} Dim newTwitterNodes() As Object = {0, "content", "items"}
Dim p As Predicate(Of EContainer) Dim p As Predicate(Of EContainer)
Dim pIndx% Dim pIndx%
Dim indxChanged As Boolean = False
Dim isOneNode As Boolean, isPins As Boolean, ExistsDetected As Boolean, userInfoParsed As Boolean = False Dim isOneNode As Boolean, isPins As Boolean, ExistsDetected As Boolean, userInfoParsed As Boolean = False
Dim j As EContainer, rootNode As EContainer, optionalNode As EContainer, workingNode As EContainer, tmpNode As EContainer, nn As EContainer = Nothing Dim j As EContainer, rootNode As EContainer, optionalNode As EContainer, workingNode As EContainer, tmpNode As EContainer, nn As EContainer = Nothing
Dim __parseContainer As Func(Of EContainer, Boolean) = Dim __parseContainer As Func(Of EContainer, Boolean) =
Function(ByVal ee As EContainer) As Boolean Function(ByVal ee As EContainer) As Boolean
nn = Nothing nn = Nothing
If dirIndx > 1 Then nn = ee If dirIndx > 1 Or IsCommunity Then nn = ee
If Not nn.ListExists Then If Not nn.ListExists Or IsCommunity Then
For Each node In nodes For Each node In nodes
nn = ee(node) nn = ee(node)
If nn.ListExists Then Exit For If nn.ListExists Then Exit For
@@ -199,6 +250,7 @@ Namespace API.Twitter
If Not _TempPostsList.Contains(PostID) Then If Not _TempPostsList.Contains(PostID) Then
_TempPostsList.Add(PostID) _TempPostsList.Add(PostID)
ElseIf dirIndx = 3 Then
ElseIf isPins Then ElseIf isPins Then
Return False Return False
Else Else
@@ -211,9 +263,22 @@ Namespace API.Twitter
If tmpUserId.IsEmptyString Then tmpUserId = nn.ItemF({"extended_entities", "media", 0, sourceIdPredicate}).XmlIfNothingValue. If tmpUserId.IsEmptyString Then tmpUserId = nn.ItemF({"extended_entities", "media", 0, sourceIdPredicate}).XmlIfNothingValue.
IfNullOrEmpty(nn.Value("user_id")).IfNullOrEmpty(nn.Value("user_id_str")).IfNullOrEmpty("/") IfNullOrEmpty(nn.Value("user_id")).IfNullOrEmpty(nn.Value("user_id_str")).IfNullOrEmpty("/")
If Not ParseUserMediaOnly OrElse If (Not ParseUserMediaOnly Or dirIndx = 3) OrElse
(dirIndx = 0 AndAlso MediaModelAllowNonUserTweets) OrElse (dirIndx = 0 AndAlso MediaModelAllowNonUserTweets) OrElse
(Not ID.IsEmptyString AndAlso tmpUserId = ID) Then ObtainMedia(nn, PostID, PostDate) (Not ID.IsEmptyString AndAlso tmpUserId = ID) Then
If dirIndx = 3 Then
Dim lUrl$ = nn.ItemF({"content", "itemContent", "tweet_results", "result", "legacy", "entities", "media", 0}, "expanded_url").XmlIfNothingValue
If Not lUrl.IsEmptyString Then
lUrl = RegexReplace(lUrl, StatusRegEx)
If Not lUrl.IsEmptyString Then
If Not _TempPostsList.Contains(lUrl) Then _TempPostsList.Add(lUrl) Else Return False
LikesPosts.ListAddValue(lUrl, LNC)
End If
End If
Else
ObtainMedia(nn, PostID, PostDate)
End If
End If
End If End If
Return True Return True
End Function End Function
@@ -225,6 +290,8 @@ Namespace API.Twitter
For Each dir As SFile In dirs For Each dir As SFile In dirs
dirIndx += 1 dirIndx += 1
If dirIndx = 3 Then likesDetected = True
ExistsDetected = False ExistsDetected = False
If Not dir.IsEmptyString Then If Not dir.IsEmptyString Then
@@ -238,10 +305,22 @@ Namespace API.Twitter
For i = 0 To timelineFiles.Count - 1 For i = 0 To timelineFiles.Count - 1
j = JsonDocument.Parse(timelineFiles(i).GetText) j = JsonDocument.Parse(timelineFiles(i).GetText)
If Not j Is Nothing Then If Not j Is Nothing Then
If i = 0 Then If i = 0 And Not indxChanged Then
If Not userInfoParsed Then If Not userInfoParsed Then
userInfoParsed = True userInfoParsed = True
Dim resValue$ = j.Value({"data", "user", "result"}, "__typename").StringTrim.StringToLower Dim resValue$ = j.Value({"data", IIf(IsCommunity, "communityResults", "user"), "result"}, "__typename").StringTrim.StringToLower
Dim icon$
Dim __getImage As Action(Of String) = Sub(ByVal img As String)
If Not img.IsEmptyString Then
Dim __imgFile As SFile = UrlFile(img, True)
If Not __imgFile.Name.IsEmptyString Then
If __imgFile.Extension.IsEmptyString Then __imgFile.Extension = "jpg"
__imgFile.Path = MyFile.CutPath.Path
If Not __imgFile.Exists Then GetWebFile(img, __imgFile, EDP.None)
If __imgFile.Exists Then IconBannerDownloaded = True
End If
End If
End Sub
If resValue.IsEmptyString Then If resValue.IsEmptyString Then
UserExists = False UserExists = False
j.Dispose() j.Dispose()
@@ -250,6 +329,29 @@ Namespace API.Twitter
UserSuspended = True UserSuspended = True
j.Dispose() j.Dispose()
Exit Sub Exit Sub
ElseIf IsCommunity Then
With j({"data", "communityResults", "result", "community_media_timeline", "timeline", "instructions"})
If .ListExists Then
With .Find(entriesNode, True)
If .ListExists Then
With .ItemF({0, "content", "items", 0, "item", "itemContent", "tweet_results", "result", "tweet", "community_results", "result"})
If .ListExists Then
If ID = .Value("id_str") Then
UserSiteNameUpdate(.Value("name"))
UserDescriptionUpdate(.Value("description"))
icon = .Value({"custom_banner_media", "media_info"}, "original_img_url").
IfNullOrEmpty(.Value({"default_banner_media", "media_info"}, "original_img_url"))
If Not icon.IsEmptyString And DownloadIconBanner Then __getImage.Invoke(icon)
End If
End If
End With
End If
End With
End If
End With
i = -1
indxChanged = True
Else Else
With j({"data", "user", "result"}) With j({"data", "user", "result"})
If .ListExists Then If .ListExists Then
@@ -259,21 +361,11 @@ Namespace API.Twitter
End If End If
With .Item({"legacy"}) With .Item({"legacy"})
If .ListExists Then If .ListExists Then
If .Value("screen_name").StringToLower = Name.ToLower Then If .Value("screen_name").StringToLower = NameTrue.ToLower Then
UserSiteNameUpdate(.Value("name")) UserSiteNameUpdate(.Value("name"))
UserDescriptionUpdate(.Value("description")) UserDescriptionUpdate(.Value("description"))
Dim __getImage As Action(Of String) = Sub(ByVal img As String)
If Not img.IsEmptyString Then icon = .Value("profile_image_url_https")
Dim __imgFile As SFile = UrlFile(img, True)
If Not __imgFile.Name.IsEmptyString Then
If __imgFile.Extension.IsEmptyString Then __imgFile.Extension = "jpg"
__imgFile.Path = MyFile.CutPath.Path
If Not __imgFile.Exists Then GetWebFile(img, __imgFile, EDP.None)
If __imgFile.Exists Then IconBannerDownloaded = True
End If
End If
End Sub
Dim icon$ = .Value("profile_image_url_https")
If Not icon.IsEmptyString Then icon = icon.Replace("_normal", String.Empty) If Not icon.IsEmptyString Then icon = icon.Replace("_normal", String.Empty)
If DownloadIconBanner Then If DownloadIconBanner Then
__getImage.Invoke(.Value("profile_banner_url")) __getImage.Invoke(.Value("profile_banner_url"))
@@ -285,29 +377,55 @@ Namespace API.Twitter
End If End If
End With End With
End If End If
ElseIf IsCommunity Then
i = -1
indxChanged = True
End If End If
Else Else
For pIndx = 0 To IIf(dirIndx < 2, 1, 0) For pIndx = 0 To IIf(dirIndx < 2 Or dirIndx = 3, 1, 0)
optionalNode = Nothing optionalNode = Nothing
Select Case dirIndx rootNode = Nothing
Case 0, 1 If IsCommunity Then
rootNode = j({"data", "user", "result", "timeline_v2", "timeline", "instructions"}) With j({"data", "communityResults", "result", "community_media_timeline", "timeline", "instructions"})
If rootNode.ListExists Then If .ListExists Then
p = If(pIndx = 0, pinNode, timelineNode) If i = 0 Then
isPins = pIndx = 0 rootNode = .Find(entriesNode, True)
Else
rootNode = .Find(moduleItemsPredicate, True)
End If
optionalNode = rootNode optionalNode = rootNode
rootNode = rootNode.Find(p, False)
If rootNode.ListExists Then rootNode = rootNode.Find(entriesNode, False)
End If End If
Case Else End With
isPins = False Else
rootNode = j({"globalObjects", "tweets"}) Select Case dirIndx
optionalNode = rootNode Case 0, 1, 3
End Select rootNode = j({"data", "user", "result", "timeline_v2", "timeline", "instructions"})
If rootNode.ListExists Then
If dirIndx = 3 Then
p = entriesNode
isPins = False
Else
p = If(pIndx = 0, pinNode, timelineNode)
isPins = pIndx = 0
End If
optionalNode = rootNode
rootNode = rootNode.Find(p, dirIndx = 3)
If dirIndx <> 3 And rootNode.ListExists Then rootNode = rootNode.Find(entriesNode, dirIndx = 3)
End If
Case Else
isPins = False
rootNode = j({"globalObjects", "tweets"})
optionalNode = rootNode
End Select
End If
If rootNode.ListExists Then If rootNode.ListExists Then
With rootNode With rootNode
isOneNode = dirIndx < 2 AndAlso .Name = entry If IsCommunity Then
isOneNode = pIndx = 0
Else
isOneNode = dirIndx < 2 AndAlso .Name = entry
End If
ProgressPre.ChangeMax(If(isOneNode, 1, .Count)) ProgressPre.ChangeMax(If(isOneNode, 1, .Count))
If isOneNode Then If isOneNode Then
ProgressPre.Perform() ProgressPre.Perform()
@@ -369,12 +487,12 @@ Namespace API.Twitter
ProcessException(ex, Token, $"data downloading error [{URL}]") ProcessException(ex, Token, $"data downloading error [{URL}]")
Finally Finally
If Not tCache Is Nothing Then tCache.Dispose() If Not tCache Is Nothing Then tCache.Dispose()
If _TempPostsList.Count > 0 Then _TempPostsList.Sort() If _TempPostsList.Count > 0 And Not likesDetected Then _TempPostsList.Sort()
End Try End Try
End Sub End Sub
Private Sub DownloadData_SavedPosts(ByVal Token As CancellationToken) Private Sub DownloadData_SavedPosts(ByVal Token As CancellationToken)
Try Try
Dim f As SFile = GetDataFromGalleryDL("https://twitter.com/i/bookmarks", Settings.Cache, True, Token) Dim f As SFile = GetDataFromGalleryDL("https://x.com/i/bookmarks", Settings.Cache, True, Token)
Dim files As List(Of SFile) = SFile.GetFiles(f, "*.txt") Dim files As List(Of SFile) = SFile.GetFiles(f, "*.txt")
If files.ListExists Then If files.ListExists Then
ResetFileNameProvider(Math.Max(files.Count.ToString.Length, 3)) ResetFileNameProvider(Math.Max(files.Count.ToString.Length, 3))
@@ -417,21 +535,24 @@ Namespace API.Twitter
#End Region #End Region
#Region "Obtain media" #Region "Obtain media"
Private Sub ObtainMedia(ByVal e As EContainer, ByVal PostID As String, ByVal PostDate As String, Optional ByVal State As UStates = UStates.Unknown, Private Sub ObtainMedia(ByVal e As EContainer, ByVal PostID As String, ByVal PostDate As String, Optional ByVal State As UStates = UStates.Unknown,
Optional ByVal Attempts As Integer = 0) Optional ByVal Attempts As Integer = 0, Optional ByVal SpecialFolder As String = Nothing)
Dim s As EContainer = e({"extended_entities", "media"}) Dim s As EContainer = e({"extended_entities", "media"})
If If(s?.Count, 0) = 0 Then s = e({"retweeted_status", "extended_entities", "media"}) If If(s?.Count, 0) = 0 Then s = e({"retweeted_status", "extended_entities", "media"})
If If(s?.Count, 0) = 0 Then s = e({"retweeted_status_result", "result", "legacy", "extended_entities", "media"}) If If(s?.Count, 0) = 0 Then s = e({"retweeted_status_result", "result", "legacy", "extended_entities", "media"})
If If(s?.Count, 0) > 0 Then If If(s?.Count, 0) > 0 Then
Dim mUrl$ Dim mUrl$
Dim media As UserMedia
For Each m As EContainer In s For Each m As EContainer In s
If Not CheckVideoNode(m, PostID, PostDate, State) Then If Not CheckVideoNode(m, PostID, PostDate, State, SpecialFolder) Then
mUrl = m.Value("media_url").IfNullOrEmpty(m.Value("media_url_https")) mUrl = m.Value("media_url").IfNullOrEmpty(m.Value("media_url_https"))
If Not mUrl.IsEmptyString Then If Not mUrl.IsEmptyString Then
Dim dName$ = UrlFile(mUrl) Dim dName$ = UrlFile(mUrl)
If Not dName.IsEmptyString AndAlso Not _DataNames.Contains(dName) Then If Not dName.IsEmptyString AndAlso Not _DataNames.Contains(dName) Then
_DataNames.Add(dName) _DataNames.Add(dName)
_TempMediaList.ListAddValue(MediaFromData(mUrl, PostID, PostDate, GetPictureOption(m), State, UTypes.Picture, Attempts), LNC) media = MediaFromData(mUrl, PostID, PostDate, GetPictureOption(m), State, UTypes.Picture, Attempts)
If Not SpecialFolder.IsEmptyString Then media.SpecialFolder = SpecialFolder
_TempMediaList.ListAddValue(media, LNC)
End If End If
End If End If
End If End If
@@ -439,15 +560,17 @@ Namespace API.Twitter
End If End If
End Sub End Sub
Private Function CheckVideoNode(ByVal w As EContainer, ByVal PostID As String, ByVal PostDate As String, Private Function CheckVideoNode(ByVal w As EContainer, ByVal PostID As String, ByVal PostDate As String,
Optional ByVal State As UStates = UStates.Unknown) As Boolean Optional ByVal State As UStates = UStates.Unknown, Optional ByVal SpecialFolder As String = Nothing) As Boolean
Try Try
If CheckForGif(w, PostID, PostDate, State) Then Return True If CheckForGif(w, PostID, PostDate, State, SpecialFolder) Then Return True
Dim URL$ = GetVideoNodeURL(w) Dim URL$ = GetVideoNodeURL(w)
If Not URL.IsEmptyString Then If Not URL.IsEmptyString Then
Dim f$ = UrlFile(URL) Dim f$ = UrlFile(URL)
If Not f.IsEmptyString AndAlso Not _DataNames.Contains(f) Then If Not f.IsEmptyString AndAlso Not _DataNames.Contains(f) Then
_DataNames.Add(f) _DataNames.Add(f)
_TempMediaList.ListAddValue(MediaFromData(URL, PostID, PostDate,, State, UTypes.Video), LNC) Dim m As UserMedia = MediaFromData(URL, PostID, PostDate,, State, UTypes.Video)
If Not SpecialFolder.IsEmptyString Then m.SpecialFolder = SpecialFolder
_TempMediaList.ListAddValue(m, LNC)
End If End If
Return True Return True
End If End If
@@ -458,7 +581,7 @@ Namespace API.Twitter
End Try End Try
End Function End Function
Private Function CheckForGif(ByVal w As EContainer, ByVal PostID As String, ByVal PostDate As String, Private Function CheckForGif(ByVal w As EContainer, ByVal PostID As String, ByVal PostDate As String,
Optional ByVal State As UStates = UStates.Unknown) As Boolean Optional ByVal State As UStates = UStates.Unknown, Optional ByVal SpecialFolder As String = Nothing) As Boolean
Try Try
Dim gifUrl As Predicate(Of EContainer) = Function(e) Not e.Value("content_type").IsEmptyString AndAlso Dim gifUrl As Predicate(Of EContainer) = Function(e) Not e.Value("content_type").IsEmptyString AndAlso
e.Value("content_type").Contains("mp4") AndAlso e.Value("content_type").Contains("mp4") AndAlso
@@ -477,9 +600,13 @@ Namespace API.Twitter
If Not ff.IsEmptyString Then If Not ff.IsEmptyString Then
If GifsDownload And Not _DataNames.Contains(ff) Then If GifsDownload And Not _DataNames.Contains(ff) Then
m = MediaFromData(url, PostID, PostDate,, State, UTypes.Video) m = MediaFromData(url, PostID, PostDate,, State, UTypes.Video)
If Not SpecialFolder.IsEmptyString Then m.SpecialFolder = SpecialFolder
f = m.File f = m.File
If Not f.IsEmptyString And Not GifsPrefix.IsEmptyString Then f.Name = $"{GifsPrefix}{f.Name}" : m.File = f If Not f.IsEmptyString And Not GifsPrefix.IsEmptyString Then f.Name = $"{GifsPrefix}{f.Name}" : m.File = f
If Not GifsSpecialFolder.IsEmptyString Then m.SpecialFolder = $"{GifsSpecialFolder}*" If Not GifsSpecialFolder.IsEmptyString Then
If Not m.SpecialFolder.IsEmptyString Then m.SpecialFolder &= "\"
m.SpecialFolder &= $"{GifsSpecialFolder}*"
End If
_TempMediaList.ListAddValue(m, LNC) _TempMediaList.ListAddValue(m, LNC)
End If End If
Return True Return True
@@ -615,6 +742,7 @@ Namespace API.Twitter
Dim dir As SFile Dim dir As SFile
Dim dm As List(Of DownloadModels) = EnumExtract(Of DownloadModels)(DownloadModel).ListIfNothing Dim dm As List(Of DownloadModels) = EnumExtract(Of DownloadModels)(DownloadModel).ListIfNothing
Dim process As Boolean Dim process As Boolean
Dim urlPrePattern$ = $"https://x.com{IIf(IsCommunity, SiteSettings.CommunitiesUser, String.Empty)}/"
Using tgdl As New TwitterGDL(Nothing, Token, MySettings.AbortOnLimit.Value) With { Using tgdl As New TwitterGDL(Nothing, Token, MySettings.AbortOnLimit.Value) With {
.TempPostsList = _TempPostsList, .TempPostsList = _TempPostsList,
@@ -625,7 +753,7 @@ Namespace API.Twitter
} }
tgdl.FileExchanger.DeleteCacheOnDispose = False tgdl.FileExchanger.DeleteCacheOnDispose = False
tgdl.FileExchanger.DeleteRootOnDispose = False tgdl.FileExchanger.DeleteRootOnDispose = False
For i As Byte = 0 To 2 For i As Byte = 0 To IIf(IsCommunity, 0, 3)
dir = rootDir.NewPath dir = rootDir.NewPath
dir.Exists(SFO.Path, True, EDP.ThrowException) dir.Exists(SFO.Path, True, EDP.ThrowException)
outList.Add(dir) outList.Add(dir)
@@ -633,9 +761,10 @@ Namespace API.Twitter
command = $"""{Settings.GalleryDLFile}"" --verbose --no-download --no-skip --config ""{conf}"" --write-pages " command = $"""{Settings.GalleryDLFile}"" --verbose --no-download --no-skip --config ""{conf}"" --write-pages "
command &= GdlGetIdFilterString() command &= GdlGetIdFilterString()
Select Case i Select Case i
Case 0 : command &= $"https://twitter.com/{Name}/media" : process = dm.Contains(DownloadModels.Media) Case 0 : command &= $"{urlPrePattern}{NameTrue}/media" : process = dm.Contains(DownloadModels.Media) Or IsCommunity
Case 1 : command &= $"https://twitter.com/{Name}" : process = dm.Contains(DownloadModels.Profile) Case 1 : command &= $"{urlPrePattern}{NameTrue}" : process = dm.Contains(DownloadModels.Profile)
Case 2 : command &= $"-o search-endpoint=graphql https://twitter.com/search?q=from:{Name}+include:nativeretweets" : process = dm.Contains(DownloadModels.Search) Case 2 : command &= $"-o search-endpoint=graphql https://x.com/search?q=from:{NameTrue}+include:nativeretweets" : process = dm.Contains(DownloadModels.Search) And Not IsCommunity
Case 3 : command &= $"{urlPrePattern}{NameTrue}/likes" : process = dm.Contains(DownloadModels.Likes)
Case Else : process = False Case Else : process = False
End Select End Select
'#If DEBUG Then '#If DEBUG Then
@@ -687,13 +816,13 @@ Namespace API.Twitter
End Function End Function
#End Region #End Region
#Region "ReparseMissing" #Region "ReparseMissing"
Private _ReparseLikes As Boolean = False
Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken) Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken)
Const SinglePostPattern$ = "https://twitter.com/{0}/status/{1}"
Dim rList As New List(Of Integer) Dim rList As New List(Of Integer)
Dim URL$ = String.Empty Dim URL$ = String.Empty
Dim cache As CacheKeeper = Nothing Dim cache As CacheKeeper = Nothing
Try Try
If ContentMissingExists Then If ContentMissingExists Or (_ReparseLikes And LikesPosts.Count > 0) Then
Dim m As UserMedia Dim m As UserMedia
Dim PostDate$ Dim PostDate$
Dim nodes As List(Of String()) = GetContainerSubnodes() Dim nodes As List(Of String()) = GetContainerSubnodes()
@@ -702,24 +831,24 @@ Namespace API.Twitter
Dim f As SFile Dim f As SFile
Dim i%, ii% Dim i%, ii%
Dim files As List(Of SFile) Dim files As List(Of SFile)
Dim lim%
Dim specFolder$ = IIf(_ReparseLikes, "Likes", String.Empty)
ResetFileNameProvider() ResetFileNameProvider()
If IsSingleObjectDownload Then cache = If(IsSingleObjectDownload, Settings.Cache, CreateCache())
cache = Settings.Cache If _ReparseLikes Then lim = LikesPosts.Count Else lim = _ContentList.Count
Else ProgressPre.ChangeMax(lim)
cache = New CacheKeeper(DownloadContentDefault_GetRootDir.CSFilePS) For i = 0 To lim - 1
cache.CacheDeleteError = CacheDeletionError(cache)
End If
ProgressPre.ChangeMax(_ContentList.Count)
For i = 0 To _ContentList.Count - 1
ProgressPre.Perform() ProgressPre.Perform()
If _ContentList(i).State = UStates.Missing Then If _ReparseLikes OrElse _ContentList(i).State = UStates.Missing Then
m = _ContentList(i) m = If(_ReparseLikes, Nothing, _ContentList(i))
If Not m.Post.ID.IsEmptyString Or (IsSingleObjectDownload And Not m.URL_BASE.IsEmptyString) Then If Not m.Post.ID.IsEmptyString Or (IsSingleObjectDownload And Not m.URL_BASE.IsEmptyString) Or _ReparseLikes Then
ThrowAny(Token) ThrowAny(Token)
If IsSingleObjectDownload Then If IsSingleObjectDownload Then
URL = m.URL_BASE URL = m.URL_BASE
ElseIf _ReparseLikes Then
URL = LikesPosts(i)
Else Else
URL = String.Format(SinglePostPattern, Name, m.Post.ID) URL = String.Format(SiteSettings.SinglePostPattern, m.Post.ID)
End If End If
f = GetDataFromGalleryDL(URL, cache, False, Token) f = GetDataFromGalleryDL(URL, cache, False, Token)
If Not f.IsEmptyString Then If Not f.IsEmptyString Then
@@ -737,7 +866,7 @@ Namespace API.Twitter
If .ListExists Then If .ListExists Then
PostDate = String.Empty PostDate = String.Empty
If .Contains("created_at") Then PostDate = .Value("created_at") Else PostDate = String.Empty If .Contains("created_at") Then PostDate = .Value("created_at") Else PostDate = String.Empty
ObtainMedia(.Self, m.Post.ID, PostDate, UStates.Missing, m.Attempts) ObtainMedia(.Self, m.Post.ID, PostDate, UStates.Missing, m.Attempts, specFolder)
rList.ListAddValue(i, LNC) rList.ListAddValue(i, LNC)
End If End If
End With End With
@@ -759,7 +888,7 @@ Namespace API.Twitter
ProcessException(ex, Token, $"ReparseMissing error [{URL}]") ProcessException(ex, Token, $"ReparseMissing error [{URL}]")
Finally Finally
If Not cache Is Nothing And Not IsSingleObjectDownload Then cache.Dispose() If Not cache Is Nothing And Not IsSingleObjectDownload Then cache.Dispose()
If rList.Count > 0 Then If rList.Count > 0 And Not _ReparseLikes Then
For i% = rList.Count - 1 To 0 Step -1 : _ContentList.RemoveAt(rList(i)) : Next For i% = rList.Count - 1 To 0 Step -1 : _ContentList.RemoveAt(rList(i)) : Next
rList.Clear() rList.Clear()
End If End If
@@ -856,7 +985,7 @@ Namespace API.Twitter
#End Region #End Region
#Region "IDisposable support" #Region "IDisposable support"
Protected Overrides Sub Dispose(ByVal disposing As Boolean) Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If Not disposedValue And disposing Then _DataNames.Clear() If Not disposedValue And disposing Then _DataNames.Clear() : LikesPosts.Clear()
MyBase.Dispose(disposing) MyBase.Dispose(disposing)
End Sub End Sub
#End Region #End Region

View File

@@ -558,7 +558,7 @@ Namespace API
End Sub End Sub
#End Region #End Region
#Region "Move, Merge" #Region "Move, Merge"
Friend Overrides Function MoveFiles(ByVal __CollectionName As String, ByVal __SpecialCollectionPath As SFile) As Boolean Friend Overrides Function MoveFiles(ByVal __CollectionName As String, ByVal __SpecialCollectionPath As SFile, Optional ByVal NewUser As SplitCollectionUserInfo? = Nothing) As Boolean
Throw New NotImplementedException("Move files is not available in the collection context") Throw New NotImplementedException("Move files is not available in the collection context")
End Function End Function
Friend Overloads Sub MergeData(ByVal Merging As Boolean) Friend Overloads Sub MergeData(ByVal Merging As Boolean)
@@ -601,7 +601,19 @@ Namespace API
"Operation canceled", MsgBoxStyle.Critical) "Operation canceled", MsgBoxStyle.Critical)
Return False Return False
Else Else
_Item.MoveFiles(String.Empty, Nothing) Dim uObj As SplitCollectionUserInfo? = DirectCast(_Item, UserDataBase).SplitCollectionGetNewUserInfo
If uObj.Value.SameDrive Then
uObj = Nothing
Else
Using f As New SplitCollectionUserInfoChangePathsForm({uObj})
f.ShowDialog()
Select Case f.DialogResult
Case DialogResult.OK : If f.Users(0).Changed Then uObj = f.Users(0) Else uObj = Nothing
Case DialogResult.Abort : Return False
End Select
End Using
End If
_Item.MoveFiles(String.Empty, Nothing, uObj)
MainFrameObj.ImageHandler(_Item) MainFrameObj.ImageHandler(_Item)
AddRemoveBttDeleteHandler(_Item, False) AddRemoveBttDeleteHandler(_Item, False)
RaiseEvent OnUserRemoved(_Item) RaiseEvent OnUserRemoved(_Item)
@@ -618,7 +630,7 @@ Namespace API
End If End If
Dim m As New MMessage($"Collection [{CollectionName} (number of profiles: {Count})] may contain data" & vbCr & Dim m As New MMessage($"Collection [{CollectionName} (number of profiles: {Count})] may contain data" & vbCr &
"Are you sure you want to delete the collection and all of its files?", MsgTitle, "Are you sure you want to delete the collection and all of its files?", MsgTitle,
{New MsgBoxButton("Delete") With {.ToolTip = "Delete the collection and all files", .KeyCode = Keys.Enter}, {New MsgBoxButton("Delete", "Delete the collection and all files") With {.KeyCode = Keys.Enter},
New MsgBoxButton("Split") With { New MsgBoxButton("Split") With {
.ToolTip = "Users will be removed from the collection and will be displayed in the program as separate users." & vbCr & .ToolTip = "Users will be removed from the collection and will be displayed in the program as separate users." & vbCr &
"All user data will remain.", "All user data will remain.",
@@ -653,12 +665,31 @@ Namespace API
MsgBoxE({$"Collection [{CollectionName}] data merged{vbCr}Unable to split merged collection{vbCr}Operation canceled", MsgTitle}, vbExclamation) MsgBoxE({$"Collection [{CollectionName}] data merged{vbCr}Unable to split merged collection{vbCr}Operation canceled", MsgTitle}, vbExclamation)
Return 0 Return 0
Else Else
Collections.ForEach(Sub(ByVal c As IUserData) Dim uu As New List(Of SplitCollectionUserInfo)(Collections.Select(Function(uuu As UserDataBase) uuu.SplitCollectionGetNewUserInfo))
If c.MoveFiles(String.Empty, Nothing) Then If uu.All(Function(uuu) uuu.SameDrive) Then
UserListLoader.UpdateUser(Settings.GetUser(c), True) uu.Clear()
MainFrameObj.ImageHandler(c) Else
End If Using colPaths As New SplitCollectionUserInfoChangePathsForm(uu)
End Sub) colPaths.ShowDialog()
Select Case colPaths.DialogResult
Case DialogResult.OK
If colPaths.Users.Any(Function(uuu) uuu.Changed) Then
uu = New List(Of SplitCollectionUserInfo)(colPaths.Users)
Else
uu.Clear()
End If
Case DialogResult.Abort : Return 0
End Select
End Using
End If
Collections.ListForEach(Sub(ByVal c As IUserData, ByVal indx As Integer)
Dim uObj As SplitCollectionUserInfo? = Nothing
If uu.Count > 0 AndAlso indx.ValueBetween(0, uu.Count - 1) AndAlso uu(indx).Changed Then uObj = uu(indx)
If c.MoveFiles(String.Empty, Nothing, uObj) Then
UserListLoader.UpdateUser(Settings.GetUser(c), True)
MainFrameObj.ImageHandler(c)
End If
End Sub)
If Collections.All(Function(c) c.CollectionName.IsEmptyString) Then If Collections.All(Function(c) c.CollectionName.IsEmptyString) Then
Settings.Users.Remove(Me) Settings.Users.Remove(Me)
Collections.Clear() Collections.Clear()

View File

@@ -265,7 +265,12 @@ Namespace API.Xhamster
Dim checkLimit As Func(Of Boolean) = Function() limit > 0 And SearchPostsCount >= limit And IsVideo Dim checkLimit As Func(Of Boolean) = Function() limit > 0 And SearchPostsCount >= limit And IsVideo
If IsSavedPosts Then If IsSavedPosts Then
containerNodes.Add(If(IsVideo, {"favoriteVideoListComponent", "models"}, {"favoritesGalleriesAndPhotosCollection"})) If IsVideo Then
containerNodes.Add({"favoriteVideoListComponent", "models"})
containerNodes.Add({"favoriteVideoListComponent", "videoThumbProps"})
Else
containerNodes.Add({"favoritesGalleriesAndPhotosCollection"})
End If
ElseIf Not SiteMode = SiteModes.Search Then ElseIf Not SiteMode = SiteModes.Search Then
If IsVideo Then If IsVideo Then
containerNodes.Add({"trendingVideoListComponent", "models"}) containerNodes.Add({"trendingVideoListComponent", "models"})
@@ -280,32 +285,18 @@ Namespace API.Xhamster
End If End If
End If End If
'TODELETE: xHamster remove old container nodes attachments
If IsSavedPosts Then If IsSavedPosts Then
URL = $"https://xhamster.com/my/favorites/{IIf(IsVideo, "videos", "photos-and-galleries")}{IIf(Page = 1, String.Empty, $"/{Page}")}" URL = $"https://xhamster.com/my/favorites/{IIf(IsVideo, "videos", "photos-and-galleries")}{IIf(Page = 1, String.Empty, $"/{Page}")}"
containerNodes.Add(If(IsVideo, {"favoriteVideoListComponent", "models"}, {"favoritesGalleriesAndPhotosCollection"})) containerNodes.Add(If(IsVideo, {"favoriteVideoListComponent", "models"}, {"favoritesGalleriesAndPhotosCollection"}))
ElseIf IsChannel Then ElseIf IsChannel Then
URL = $"https://xhamster.com/channels/{TrueName}/newest{IIf(Page = 1, String.Empty, $"/{Page}")}" URL = $"https://xhamster.com/channels/{TrueName}/newest{IIf(Page = 1, String.Empty, $"/{Page}")}"
'containerNodes.Add({"trendingVideoListComponent", "models"})
'containerNodes.Add({"pagesCategoryComponent", "trendingVideoListProps", "models"})
ElseIf SiteMode = SiteModes.Search Then ElseIf SiteMode = SiteModes.Search Then
URL = GetNonUserUrl(Page) URL = GetNonUserUrl(Page)
containerNodes.Add({"searchResult", "models"}) containerNodes.Add({"searchResult", "models"})
ElseIf IsCreator Or SiteMode = SiteModes.Tags Or SiteMode = SiteModes.Categories Or SiteMode = SiteModes.Pornstars Then ElseIf IsCreator Or SiteMode = SiteModes.Tags Or SiteMode = SiteModes.Categories Or SiteMode = SiteModes.Pornstars Then
URL = GetNonUserUrl(Page) URL = GetNonUserUrl(Page)
'If SiteMode = SiteModes.Pornstars Then
' containerNodes.Add({"trendingVideoListComponent", "models"})
' containerNodes.Add({"pagesCategoryComponent", "trendingVideoListProps", "models"})
'Else
' containerNodes.Add({"pagesCategoryComponent", "trendingVideoListProps", "models"})
' containerNodes.Add({"trendingVideoListComponent", "models"})
'End If
'containerNodes.Add({"trendingVideoSectionComponent", "videoModels"})
Else Else
URL = $"https://xhamster.com/users/{TrueName}/{IIf(IsVideo, "videos", "photos")}{IIf(Page = 1, String.Empty, $"/{Page}")}" URL = $"https://xhamster.com/users/{TrueName}/{IIf(IsVideo, "videos", "photos")}{IIf(Page = 1, String.Empty, $"/{Page}")}"
'containerNodes.Add({If(IsVideo, "userVideoCollection", "userGalleriesCollection")})
'containerNodes.Add(If(IsVideo, {"videoListComponent", "models"}, {"userGalleriesCollection"}))
End If End If
ThrowAny(Token) ThrowAny(Token)

View File

@@ -59,10 +59,10 @@ Namespace API.YouTube
.Cookies.Clear() .Cookies.Clear()
.Cookies.AddRange(Responser.Cookies) .Cookies.AddRange(Responser.Cookies)
.CookiesUpdated = True .CookiesUpdated = True
.PerformUpdate()
End With End With
End If End If
End With End With
DirectCast(MyYouTubeSettings, YTSettings_Internal).PerformUpdate()
End If End If
MyBase.Update() MyBase.Update()
End Sub End Sub

View File

@@ -58,7 +58,6 @@ Namespace DownloadObjects
End If End If
Catch ex As Exception Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "Change 'ActiveDownloadingProgress' size") ErrorsDescriber.Execute(EDP.SendToLog, ex, "Change 'ActiveDownloadingProgress' size")
MainFrameObj.UpdateLogButton()
End Try End Try
End Sub End Sub
Private Sub Downloader_Reconfigured() Private Sub Downloader_Reconfigured()

View File

@@ -16,11 +16,13 @@ Imports PersonalUtilities.Tools.Notifications
Namespace DownloadObjects Namespace DownloadObjects
Friend Class AutoDownloader : Inherits GroupParameters : Implements IIndexable, IEContainerProvider, IComparable(Of AutoDownloader) Friend Class AutoDownloader : Inherits GroupParameters : Implements IIndexable, IEContainerProvider, IComparable(Of AutoDownloader)
Friend Event PauseChanged(ByVal Value As PauseModes) Friend Event PauseChanged(ByVal Value As PauseModes)
Friend Event PlanChanged As Scheduler.PlanChangedEventHandler
Friend Enum Modes As Integer Friend Enum Modes As Integer
None = 0 None = 0
Specified = 3 Specified = 3
Groups = 4 Groups = 4
End Enum End Enum
Friend Const NoPauseMode As Integer = -100
Friend Enum PauseModes As Integer Friend Enum PauseModes As Integer
Disabled = -2 Disabled = -2
Enabled = -1 Enabled = -1
@@ -198,6 +200,52 @@ Namespace DownloadObjects
Private Const Name_ShowSimpleNotification As String = "ShowSimpleNotification" Private Const Name_ShowSimpleNotification As String = "ShowSimpleNotification"
#End Region #End Region
#Region "Declarations" #Region "Declarations"
Private _LVIState As Integer = 0
Friend Function LVIStateChanged() As Boolean
Dim ____LVIState%
Dim result As Boolean
If Downloading Then
____LVIState = 1
ElseIf DownloadReady(True, True) Or ForceStartRequested Then
____LVIState = 2
ElseIf Not Working And Not IsManual Then
____LVIState = 3
ElseIf IsPaused Then
____LVIState = 4
ElseIf Settings.AutomationBrushUndownloadedPlansMinutes.Value > 0 AndAlso
LastDownloadDate.AddMinutes(Settings.AutomationBrushUndownloadedPlansMinutes.Value) < Now Then
____LVIState = 5
Else
____LVIState = 0
End If
result = Not _LVIState = ____LVIState
_LVIState = ____LVIState
Return result
End Function
Friend ReadOnly Property LVI As ListViewItem
Get
Dim l As New ListViewItem(ToString)
If Downloading Then
l.BackColor = MyColor.OkBack
l.ForeColor = MyColor.OkFore
ElseIf DownloadReady(True, True) Or ForceStartRequested Then
l.BackColor = MyColor.EditBack
l.ForeColor = MyColor.EditFore
ElseIf Not Working And Not IsManual Then
l.BackColor = MyColor.DeleteBack
l.ForeColor = MyColor.DeleteFore
ElseIf Working And IsPaused And Not IsManual Then
l.BackColor = MyColor.UpdateBack
l.ForeColor = MyColor.UpdateFore
ElseIf Settings.AutomationBrushUndownloadedPlansMinutes.Value > 0 AndAlso
LastDownloadDate.AddMinutes(Settings.AutomationBrushUndownloadedPlansMinutes.Value) < Now Then
l.BackColor = Color.FromArgb(224, 224, 224)
l.ForeColor = Color.FromArgb(64, 64, 64)
End If
LVIStateChanged()
Return l
End Get
End Property
Friend Property Source As Scheduler Friend Property Source As Scheduler
Private _Mode As Modes = Modes.None Private _Mode As Modes = Modes.None
Friend Property Mode As Modes Friend Property Mode As Modes
@@ -266,11 +314,15 @@ Namespace DownloadObjects
End Property End Property
Private Function GetWorkingState() As String Private Function GetWorkingState() As String
Dim OutStr$ Dim OutStr$
If Working Then If Working And Not IsManual Then
If StartupDelay > 0 And _StartTime.AddMinutes(StartupDelay) > Now Then If _Downloading Then
OutStr = $"delayed until {_StartTime.AddMinutes(StartupDelay).ToStringDate(ADateTime.Formats.BaseDateTime)}" OutStr = "downloading"
ElseIf _ForceStartRequested Then
OutStr = "force start pending"
ElseIf _StopRequested Then ElseIf _StopRequested Then
OutStr = "stopping" OutStr = "stopping"
ElseIf StartupDelay > 0 And _StartTime.AddMinutes(StartupDelay) > Now Then
OutStr = $"delayed ({StartupDelay}) until {_StartTime.AddMinutes(StartupDelay).ToStringDate(ADateTime.Formats.BaseDateTime)}"
Else Else
OutStr = "working" OutStr = "working"
End If End If
@@ -281,14 +333,26 @@ Namespace DownloadObjects
Case Else : OutStr &= $", paused ([{Pause}] until {AConvert(Of String)(_PauseValue, ADateTime.Formats.BaseDateTime, "?")})" Case Else : OutStr &= $", paused ([{Pause}] until {AConvert(Of String)(_PauseValue, ADateTime.Formats.BaseDateTime, "?")})"
End Select End Select
End If End If
ElseIf IsManual Then
If _Downloading Then
OutStr = "downloading"
ElseIf _ForceStartRequested Then
OutStr = "force start pending"
Else
OutStr = String.Empty
End If
Else Else
OutStr = "stopped" OutStr = "stopped"
End If End If
Return OutStr Return OutStr
End Function End Function
Private Function GetWorkingState_Manual() As String
Dim OutStr$ = GetWorkingState()
If Not OutStr.IsEmptyString Then Return $" ({OutStr})" Else Return String.Empty
End Function
Public Overrides Function ToString() As String Public Overrides Function ToString() As String
If IsManual Then If IsManual Then
Return $"{Name} (manual): last download date: {GetLastDateString()}" Return $"{Name} (manual{GetWorkingState_Manual()}): last download date: {GetLastDateString()}"
Else Else
Return $"{Name} ({GetWorkingState()}): last download date: {GetLastDateString()}; next run: {GetNextDateString()}" Return $"{Name} ({GetWorkingState()}): last download date: {GetLastDateString()}; next run: {GetNextDateString()}"
End If End If
@@ -315,6 +379,7 @@ Namespace DownloadObjects
Friend Sub New(ByVal x As EContainer) Friend Sub New(ByVal x As EContainer)
Me.New Me.New
Initialization = True Initialization = True
'URGENT: replace this line
Dim m% = x.Value(Name_Mode).FromXML(Of Integer)(Modes.None) Dim m% = x.Value(Name_Mode).FromXML(Of Integer)(Modes.None)
If m = 1 Or m = 2 Then m = Modes.Specified If m = 1 Or m = 2 Then m = Modes.Specified
Mode = m Mode = m
@@ -394,10 +459,10 @@ Namespace DownloadObjects
End Function End Function
#End Region #End Region
#Region "Execution" #Region "Execution"
Private AThread As Thread Private _Working As Boolean = False
Friend ReadOnly Property Working As Boolean Friend ReadOnly Property Working As Boolean
Get Get
Return If(AThread?.IsAlive, False) Return _Working
End Get End Get
End Property End Property
Private _StartTime As Date = Now Private _StartTime As Date = Now
@@ -405,11 +470,8 @@ Namespace DownloadObjects
If Not IsManual Or Force Then If Not IsManual Or Force Then
If Init Then _StartTime = Now If Init Then _StartTime = Now
_IsNewPlan = False _IsNewPlan = False
If Not Working And Not Mode = Modes.None Then If Not Working And Not Mode = Modes.None Then _Working = True
AThread = New Thread(New ThreadStart(AddressOf Checker)) RaiseEvent PlanChanged(Me)
AThread.SetApartmentState(ApartmentState.MTA)
AThread.Start()
End If
End If End If
End Sub End Sub
Private _StopRequested As Boolean = False Private _StopRequested As Boolean = False
@@ -433,6 +495,7 @@ Namespace DownloadObjects
Case Else : _PauseValue = Nothing Case Else : _PauseValue = Nothing
End Select End Select
RaiseEvent PauseChanged(p) RaiseEvent PauseChanged(p)
RaiseEvent PlanChanged(Me)
End Set End Set
End Property End Property
Private ReadOnly Property IsPaused As Boolean Private ReadOnly Property IsPaused As Boolean
@@ -456,7 +519,10 @@ Namespace DownloadObjects
End Get End Get
End Property End Property
Friend Sub [Stop]() Friend Sub [Stop]()
If Working Then _StopRequested = True If Working Then
If Downloading Then _StopRequested = True Else _Working = False
RaiseEvent PlanChanged(Me)
End If
End Sub End Sub
Friend Overloads Sub Skip() Friend Overloads Sub Skip()
If LastDownloadDate.AddMinutes(Timer) <= Now Then If LastDownloadDate.AddMinutes(Timer) <= Now Then
@@ -464,65 +530,59 @@ Namespace DownloadObjects
Else Else
_LastDownloadDateSkip = LastDownloadDate.AddMinutes(Timer) _LastDownloadDateSkip = LastDownloadDate.AddMinutes(Timer)
End If End If
RaiseEvent PlanChanged(Me)
End Sub End Sub
Friend Overloads Sub Skip(ByVal Minutes As Integer) Friend Overloads Sub Skip(ByVal Minutes As Integer)
_LastDownloadDateSkip = If(_LastDownloadDateSkip, Now).AddMinutes(Minutes) _LastDownloadDateSkip = If(_LastDownloadDateSkip, Now).AddMinutes(Minutes)
RaiseEvent PlanChanged(Me)
End Sub End Sub
Friend Overloads Sub Skip(ByVal ToDate As Date) Friend Overloads Sub Skip(ByVal ToDate As Date)
_LastDownloadDateSkip = ToDate _LastDownloadDateSkip = ToDate
RaiseEvent PlanChanged(Me)
End Sub End Sub
Friend Sub SkipReset() Friend Sub SkipReset()
_LastDownloadDateSkip = Nothing _LastDownloadDateSkip = Nothing
RaiseEvent PlanChanged(Me)
End Sub End Sub
Friend Sub ForceStart() Friend Sub ForceStart()
_ForceStartRequested = True _ForceStartRequested = True
If IsManual Then Start(False, True) If IsManual Then Start(False, True)
RaiseEvent PlanChanged(Me)
End Sub End Sub
Private _ForceStartRequested As Boolean = False Private _ForceStartRequested As Boolean = False
Private _SpecialDelayUse As Boolean = False Friend ReadOnly Property ForceStartRequested As Boolean
Private _SpecialDelayTime As Date? = Nothing Get
Private Sub Checker() Return _ForceStartRequested
Try End Get
Dim _StartDownload As Boolean End Property
While (Not _StopRequested Or Downloader.Working) And Not Mode = Modes.None Friend ReadOnly Property DownloadReady(Optional ByVal IgnorePause As Boolean = False, Optional ByVal IgnoreDownloaderWorking As Boolean = False) As Boolean
If ((IsManual And _ForceStartRequested) Or (NextExecutionDate < Now And Not IsPaused) Or _ForceStartRequested) And Get
Not _StopRequested And Not Mode = Modes.None Then If _StopRequested Then _Working = False
If Downloader.Working Then Return (Working Or IsManual) And ((IsManual And _ForceStartRequested) Or (Not IsManual And NextExecutionDate < Now And (Not IsPaused Or IgnorePause)) Or _ForceStartRequested) And
_SpecialDelayUse = True Not _StopRequested And Not Mode = Modes.None And (Not Downloader.Working Or IgnoreDownloaderWorking)
Else End Get
If _SpecialDelayUse And Not _SpecialDelayTime.HasValue Then _SpecialDelayTime = Now.AddSeconds(10) End Property
If Not _SpecialDelayUse OrElse (_SpecialDelayTime.HasValue AndAlso _SpecialDelayTime.Value < Now) Then Friend ReadOnly Property NextDate As Date?
_SpecialDelayUse = False Get
_SpecialDelayTime = Nothing If Not _StopRequested And Not Mode = Modes.None Then
_StartDownload = False If IsManual Or _ForceStartRequested Then
If Settings.Automation.Count = 1 Or _ForceStartRequested Or Index = -1 Then Return Now.AddYears(-10)
_StartDownload = True ElseIf Not IsPaused And Not IsManual And Working Then
Else Return NextExecutionDate
_StartDownload = NextExecutionDate.AddMilliseconds(1000 * (Index + 1)).Ticks <= Now.Ticks
End If
If _StartDownload Then
Download()
If IsManual Then Exit While
End If
End If
End If
End If End If
Thread.Sleep(500) End If
End While Return Nothing
Catch ex As Exception End Get
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[AutoDownloader.Checker]") End Property
Finally
_StopRequested = False
End Try
End Sub
Private _Downloading As Boolean = False Private _Downloading As Boolean = False
Friend ReadOnly Property Downloading As Boolean Friend ReadOnly Property Downloading As Boolean
Get Get
Return _Downloading Return _Downloading
End Get End Get
End Property End Property
Private Sub Download() Friend Sub Download()
_Downloading = True _Downloading = True
RaiseEvent PlanChanged(Me)
Dim Keys As New List(Of String) Dim Keys As New List(Of String)
Try Try
Dim users As New List(Of IUserData) Dim users As New List(Of IUserData)
@@ -572,11 +632,23 @@ Namespace DownloadObjects
With Downloader With Downloader
.AutoDownloaderWorking = True .AutoDownloaderWorking = True
If .Downloaded.Count > 0 Then .Downloaded.RemoveAll(Function(u) Keys.Contains(u.Key)) : .InvokeDownloadsChangeEvent() If .Downloaded.Count > 0 Then .Downloaded.RemoveAll(Function(u) Keys.Contains(u.Key)) : .InvokeDownloadsChangeEvent()
Do : Try : doRound += 1 : .AddRange(users, True) : Exit Do : Catch iex As IndexOutOfRangeException : Thread.Sleep(200) : End Try : Loop While doRound < doLim Do
Try
doRound += 1
.AddRange(users, True)
Exit Do
Catch iex As Exception
If doRound = doLim Then
Throw iex
Else
Thread.Sleep(200)
End If
End Try
Loop While doRound <= doLim
While .Working Or .Count > 0 : notify.Invoke() : Thread.Sleep(200) : End While While .Working Or .Count > 0 : notify.Invoke() : Thread.Sleep(200) : End While
.AutoDownloaderWorking = False .AutoDownloaderWorking = False
notify.Invoke notify.Invoke
If simple And DownloadedUsersCount + DownloadedSubscriptionsCount > 0 Then If simple And (DownloadedUsersCount + DownloadedSubscriptionsCount) > 0 Then
Dim msg$ = String.Empty Dim msg$ = String.Empty
If DownloadedUsersCount > 0 Then msg = $"{DownloadedUsersCount} user(s) " If DownloadedUsersCount > 0 Then msg = $"{DownloadedUsersCount} user(s) "
If DownloadedSubscriptionsCount > 0 Then msg &= $"{IIf(DownloadedUsersCount > 0, "and ", String.Empty)}{DownloadedSubscriptionsCount} subscription(s) " If DownloadedSubscriptionsCount > 0 Then msg &= $"{IIf(DownloadedUsersCount > 0, "and ", String.Empty)}{DownloadedSubscriptionsCount} subscription(s) "
@@ -586,7 +658,7 @@ Namespace DownloadObjects
End With End With
End If End If
Catch ex As Exception Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[AutoDownloader.Download]") ErrorsDescriber.Execute(EDP.SendToLog, ex, $"[AutoDownloader.Download({Name})]")
Finally Finally
Keys.Clear() Keys.Clear()
LastDownloadDate = Now LastDownloadDate = Now
@@ -594,6 +666,8 @@ Namespace DownloadObjects
_Downloading = False _Downloading = False
_ForceStartRequested = False _ForceStartRequested = False
_LastDownloadDateSkip = Nothing _LastDownloadDateSkip = Nothing
If _StopRequested Then _Working = False
RaiseEvent PlanChanged(Me)
End Try End Try
End Sub End Sub
Private Sub ShowNotification(ByVal u As IUserData) Private Sub ShowNotification(ByVal u As IUserData)

View File

@@ -28,9 +28,10 @@ Namespace DownloadObjects
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(AutoDownloaderEditorForm)) Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(AutoDownloaderEditorForm))
Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TP_NOTIFY As System.Windows.Forms.TableLayoutPanel
Dim ActionButton3 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton3 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TP_NOTIFY As System.Windows.Forms.TableLayoutPanel
Dim ActionButton4 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton4 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton5 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TT_MAIN As System.Windows.Forms.ToolTip Dim TT_MAIN As System.Windows.Forms.ToolTip
Me.DEF_GROUP = New SCrawler.DownloadObjects.Groups.GroupDefaults() Me.DEF_GROUP = New SCrawler.DownloadObjects.Groups.GroupDefaults()
Me.OPT_SPEC = New System.Windows.Forms.RadioButton() Me.OPT_SPEC = New System.Windows.Forms.RadioButton()
@@ -178,9 +179,14 @@ Namespace DownloadObjects
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image) ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
ActionButton1.Name = "Edit" ActionButton1.Name = "Edit"
ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image) ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image)
ActionButton2.Name = "Clear" ActionButton2.Name = "Info"
ActionButton2.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Info
ActionButton2.ToolTipText = "Open group"
ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image)
ActionButton3.Name = "Clear"
Me.TXT_GROUPS.Buttons.Add(ActionButton1) Me.TXT_GROUPS.Buttons.Add(ActionButton1)
Me.TXT_GROUPS.Buttons.Add(ActionButton2) Me.TXT_GROUPS.Buttons.Add(ActionButton2)
Me.TXT_GROUPS.Buttons.Add(ActionButton3)
Me.TXT_GROUPS.CaptionText = "Groups" Me.TXT_GROUPS.CaptionText = "Groups"
Me.TXT_GROUPS.CaptionWidth = 50.0R Me.TXT_GROUPS.CaptionWidth = 50.0R
Me.TXT_GROUPS.Dock = System.Windows.Forms.DockStyle.Fill Me.TXT_GROUPS.Dock = System.Windows.Forms.DockStyle.Fill
@@ -260,9 +266,9 @@ Namespace DownloadObjects
' '
'TXT_TIMER 'TXT_TIMER
' '
ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image) ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image)
ActionButton3.Name = "Refresh" ActionButton4.Name = "Refresh"
Me.TXT_TIMER.Buttons.Add(ActionButton3) Me.TXT_TIMER.Buttons.Add(ActionButton4)
Me.TXT_TIMER.CaptionText = "Timer" Me.TXT_TIMER.CaptionText = "Timer"
Me.TXT_TIMER.CaptionToolTipEnabled = True Me.TXT_TIMER.CaptionToolTipEnabled = True
Me.TXT_TIMER.CaptionToolTipText = "Timer (in minutes)" Me.TXT_TIMER.CaptionToolTipText = "Timer (in minutes)"
@@ -275,9 +281,9 @@ Namespace DownloadObjects
' '
'NUM_DELAY 'NUM_DELAY
' '
ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image) ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image)
ActionButton4.Name = "Refresh" ActionButton5.Name = "Refresh"
Me.NUM_DELAY.Buttons.Add(ActionButton4) Me.NUM_DELAY.Buttons.Add(ActionButton5)
Me.NUM_DELAY.CaptionText = "Delay" Me.NUM_DELAY.CaptionText = "Delay"
Me.NUM_DELAY.CaptionToolTipEnabled = True Me.NUM_DELAY.CaptionToolTipEnabled = True
Me.NUM_DELAY.CaptionToolTipText = "Startup delay" Me.NUM_DELAY.CaptionToolTipText = "Startup delay"

View File

@@ -189,6 +189,18 @@
</value> </value>
</data> </data>
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1
MAAA6mAAADqYAAAXb5JfxUYAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAFQSURBVFhH7ZfNDcIwFIMZoXcm
YBtGYRHECIgTR1ZhBsS9YoJgQ1Poi5sfqhIOWPqkqvV7dWlI0oVzriry5Dd5HSS0PFwasAEn0AJn4Dle
o6fpykaVHYDNwB7YG6ZgzWiQrABosAbqaXNh7bprN1AyAAp3b42msuva9ooGYIFpELA931D2FI+VxzAI
gTIdAEb+7KpBz+p4RclQyifoXwdKwgAwcMAl3/mEAOz9GJgokQGyR/sHr8CzlwFwgU+vCuagUQE4gSjz
HGxUAM5iyiyxUp4IJ5QEAYomHCvlidCiJAigjKNYKU8M6B/g9wJUH4TV/4ZFE5GV8kSQE1HRVGylPBHC
qbh0MbJSnhH0YtQFyFqOiZXyCOLLMQVDckNCrJRHEN+QeMGY3JJZKY8hb0vmxQLTYAplm1IvFNbblnuh
Qb0Pk3exGZjv06wW8uT3cIs7jQnSONrSxH0AAAAASUVORK5CYII=
</value>
</data>
<data name="ActionButton3.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
@@ -203,22 +215,6 @@
<value>Show a simple notification instead of a user notification. <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. 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> The 'Image' and 'User icon' parameters will be ignored.</value>
</data>
<data name="ActionButton3.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
QVQ4T2P4//8/QczOJyyqHpzfiE0OQwAZC8iqszAzs7CJ69o4BR768V/W2jcGXQ0KB4aFNS3dDQtnrbCb
ePCK48wTN1wXXXzge/jXf/clV55zC4hIIatF0cjIyMikElzc57z0wX+XHd/+2+//99/ywP//xlu//tdb
+eK/4Zp3/1WTOhYzARViNUAluKjTdf37/0ZTTn9TbdhwXblhwwW1/qOP1Ja9+K8w+95/6cm3/6v2Xvkv
qKjniGGAoIqRpW3/4e8S9uGdzFz82gwMDFxAzCxm4ZegtuLDf+VJ1/8rZM25IqLvnM/CximCYYCic1QN
v7x2JIwPwyrJ3XNUylddE9G2TWNmZOBDl4czmJiZMSRBmFdSyYyJgUEQmxwIYxWEYXZBCUls4sgYq6CA
prWNbtG8nXKeaVPR5XiVjSxEzf0yYXy4BBMLO6eQjoOXZvrkbbazrv53Xf/2v4CSbjBMXkhBl1/CMyNZ
qWnvGy5pNQ+YONwAfjXzAOupl/47LLr333L50/96q9/8l23YdES6cO5KuYqVW+R7Tj6SnfP0v4hryjyY
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value>
</data> </data>
<data name="ActionButton4.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton4.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
@@ -234,6 +230,22 @@ The 'Image' and 'User icon' parameters will be ignored.</value>
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74 HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg== VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value>
</data>
<data name="ActionButton5.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
QVQ4T2P4//8/QczOJyyqHpzfiE0OQwAZC8iqszAzs7CJ69o4BR768V/W2jcGXQ0KB4aFNS3dDQtnrbCb
ePCK48wTN1wXXXzge/jXf/clV55zC4hIIatF0cjIyMikElzc57z0wX+XHd/+2+//99/ywP//xlu//tdb
+eK/4Zp3/1WTOhYzARViNUAluKjTdf37/0ZTTn9TbdhwXblhwwW1/qOP1Ja9+K8w+95/6cm3/6v2Xvkv
qKjniGGAoIqRpW3/4e8S9uGdzFz82gwMDFxAzCxm4ZegtuLDf+VJ1/8rZM25IqLvnM/CximCYYCic1QN
v7x2JIwPwyrJ3XNUylddE9G2TWNmZOBDl4czmJiZMSRBmFdSyYyJgUEQmxwIYxWEYXZBCUls4sgYq6CA
prWNbtG8nXKeaVPR5XiVjSxEzf0yYXy4BBMLO6eQjoOXZvrkbbazrv53Xf/2v4CSbjBMXkhBl1/CMyNZ
qWnvGy5pNQ+YONwAfjXzAOupl/47LLr333L50/96q9/8l23YdES6cO5KuYqVW+R7Tj6SnfP0v4hryjyY
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
</root> </root>

View File

@@ -134,11 +134,26 @@ Namespace DownloadObjects
Private Sub TXT_GROUPS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) 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 Select Case Sender.DefaultButton
Case ActionButton.DefaultButtons.Edit Case ActionButton.DefaultButtons.Edit
Using f As New LabelsForm(MyGroups, (From g As DownloadGroup In Settings.Groups Where Not g.IsViewFilter Select g.Name)) With {.Text = "Groups", .Icon = My.Resources.GroupByIcon_16} Using f As New LabelsForm(MyGroups, (From g As DownloadGroup In Settings.Groups Where Not g.IsViewFilter Select g.Name)) With {
.Text = "Groups (F3 to edit)",
.Icon = My.Resources.GroupByIcon_16,
.IsGroups = True
}
f.ShowDialog() f.ShowDialog()
If f.DialogResult = DialogResult.OK Then MyGroups.ListAddList(f.LabelsList, LAP.ClearBeforeAdd) : TXT_GROUPS.Text = MyGroups.ListToString If f.DialogResult = DialogResult.OK Then MyGroups.ListAddList(f.LabelsList, LAP.ClearBeforeAdd) : TXT_GROUPS.Text = MyGroups.ListToString
End Using End Using
Case ActionButton.DefaultButtons.Clear : MyGroups.Clear() Case ActionButton.DefaultButtons.Clear : MyGroups.Clear()
Case ActionButton.DefaultButtons.Info
Try
If MyGroups.Count > 0 Then
Dim i% = Settings.Groups.IndexOf(MyGroups(0))
If i >= 0 Then
Using gf As New GroupEditorForm(Settings.Groups(i)) : gf.ShowDialog() : End Using
End If
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Show group")
End Try
End Select End Select
End Sub End Sub
Private Sub ChangeEnabled() Handles OPT_DISABLED.CheckedChanged, Private Sub ChangeEnabled() Handles OPT_DISABLED.CheckedChanged,

View File

@@ -14,15 +14,19 @@ Imports PauseModes = SCrawler.DownloadObjects.AutoDownloader.PauseModes
Namespace DownloadObjects Namespace DownloadObjects
Friend Class Scheduler : Implements IEnumerable(Of AutoDownloader), IMyEnumerator(Of AutoDownloader), IDisposable Friend Class Scheduler : Implements IEnumerable(Of AutoDownloader), IMyEnumerator(Of AutoDownloader), IDisposable
Friend Const Name_Plan As String = "Plan" Friend Const Name_Plan As String = "Plan"
Friend Delegate Sub PlanChangedEventHandler(ByVal Plan As AutoDownloader)
Friend Event PauseChanged As AutoDownloader.PauseChangedEventHandler Friend Event PauseChanged As AutoDownloader.PauseChangedEventHandler
Private Sub OnPauseChanged(ByVal Value As PauseModes) Private Sub OnPauseChanged(ByVal Value As PauseModes)
RaiseEvent PauseChanged(Pause) RaiseEvent PauseChanged(Pause)
End Sub End Sub
Friend Event PlanChanged As PlanChangedEventHandler
Private Sub OnPlanChanged(ByVal Plan As AutoDownloader)
Try : RaiseEvent PlanChanged(Plan) : Catch : End Try
End Sub
Private ReadOnly Plans As List(Of AutoDownloader) Private ReadOnly Plans As List(Of AutoDownloader)
Friend Const FileNameDefault As String = "AutoDownload" Friend Const FileNameDefault As String = "AutoDownload"
Friend ReadOnly FileDefault As SFile = $"{SettingsFolderName}\{FileNameDefault}.xml" Friend ReadOnly FileDefault As SFile = $"{SettingsFolderName}\{FileNameDefault}.xml"
Friend File As SFile = Nothing Friend File As SFile = Nothing
Private ReadOnly PlanWorking As Predicate(Of AutoDownloader) = Function(Plan) Plan.Working
Private ReadOnly PlanDownloading As Predicate(Of AutoDownloader) = Function(Plan) Plan.Downloading Private ReadOnly PlanDownloading As Predicate(Of AutoDownloader) = Function(Plan) Plan.Downloading
Private ReadOnly PlansWaiter As Action(Of Predicate(Of AutoDownloader)) = Sub(ByVal Predicate As Predicate(Of AutoDownloader)) Private ReadOnly PlansWaiter As Action(Of Predicate(Of AutoDownloader)) = Sub(ByVal Predicate As Predicate(Of AutoDownloader))
While Plans.Exists(Predicate) : Thread.Sleep(200) : End While While Plans.Exists(Predicate) : Thread.Sleep(200) : End While
@@ -69,6 +73,7 @@ Namespace DownloadObjects
Friend Sub Add(ByVal Plan As AutoDownloader) Friend Sub Add(ByVal Plan As AutoDownloader)
Plan.Source = Me Plan.Source = Me
AddHandler Plan.PauseChanged, AddressOf OnPauseChanged AddHandler Plan.PauseChanged, AddressOf OnPauseChanged
AddHandler Plan.PlanChanged, AddressOf OnPlanChanged
Plans.Add(Plan) Plans.Add(Plan)
Plans.ListReindex Plans.ListReindex
Update() Update()
@@ -77,9 +82,9 @@ Namespace DownloadObjects
If Index.ValueBetween(0, Count - 1) Then If Index.ValueBetween(0, Count - 1) Then
With Plans(Index) With Plans(Index)
.Stop() .Stop()
If .Working Then If .Downloading Then
Await Task.Run(Sub() Await Task.Run(Sub()
While .Working : Thread.Sleep(510) : End While While .Downloading : Thread.Sleep(510) : End While
End Sub) End Sub)
End If End If
.Dispose() .Dispose()
@@ -103,10 +108,10 @@ Namespace DownloadObjects
End Try End Try
End Sub End Sub
Friend Function Reset(ByVal f As SFile, ByVal IsInit As Boolean) As Boolean Friend Function Reset(ByVal f As SFile, ByVal IsInit As Boolean) As Boolean
If Plans.Count > 0 Then If Count > 0 Then
If Not Plans.Exists(PlanWorking) Then If Not Plans.Exists(PlanDownloading) Then
Pause = PauseModes.Unlimited Pause = PauseModes.Unlimited
If Plans.Exists(PlanWorking) Then If Plans.Exists(PlanDownloading) Then
MsgBoxE({$"Some plans are already being worked.{vbCr}Wait for the plans to complete their work and try again.", MsgBoxE({$"Some plans are already being worked.{vbCr}Wait for the plans to complete their work and try again.",
"Change scheduler"}, vbCritical) "Change scheduler"}, vbCritical)
Pause = PauseModes.Unlimited Pause = PauseModes.Unlimited
@@ -114,6 +119,7 @@ Namespace DownloadObjects
End If End If
End If End If
[Stop]() [Stop]()
While Working : Thread.Sleep(200) : End While
If _UpdateRequired Then Update() If _UpdateRequired Then Update()
Plans.ListClearDispose(,, EDP.LogMessageValue) Plans.ListClearDispose(,, EDP.LogMessageValue)
End If End If
@@ -127,11 +133,12 @@ Namespace DownloadObjects
Plans.Add(New AutoDownloader(x)) Plans.Add(New AutoDownloader(x))
End If End If
End Using End Using
If Plans.Count > 0 Then Plans.ForEach(Sub(ByVal p As AutoDownloader) If Count > 0 Then Plans.ForEach(Sub(ByVal p As AutoDownloader)
p.Source = Me p.Source = Me
If Not IsInit Then p.Pause = PauseModes.Unlimited If Not IsInit Then p.Pause = PauseModes.Unlimited
AddHandler p.PauseChanged, AddressOf OnPauseChanged AddHandler p.PauseChanged, AddressOf OnPauseChanged
End Sub) : Plans.ListReindex AddHandler p.PlanChanged, AddressOf OnPlanChanged
End Sub) : Plans.ListReindex
End If End If
Return True Return True
End Function End Function
@@ -163,38 +170,94 @@ Namespace DownloadObjects
End Sub End Sub
#End Region #End Region
#Region "Execution" #Region "Execution"
Private AThread As Thread = Nothing
Private _StopRequested As Boolean = False
Friend ReadOnly Property Working As Boolean
Get
Return If(AThread?.IsAlive, False)
End Get
End Property
Friend Async Function Start(ByVal Init As Boolean) As Task Friend Async Function Start(ByVal Init As Boolean) As Task
Try Try
_StopRequested = False
Await Task.Run(Sub() Await Task.Run(Sub()
Dim r% = 0 Dim r% = 0
Do Do
r += 1 r += 1
Try Try
If Count > 0 Then If Count > 0 Then PlansWaiter(PlanDownloading) : Plans.ForEach(Sub(p) p.Start(Init))
If Plans.Exists(PlanDownloading) Then PlansWaiter(PlanDownloading)
For Each Plan In Plans
Plan.Start(Init)
PlansWaiter(PlanDownloading)
Thread.Sleep(1000)
Next
End If
Exit Do Exit Do
Catch io_ex As InvalidOperationException 'Collection was modified; enumeration operation may not execute Catch io_ex As InvalidOperationException 'Collection was modified; enumeration operation may not execute
End Try End Try
Loop While r < 10 Loop While r < 10
End Sub) End Sub)
If Not Working Then
AThread = New Thread(New ThreadStart(AddressOf Checker))
AThread.SetApartmentState(ApartmentState.MTA)
AThread.Start()
End If
Catch ex As Exception Catch ex As Exception
If Init Then If Init Then
ErrorsDescriber.Execute(EDP.SendToLog, ex, "Start automation") ErrorsDescriber.Execute(EDP.SendToLog, ex, "Start automation")
MainFrameObj.UpdateLogButton()
Else Else
Throw ex Throw ex
End If End If
End Try End Try
End Function End Function
Friend Sub [Stop]() Friend Sub [Stop]()
If Working Then _StopRequested = True
If Count > 0 Then Plans.ForEach(Sub(p) p.Stop()) If Count > 0 Then Plans.ForEach(Sub(p) p.Stop())
End Sub End Sub
Private Sub Checker()
Do
Try
If Count = 0 Or _StopRequested Then Exit Sub
PlansWaiter.Invoke(PlanDownloading)
Dim i% = Checker_GetNextPlanIndex()
If i >= 0 Then Checker_DownloadPlan(i)
Thread.Sleep(500)
Catch dex As ArgumentOutOfRangeException When disposedValue Or _StopRequested
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[Scheduler.Checker]")
End Try
Loop While Not _StopRequested
_StopRequested = False
End Sub
Private Sub Checker_DownloadPlan(ByVal PlanIndex As Integer)
While Downloader.Working : Thread.Sleep(200) : End While
With Plans(PlanIndex)
If .Downloading Then
PlansWaiter.Invoke(PlanDownloading)
ElseIf .DownloadReady Then
.Download()
End If
End With
End Sub
Private Function Checker_GetNextPlanIndex() As Integer
Try
Dim result% = -1
Dim l As New List(Of KeyValuePair(Of Integer, Date))
Dim d As Date?
If Count > 0 Then
For i% = 0 To Count - 1
With Plans(i)
If .DownloadReady Then
d = .NextDate
If d.HasValue Then l.Add(New KeyValuePair(Of Integer, Date)(i, d.Value))
End If
End With
Next
End If
If l.Count > 0 Then
Dim md As Date = l.Min(Function(p) p.Value)
result = l.Find(Function(p) p.Value = md).Key
l.Clear()
End If
Return result
Catch
Return -1
End Try
End Function
Friend Property Pause(Optional ByVal LimitDate As Date? = Nothing) As PauseModes Friend Property Pause(Optional ByVal LimitDate As Date? = Nothing) As PauseModes
Get Get
If Count > 0 Then Return Plans.FirstOrDefault(Function(p) p.Pause >= PauseModes.Disabled).Pause Else Return PauseModes.Disabled If Count > 0 Then Return Plans.FirstOrDefault(Function(p) p.Pause >= PauseModes.Disabled).Pause Else Return PauseModes.Disabled
@@ -218,7 +281,8 @@ Namespace DownloadObjects
If Not disposedValue Then If Not disposedValue Then
If disposing Then If disposing Then
[Stop]() [Stop]()
If Plans.Exists(PlanWorking) Then Task.WaitAll(Task.Run(Sub() PlansWaiter(PlanWorking))) If Plans.Exists(PlanDownloading) Then Task.WaitAll(Task.Run(Sub() PlansWaiter(PlanDownloading)))
While Working : Thread.Sleep(200) : End While
If _UpdateRequired Then Update() If _UpdateRequired Then Update()
Plans.ListClearDispose Plans.ListClearDispose
End If End If

View File

@@ -23,7 +23,8 @@ Namespace DownloadObjects
<System.Diagnostics.DebuggerStepThrough()> <System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent() Private Sub InitializeComponent()
Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
Me.LIST_PLANS = New System.Windows.Forms.ListBox() Me.LIST_PLANS = New System.Windows.Forms.ListView()
Me.COL_MAIN = CType(New System.Windows.Forms.ColumnHeader(), System.Windows.Forms.ColumnHeader)
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer() CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
CONTAINER_MAIN.ContentPanel.SuspendLayout() CONTAINER_MAIN.ContentPanel.SuspendLayout()
CONTAINER_MAIN.SuspendLayout() CONTAINER_MAIN.SuspendLayout()
@@ -47,12 +48,25 @@ Namespace DownloadObjects
' '
'LIST_PLANS 'LIST_PLANS
' '
Me.LIST_PLANS.Alignment = System.Windows.Forms.ListViewAlignment.Left
Me.LIST_PLANS.Columns.AddRange(New System.Windows.Forms.ColumnHeader() {Me.COL_MAIN})
Me.LIST_PLANS.Dock = System.Windows.Forms.DockStyle.Fill Me.LIST_PLANS.Dock = System.Windows.Forms.DockStyle.Fill
Me.LIST_PLANS.FormattingEnabled = True Me.LIST_PLANS.FullRowSelect = True
Me.LIST_PLANS.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None
Me.LIST_PLANS.HideSelection = False
Me.LIST_PLANS.Location = New System.Drawing.Point(0, 0) Me.LIST_PLANS.Location = New System.Drawing.Point(0, 0)
Me.LIST_PLANS.MultiSelect = False
Me.LIST_PLANS.Name = "LIST_PLANS" Me.LIST_PLANS.Name = "LIST_PLANS"
Me.LIST_PLANS.ShowGroups = False
Me.LIST_PLANS.Size = New System.Drawing.Size(414, 316) Me.LIST_PLANS.Size = New System.Drawing.Size(414, 316)
Me.LIST_PLANS.TabIndex = 0 Me.LIST_PLANS.TabIndex = 0
Me.LIST_PLANS.UseCompatibleStateImageBehavior = False
Me.LIST_PLANS.View = System.Windows.Forms.View.Details
'
'COL_MAIN
'
Me.COL_MAIN.Text = "Task"
Me.COL_MAIN.Width = 410
' '
'SchedulerEditorForm 'SchedulerEditorForm
' '
@@ -63,7 +77,6 @@ Namespace DownloadObjects
Me.KeyPreview = True Me.KeyPreview = True
Me.MinimumSize = New System.Drawing.Size(430, 380) Me.MinimumSize = New System.Drawing.Size(430, 380)
Me.Name = "SchedulerEditorForm" Me.Name = "SchedulerEditorForm"
Me.ShowIcon = True
Me.ShowInTaskbar = False Me.ShowInTaskbar = False
Me.Text = "Scheduler" Me.Text = "Scheduler"
CONTAINER_MAIN.ContentPanel.ResumeLayout(False) CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
@@ -72,6 +85,7 @@ Namespace DownloadObjects
Me.ResumeLayout(False) Me.ResumeLayout(False)
End Sub End Sub
Private WithEvents LIST_PLANS As ListBox Private WithEvents LIST_PLANS As ListView
Private WithEvents COL_MAIN As ColumnHeader
End Class End Class
End Namespace End Namespace

View File

@@ -6,8 +6,12 @@
' '
' This program is distributed in the hope that it will be useful, ' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY ' but WITHOUT ANY WARRANTY
Imports System.Threading
Imports System.ComponentModel
Imports PersonalUtilities.Forms Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Toolbars Imports PersonalUtilities.Forms.Toolbars
Imports PersonalUtilities.Forms.Controls.Base
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Tools Imports PersonalUtilities.Tools
Imports ECI = PersonalUtilities.Forms.Toolbars.EditToolbar.ControlItem Imports ECI = PersonalUtilities.Forms.Toolbars.EditToolbar.ControlItem
Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons
@@ -129,6 +133,16 @@ Namespace DownloadObjects
SetTitle() SetTitle()
.EndLoaderOperations(False) .EndLoaderOperations(False)
End With End With
SchedulerCheckerThread = New Thread(New ThreadStart(AddressOf SchedulerChecker))
SchedulerCheckerThread.SetApartmentState(ApartmentState.MTA)
SchedulerCheckerThread.Start()
Try : AddHandler Settings.Automation.PlanChanged, AddressOf Scheduler_PauseChanged : Catch : End Try
End Sub
Private _CloseRequested As Boolean = False
Private Sub SchedulerEditorForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
_CloseRequested = True
While If(SchedulerCheckerThread?.IsAlive, False) : Thread.Sleep(200) : End While
Try : RemoveHandler Settings.Automation.PlanChanged, AddressOf Scheduler_PauseChanged : Catch : End Try
End Sub End Sub
Private Sub SchedulerEditorForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown Private Sub SchedulerEditorForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If e.KeyCode = Keys.Escape Then If e.KeyCode = Keys.Escape Then
@@ -141,21 +155,48 @@ Namespace DownloadObjects
Private Sub SchedulerEditorForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed Private Sub SchedulerEditorForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
PauseArr.Dispose() PauseArr.Dispose()
End Sub End Sub
Private Sub SchedulerEditorForm_SizeChanged(sender As Object, e As EventArgs) Handles Me.SizeChanged
Try : ControlInvokeFast(LIST_PLANS, Sub()
COL_MAIN.Width = -2
LIST_PLANS.Refresh()
End Sub, EDP.None) : Catch : End Try
End Sub
#End Region #End Region
Private Property ListSelectedIndex As Integer
Get
Return If(LIST_PLANS.SelectedIndices.Count > 0, LIST_PLANS.SelectedIndices(0), -1)
End Get
Set(ByVal indx As Integer)
Try : ControlInvokeFast(LIST_PLANS, Sub()
With LIST_PLANS
.SelectedItems.Clear()
.Items(indx).Selected = True
.FocusedItem = .Items(indx)
.Refresh()
.EnsureVisible(indx)
End With
End Sub, EDP.None) : Catch : End Try
End Set
End Property
Private _RefillInProgress As Boolean = False Private _RefillInProgress As Boolean = False
Private Sub Refill() Handles MyDefs.ButtonUpdateClick Private Sub Refill() Handles MyDefs.ButtonUpdateClick
Try Try
If Not _RefillInProgress Then ControlInvokeFast(LIST_PLANS,
_RefillInProgress = True Sub()
LIST_PLANS.Items.Clear() If Not _RefillInProgress Then
If Settings.Automation.Count > 0 Then _RefillInProgress = True
LIST_PLANS.Items.AddRange(Settings.Automation.Select(Function(a) a.ToString()).Cast(Of Object).ToArray) With LIST_PLANS.Items
If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then LIST_PLANS.SelectedIndex = _LatestSelected .Clear()
Else If Settings.Automation.Count > 0 Then
_LatestSelected = -1 .AddRange(Settings.Automation.Select(Function(a) a.LVI).ToArray)
If _LatestSelected.ValueBetween(0, .Count - 1) Then ListSelectedIndex = _LatestSelected
Else
_LatestSelected = -1
End If
End With
_RefillInProgress = False
End If End If
_RefillInProgress = False End Sub)
End If
Catch ex As Exception Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[DownloadObjects.SchedulerEditorForm.Refill]") ErrorsDescriber.Execute(EDP.SendToLog, ex, "[DownloadObjects.SchedulerEditorForm.Refill]")
End Try End Try
@@ -194,7 +235,7 @@ Namespace DownloadObjects
Private Sub Edit() Handles MyDefs.ButtonEditClick Private Sub Edit() Handles MyDefs.ButtonEditClick
If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then
Using f As New AutoDownloaderEditorForm(Settings.Automation(_LatestSelected)) : f.ShowDialog() : End Using Using f As New AutoDownloaderEditorForm(Settings.Automation(_LatestSelected)) : f.ShowDialog() : End Using
Refill() LIST_PLANS_Refresh(_LatestSelected)
Else Else
MsgBoxE("You have not selected a plan to edit.", vbExclamation) MsgBoxE("You have not selected a plan to edit.", vbExclamation)
End If End If
@@ -222,19 +263,83 @@ Namespace DownloadObjects
#End Region #End Region
#Region "List handlers" #Region "List handlers"
Private _LatestSelected As Integer = -1 Private _LatestSelected As Integer = -1
Private _LatestSelectedChangeEnabled As Boolean = True
Private Sub LIST_PLANS_SelectedIndexChanged(sender As Object, e As EventArgs) Handles LIST_PLANS.SelectedIndexChanged Private Sub LIST_PLANS_SelectedIndexChanged(sender As Object, e As EventArgs) Handles LIST_PLANS.SelectedIndexChanged
_LatestSelected = LIST_PLANS.SelectedIndex If _LatestSelectedChangeEnabled Then
PauseArr.PlanIndex = _LatestSelected _LatestSelected = ListSelectedIndex
PauseArr.UpdatePauseButtons(False) PauseArr.PlanIndex = _LatestSelected
PauseArr.UpdatePauseButtons(False)
End If
End Sub End Sub
Private Sub LIST_PLANS_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles LIST_PLANS.MouseDoubleClick Private Sub LIST_PLANS_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles LIST_PLANS.MouseDoubleClick
Edit() Edit()
End Sub End Sub
Private Sub LIST_PLANS_Refresh(Optional ByVal PlanIndex As Integer = -1)
_LatestSelectedChangeEnabled = False
Try
ControlInvokeFast(LIST_PLANS,
Sub()
Dim indx% = If(PlanIndex >= 0, PlanIndex, ListSelectedIndex)
If indx = -1 And PlanIndex = -1 Then indx = _LatestSelected
If indx.ValueBetween(0, Settings.Automation.Count - 1) Then _
LIST_PLANS.Items(indx) = Settings.Automation(indx).LVI
If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then ListSelectedIndex = _LatestSelected
End Sub, EDP.None)
Catch
Finally
_LatestSelectedChangeEnabled = True
End Try
End Sub
Private Sub Scheduler_PauseChanged(ByVal Plan As AutoDownloader)
LIST_PLANS_Refresh(Plan.Index)
End Sub
Private SchedulerCheckerThread As Thread
Private Sub SchedulerChecker()
Try
While Not _CloseRequested
Try
With Settings.Automation
If .Count > 0 Then
For i% = 0 To .Count - 1
If .Item(i).LVIStateChanged Then LIST_PLANS_Refresh(i)
If _CloseRequested Then Exit Sub
Thread.Sleep(200)
Next
Else
If _CloseRequested Then Exit Sub
Thread.Sleep(200)
End If
End With
Catch
End Try
End While
Catch
End Try
End Sub
#End Region #End Region
#Region "Settings, Start, Skip, Pause" #Region "Settings, Start, Skip, Pause"
Private Function GetSchedulerFiles() As List(Of SFile) Private Function GetSchedulerFiles() As List(Of SFile)
Return SFile.GetFiles(SettingsFolderName.CSFileP, $"{Scheduler.FileNameDefault}*.xml",, EDP.ReturnValue) Return SFile.GetFiles(SettingsFolderName.CSFileP, $"{Scheduler.FileNameDefault}*.xml",, EDP.ReturnValue)
End Function End Function
Private Class SchedulerList : Inherits SimpleListForm(Of String)
Friend Sub New(ByVal Source As IEnumerable(Of String), Optional ByRef DesignXML As EContainer = Nothing)
MyBase.New(Source, DesignXML)
End Sub
Protected Overrides Sub MyForm_Load(sender As Object, e As EventArgs)
MyBase.MyForm_Load(sender, e)
CMB_DATA.Button(ADB.Add).ToolTipText = "Create a new scheduler"
CMB_DATA.Button(ADB.SaveAs).ToolTipText = "Clone an existing scheduler and save it as a new one"
CMB_DATA.Button(ADB.Delete).ToolTipText = "Delete the selected scheduler"
CMB_DATA.Buttons.UpdateButtonsPositions()
End Sub
Protected Overrides Sub CMB_DATA_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs)
If e.DefaultButton = ADB.SaveAs Then
AddNewItem(e, e.Key, e.KeyEventArgs)
Else
MyBase.CMB_DATA_ActionOnButtonClick(Sender, e)
End If
End Sub
End Class
Private Sub BTT_SETTINGS_Click(sender As Object, e As EventArgs) Handles BTT_SETTINGS.Click Private Sub BTT_SETTINGS_Click(sender As Object, e As EventArgs) Handles BTT_SETTINGS.Click
Const msgTitle$ = "Change scheduler" Const msgTitle$ = "Change scheduler"
Try Try
@@ -244,7 +349,7 @@ Namespace DownloadObjects
If .ListExists Then .ForEach(Sub(ff) l.Add(ff, ff.Name.Replace(Scheduler.FileNameDefault, String.Empty).StringTrimStart("_").IfNullOrEmpty(defName))) If .ListExists Then .ForEach(Sub(ff) l.Add(ff, ff.Name.Replace(Scheduler.FileNameDefault, String.Empty).StringTrimStart("_").IfNullOrEmpty(defName)))
End With End With
If l.Count > 0 Then If l.Count > 0 Then
Using chooser As New SimpleListForm(Of String)(l.Values.Cast(Of String), Settings.Design) With { Using chooser As New SchedulerList(l.Values.Cast(Of String), Settings.Design) With {
.DesignXMLNodeName = "SchedulerChooserForm", .DesignXMLNodeName = "SchedulerChooserForm",
.Icon = ImageRenderer.GetIcon(My.Resources.ScriptPic_32, EDP.ReturnValue), .Icon = ImageRenderer.GetIcon(My.Resources.ScriptPic_32, EDP.ReturnValue),
.FormText = "Schedulers", .FormText = "Schedulers",
@@ -256,17 +361,56 @@ Namespace DownloadObjects
Dim f As SFile Dim f As SFile
Dim selectedName$ Dim selectedName$
Dim addedObj$ = String.Empty Dim addedObj$ = String.Empty
Dim addedObjIsClone As Boolean = False
Dim createSchedulerPath As Func(Of String, SFile) = Function(n) $"{SettingsFolderName}\{Scheduler.FileNameDefault}_{n.StringRemoveWinForbiddenSymbols}.xml"
.ClearButtons() .ClearButtons()
.Buttons = {ADB.Add, ADB.Delete} .Buttons = {ADB.Add, ADB.SaveAs, ADB.Delete}
AddHandler .AddClick, Sub(ByVal obj As Object, ByVal args As SimpleListFormEventArgs) AddHandler .AddClick, Sub(ByVal obj As Object, ByVal args As SimpleListFormEventArgs)
If addedObj.IsEmptyString Then If addedObj.IsEmptyString Then
addedObj = InputBoxE("Enter a new scheduler name:", msgTitle) addedObj = InputBoxE("Enter a new scheduler name:", msgTitle)
args.Result = Not addedObj.IsEmptyString args.Result = Not addedObj.IsEmptyString
If args.Result Then args.Item = addedObj If args.Result Then
If l.Values.Count > 0 AndAlso l.Values.ListIndexOf(Function(n) n.StringToLower = addedObj.StringToLower) >= 0 Then
args.Result = False
MsgBoxE({$"A scheduler named '{addedObj}' already exists", msgTitle}, vbCritical)
Else
args.Item = addedObj
addedObjIsClone = Not args.ButtonEventArgs Is Nothing AndAlso
TypeOf args.ButtonEventArgs Is ActionButtonEventArgs AndAlso
DirectCast(args.ButtonEventArgs, ActionButtonEventArgs).DefaultButton = ADB.SaveAs
If addedObjIsClone Then
Dim cloneF As SFile = createSchedulerPath.Invoke(addedObj)
If Not cloneF.Exists And Settings.Automation.File.Exists Then
Using x As New XmlFile(Settings.Automation.File, Protector.Modes.All, False) With {.AllowSameNames = True, .XmlReadOnly = True}
x.LoadData()
x.Save(cloneF, EDP.SendToLog)
End Using
End If
End If
End If
End If
Else Else
MsgBoxE({"You can only create one scheduler at a time", "Create a new scheduler"}, vbCritical) MsgBoxE({"You can only create one scheduler at a time", "Create a new scheduler"}, vbCritical)
End If End If
End Sub End Sub
AddHandler .DeleteClick, Sub(ByVal obj As Object, ByVal args As SimpleListFormEventArgs)
Dim n$ = AConvert(Of String)(args.Item, String.Empty)
If Not n.IsEmptyString Then
If MsgBoxE({$"Are you sure you want to delete the '{n}' scheduler?", msgTitle}, vbExclamation,,,
{"Process", "Cancel"}) = 0 Then
Dim delF As SFile = createSchedulerPath.Invoke(n)
If delF.Exists AndAlso delF.Delete Then
args.Result = True
If l.ContainsKey(delF) Then
l.Remove(delF)
Else
Dim delIndx% = l.ListIndexOf(Function(dd) dd.Value = n)
If delIndx >= 0 Then l.Remove(l.Keys(delIndx))
End If
End If
End If
End If
End Sub
If Settings.Automation.File.Name = Scheduler.FileNameDefault Then If Settings.Automation.File.Name = Scheduler.FileNameDefault Then
.DataSelectedIndexes.Add(0) .DataSelectedIndexes.Add(0)
Else Else
@@ -279,7 +423,7 @@ Namespace DownloadObjects
If selectedName = defName Then If selectedName = defName Then
f = Settings.Automation.FileDefault f = Settings.Automation.FileDefault
Else Else
f = $"{SettingsFolderName}\{Scheduler.FileNameDefault}_{selectedName.StringRemoveWinForbiddenSymbols}.xml" f = createSchedulerPath.Invoke(selectedName)
End If End If
If Not Settings.Automation.File = f AndAlso Settings.Automation.Reset(f, False) Then If Not Settings.Automation.File = f AndAlso Settings.Automation.Reset(f, False) Then
Settings.Automation.File = f Settings.Automation.File = f
@@ -312,13 +456,13 @@ Namespace DownloadObjects
Private Sub BTT_START_Click(sender As Object, e As EventArgs) Handles BTT_START.Click Private Sub BTT_START_Click(sender As Object, e As EventArgs) Handles BTT_START.Click
If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then
With Settings.Automation(_LatestSelected) : .Start(.IsNewPlan) : End With With Settings.Automation(_LatestSelected) : .Start(.IsNewPlan) : End With
Refill() LIST_PLANS_Refresh(_LatestSelected)
End If End If
End Sub End Sub
Private Sub BTT_START_FORCE_Click(sender As Object, e As EventArgs) Handles BTT_START_FORCE.Click Private Sub BTT_START_FORCE_Click(sender As Object, e As EventArgs) Handles BTT_START_FORCE.Click
If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then
With Settings.Automation(_LatestSelected) With Settings.Automation(_LatestSelected)
If .Working Or .IsManual Then .ForceStart() : Refill() If .Working Or .IsManual Then .ForceStart() : LIST_PLANS_Refresh(_LatestSelected)
End With End With
End If End If
End Sub End Sub
@@ -328,10 +472,10 @@ Namespace DownloadObjects
Select Case mode Select Case mode
Case String.Empty Case String.Empty
Settings.Automation(_LatestSelected).Skip() Settings.Automation(_LatestSelected).Skip()
Refill() LIST_PLANS_Refresh(_LatestSelected)
Case "m" Case "m"
Dim mins% = AConvert(Of Integer)(InputBoxE("Enter a number of minutes you want to delay:", Sender.Text, 60), -1) Dim mins% = AConvert(Of Integer)(InputBoxE("Enter a number of minutes you want to delay:", Sender.Text, 60), -1)
If mins > 0 Then Settings.Automation(_LatestSelected).Skip(mins) : Refill() If mins > 0 Then Settings.Automation(_LatestSelected).Skip(mins) : LIST_PLANS_Refresh(_LatestSelected)
Case "d" Case "d"
Dim d As Date? = Nothing Dim d As Date? = Nothing
Using f As New DateTimeSelectionForm(DateTimeSelectionForm.Modes.Date + Using f As New DateTimeSelectionForm(DateTimeSelectionForm.Modes.Date +
@@ -342,16 +486,13 @@ Namespace DownloadObjects
f.ShowDialog() f.ShowDialog()
If f.DialogResult = DialogResult.OK Then d = f.MyDateStart If f.DialogResult = DialogResult.OK Then d = f.MyDateStart
End Using End Using
If d.HasValue Then Settings.Automation(_LatestSelected).Skip(d.Value) : Refill() If d.HasValue Then Settings.Automation(_LatestSelected).Skip(d.Value) : LIST_PLANS_Refresh(_LatestSelected)
Case "r" Case "r"
Settings.Automation(_LatestSelected).SkipReset() Settings.Automation(_LatestSelected).SkipReset()
Refill() LIST_PLANS_Refresh(_LatestSelected)
End Select End Select
End If End If
End Sub End Sub
Private Sub PauseArr_Updating() Handles PauseArr.Updating
Refill()
End Sub
#End Region #End Region
#Region "Move" #Region "Move"
Private Sub BTT_MOVE_UP_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_MOVE_UP.Click, BTT_MOVE_DOWN.Click Private Sub BTT_MOVE_UP_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_MOVE_UP.Click, BTT_MOVE_DOWN.Click

View File

@@ -35,6 +35,7 @@ Namespace DownloadObjects
Dim MENU_LOAD_SEP_7 As System.Windows.Forms.ToolStripSeparator Dim MENU_LOAD_SEP_7 As System.Windows.Forms.ToolStripSeparator
Dim MENU_LOAD_SEP_0 As System.Windows.Forms.ToolStripSeparator Dim MENU_LOAD_SEP_0 As System.Windows.Forms.ToolStripSeparator
Dim MENU_LOAD_SEP_8 As System.Windows.Forms.ToolStripSeparator Dim MENU_LOAD_SEP_8 As System.Windows.Forms.ToolStripSeparator
Dim MENU_LOAD_SEP_9 As System.Windows.Forms.ToolStripSeparator
Me.OPT_DEFAULT = New System.Windows.Forms.ToolStripMenuItem() Me.OPT_DEFAULT = New System.Windows.Forms.ToolStripMenuItem()
Me.OPT_SUBSCRIPTIONS = New System.Windows.Forms.ToolStripMenuItem() Me.OPT_SUBSCRIPTIONS = New System.Windows.Forms.ToolStripMenuItem()
Me.ToolbarTOP = New System.Windows.Forms.ToolStrip() Me.ToolbarTOP = New System.Windows.Forms.ToolStrip()
@@ -57,19 +58,23 @@ Namespace DownloadObjects
Me.BTT_FEED_DELETE_SPEC = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_FEED_DELETE_SPEC = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_DELETE_DAILY_LIST = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_FEED_DELETE_DAILY_LIST = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_DELETE_DAILY_DATE = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_FEED_DELETE_DAILY_DATE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CURR_SESSION_SET = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_MERGE_SESSIONS = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_MERGE_SESSIONS = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CLEAR_DAILY = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_CLEAR_DAILY = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_MERGE_FEEDS = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_MERGE_FEEDS = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CHECK_ALL = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_CHECK_ALL = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CHECK_NONE = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_CHECK_NONE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_VIEW_SAVE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_VIEW_LOAD = New System.Windows.Forms.ToolStripMenuItem()
Me.SEP_0 = New System.Windows.Forms.ToolStripSeparator() Me.SEP_0 = New System.Windows.Forms.ToolStripSeparator()
Me.MENU_DOWN = New System.Windows.Forms.ToolStripDropDownButton() Me.MENU_DOWN = New System.Windows.Forms.ToolStripDropDownButton()
Me.BTT_DOWN_ALL = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_DOWN_ALL = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_DOWN_SELECTED = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_DOWN_SELECTED = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_REFRESH = New System.Windows.Forms.ToolStripButton() Me.BTT_REFRESH = New System.Windows.Forms.ToolStripButton()
Me.TP_DATA = New System.Windows.Forms.TableLayoutPanel() Me.TP_DATA = New System.Windows.Forms.TableLayoutPanel()
Me.BTT_VIEW_SAVE = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_COPY_SPEC_TO = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_VIEW_LOAD = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_MOVE_SPEC_TO = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_RESET_DAILY = New System.Windows.Forms.ToolStripMenuItem()
SEP_1 = New System.Windows.Forms.ToolStripSeparator() SEP_1 = New System.Windows.Forms.ToolStripSeparator()
SEP_2 = New System.Windows.Forms.ToolStripSeparator() SEP_2 = New System.Windows.Forms.ToolStripSeparator()
MENU_VIEW = New System.Windows.Forms.ToolStripDropDownButton() MENU_VIEW = New System.Windows.Forms.ToolStripDropDownButton()
@@ -82,6 +87,7 @@ Namespace DownloadObjects
MENU_LOAD_SEP_7 = New System.Windows.Forms.ToolStripSeparator() MENU_LOAD_SEP_7 = New System.Windows.Forms.ToolStripSeparator()
MENU_LOAD_SEP_0 = New System.Windows.Forms.ToolStripSeparator() MENU_LOAD_SEP_0 = New System.Windows.Forms.ToolStripSeparator()
MENU_LOAD_SEP_8 = New System.Windows.Forms.ToolStripSeparator() MENU_LOAD_SEP_8 = New System.Windows.Forms.ToolStripSeparator()
MENU_LOAD_SEP_9 = New System.Windows.Forms.ToolStripSeparator()
Me.ToolbarTOP.SuspendLayout() Me.ToolbarTOP.SuspendLayout()
Me.SuspendLayout() Me.SuspendLayout()
' '
@@ -157,6 +163,11 @@ Namespace DownloadObjects
MENU_LOAD_SEP_0.Name = "MENU_LOAD_SEP_0" MENU_LOAD_SEP_0.Name = "MENU_LOAD_SEP_0"
MENU_LOAD_SEP_0.Size = New System.Drawing.Size(349, 6) MENU_LOAD_SEP_0.Size = New System.Drawing.Size(349, 6)
' '
'MENU_LOAD_SEP_8
'
MENU_LOAD_SEP_8.Name = "MENU_LOAD_SEP_8"
MENU_LOAD_SEP_8.Size = New System.Drawing.Size(349, 6)
'
'ToolbarTOP 'ToolbarTOP
' '
Me.ToolbarTOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden Me.ToolbarTOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden
@@ -170,7 +181,7 @@ Namespace DownloadObjects
' '
Me.MENU_LOAD_SESSION.AutoToolTip = False Me.MENU_LOAD_SESSION.AutoToolTip = False
Me.MENU_LOAD_SESSION.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image Me.MENU_LOAD_SESSION.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image
Me.MENU_LOAD_SESSION.DropDownItems.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_LOAD_SESSION_CURRENT, Me.BTT_LOAD_SESSION_LAST, Me.BTT_LOAD_SESSION_CHOOSE, MENU_LOAD_SEP_0, Me.BTT_COPY_TO, Me.BTT_MOVE_TO, MENU_LOAD_SEP_1, Me.BTT_LOAD_FAV, Me.BTT_LOAD_SPEC, MENU_LOAD_SEP_2, Me.BTT_FEED_ADD_FAV, Me.BTT_FEED_ADD_FAV_REMOVE, Me.BTT_FEED_REMOVE_FAV, MENU_LOAD_SEP_3, Me.BTT_FEED_ADD_SPEC, Me.BTT_FEED_ADD_SPEC_REMOVE, Me.BTT_FEED_REMOVE_SPEC, MENU_LOAD_SEP_4, Me.BTT_FEED_CLEAR_FAV, Me.BTT_FEED_CLEAR_SPEC, Me.BTT_FEED_DELETE_SPEC, Me.BTT_FEED_DELETE_DAILY_LIST, Me.BTT_FEED_DELETE_DAILY_DATE, MENU_LOAD_SEP_5, Me.BTT_MERGE_SESSIONS, Me.BTT_CLEAR_DAILY, MENU_LOAD_SEP_6, Me.BTT_MERGE_FEEDS, MENU_LOAD_SEP_7, Me.BTT_CHECK_ALL, Me.BTT_CHECK_NONE, MENU_LOAD_SEP_8, Me.BTT_VIEW_SAVE, Me.BTT_VIEW_LOAD}) Me.MENU_LOAD_SESSION.DropDownItems.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_LOAD_SESSION_CURRENT, Me.BTT_LOAD_SESSION_LAST, Me.BTT_LOAD_SESSION_CHOOSE, MENU_LOAD_SEP_0, Me.BTT_COPY_TO, Me.BTT_MOVE_TO, MENU_LOAD_SEP_1, Me.BTT_COPY_SPEC_TO, Me.BTT_MOVE_SPEC_TO, MENU_LOAD_SEP_2, Me.BTT_LOAD_FAV, Me.BTT_LOAD_SPEC, MENU_LOAD_SEP_3, Me.BTT_FEED_ADD_FAV, Me.BTT_FEED_ADD_FAV_REMOVE, Me.BTT_FEED_REMOVE_FAV, MENU_LOAD_SEP_4, Me.BTT_FEED_ADD_SPEC, Me.BTT_FEED_ADD_SPEC_REMOVE, Me.BTT_FEED_REMOVE_SPEC, MENU_LOAD_SEP_5, Me.BTT_FEED_CLEAR_FAV, Me.BTT_FEED_CLEAR_SPEC, Me.BTT_FEED_DELETE_SPEC, Me.BTT_FEED_DELETE_DAILY_LIST, Me.BTT_FEED_DELETE_DAILY_DATE, MENU_LOAD_SEP_6, Me.BTT_CURR_SESSION_SET, Me.BTT_MERGE_SESSIONS, Me.BTT_CLEAR_DAILY, Me.BTT_RESET_DAILY, MENU_LOAD_SEP_7, Me.BTT_MERGE_FEEDS, MENU_LOAD_SEP_8, Me.BTT_CHECK_ALL, Me.BTT_CHECK_NONE, MENU_LOAD_SEP_9, Me.BTT_VIEW_SAVE, Me.BTT_VIEW_LOAD})
Me.MENU_LOAD_SESSION.Image = Global.SCrawler.My.Resources.Resources.ArrowDownPic_Blue_24 Me.MENU_LOAD_SESSION.Image = Global.SCrawler.My.Resources.Resources.ArrowDownPic_Blue_24
Me.MENU_LOAD_SESSION.ImageTransparentColor = System.Drawing.Color.Magenta Me.MENU_LOAD_SESSION.ImageTransparentColor = System.Drawing.Color.Magenta
Me.MENU_LOAD_SESSION.Name = "MENU_LOAD_SESSION" Me.MENU_LOAD_SESSION.Name = "MENU_LOAD_SESSION"
@@ -303,6 +314,15 @@ Namespace DownloadObjects
Me.BTT_FEED_DELETE_DAILY_DATE.Size = New System.Drawing.Size(352, 22) Me.BTT_FEED_DELETE_DAILY_DATE.Size = New System.Drawing.Size(352, 22)
Me.BTT_FEED_DELETE_DAILY_DATE.Text = "Delete daily feed (by date)" Me.BTT_FEED_DELETE_DAILY_DATE.Text = "Delete daily feed (by date)"
' '
'BTT_CURR_SESSION_SET
'
Me.BTT_CURR_SESSION_SET.AutoToolTip = True
Me.BTT_CURR_SESSION_SET.Image = Global.SCrawler.My.Resources.Resources.ArrowDownPic_Blue_24
Me.BTT_CURR_SESSION_SET.Name = "BTT_CURR_SESSION_SET"
Me.BTT_CURR_SESSION_SET.Size = New System.Drawing.Size(352, 22)
Me.BTT_CURR_SESSION_SET.Text = "Set current session..."
Me.BTT_CURR_SESSION_SET.ToolTipText = "Select one of the download sessions and set it as the current session"
'
'BTT_MERGE_SESSIONS 'BTT_MERGE_SESSIONS
' '
Me.BTT_MERGE_SESSIONS.AutoToolTip = True Me.BTT_MERGE_SESSIONS.AutoToolTip = True
@@ -343,6 +363,20 @@ Namespace DownloadObjects
Me.BTT_CHECK_NONE.Size = New System.Drawing.Size(352, 22) Me.BTT_CHECK_NONE.Size = New System.Drawing.Size(352, 22)
Me.BTT_CHECK_NONE.Text = "Select none" Me.BTT_CHECK_NONE.Text = "Select none"
' '
'BTT_VIEW_SAVE
'
Me.BTT_VIEW_SAVE.Name = "BTT_VIEW_SAVE"
Me.BTT_VIEW_SAVE.Size = New System.Drawing.Size(352, 22)
Me.BTT_VIEW_SAVE.Text = "Save current view"
'
'BTT_VIEW_LOAD
'
Me.BTT_VIEW_LOAD.AutoToolTip = True
Me.BTT_VIEW_LOAD.Name = "BTT_VIEW_LOAD"
Me.BTT_VIEW_LOAD.Size = New System.Drawing.Size(352, 22)
Me.BTT_VIEW_LOAD.Text = "Load view (from saved)"
Me.BTT_VIEW_LOAD.ToolTipText = "Load one of your previously saved views"
'
'SEP_0 'SEP_0
' '
Me.SEP_0.Name = "SEP_0" Me.SEP_0.Name = "SEP_0"
@@ -409,24 +443,37 @@ Namespace DownloadObjects
Me.TP_DATA.Size = New System.Drawing.Size(484, 436) Me.TP_DATA.Size = New System.Drawing.Size(484, 436)
Me.TP_DATA.TabIndex = 1 Me.TP_DATA.TabIndex = 1
' '
'MENU_LOAD_SEP_8 'MENU_LOAD_SEP_9
' '
MENU_LOAD_SEP_8.Name = "MENU_LOAD_SEP_8" MENU_LOAD_SEP_9.Name = "MENU_LOAD_SEP_9"
MENU_LOAD_SEP_8.Size = New System.Drawing.Size(349, 6) MENU_LOAD_SEP_9.Size = New System.Drawing.Size(349, 6)
' '
'BTT_VIEW_SAVE 'BTT_COPY_SPEC_TO
' '
Me.BTT_VIEW_SAVE.Name = "BTT_VIEW_SAVE" Me.BTT_COPY_SPEC_TO.AutoToolTip = True
Me.BTT_VIEW_SAVE.Size = New System.Drawing.Size(352, 22) Me.BTT_COPY_SPEC_TO.Image = Global.SCrawler.My.Resources.Resources.PastePic_32
Me.BTT_VIEW_SAVE.Text = "Save current view" Me.BTT_COPY_SPEC_TO.Name = "BTT_COPY_SPEC_TO"
Me.BTT_COPY_SPEC_TO.Size = New System.Drawing.Size(352, 22)
Me.BTT_COPY_SPEC_TO.Text = "Copy feed/session files to..."
Me.BTT_COPY_SPEC_TO.ToolTipText = "Copy all the files of the loaded feed/session to..."
' '
'BTT_VIEW_LOAD 'BTT_MOVE_SPEC_TO
' '
Me.BTT_VIEW_LOAD.AutoToolTip = True Me.BTT_MOVE_SPEC_TO.AutoToolTip = True
Me.BTT_VIEW_LOAD.Name = "BTT_VIEW_LOAD" Me.BTT_MOVE_SPEC_TO.Image = Global.SCrawler.My.Resources.Resources.CutPic_48
Me.BTT_VIEW_LOAD.Size = New System.Drawing.Size(352, 22) Me.BTT_MOVE_SPEC_TO.Name = "BTT_MOVE_SPEC_TO"
Me.BTT_VIEW_LOAD.Text = "Load view (from saved)" Me.BTT_MOVE_SPEC_TO.Size = New System.Drawing.Size(352, 22)
Me.BTT_VIEW_LOAD.ToolTipText = "Load one of your previously saved views" Me.BTT_MOVE_SPEC_TO.Text = "Move feed/session files to..."
Me.BTT_MOVE_SPEC_TO.ToolTipText = "Move all the files of the loaded feed/session to..."
'
'BTT_RESET_DAILY
'
Me.BTT_RESET_DAILY.AutoToolTip = True
Me.BTT_RESET_DAILY.Image = Global.SCrawler.My.Resources.Resources.RefreshPic_24
Me.BTT_RESET_DAILY.Name = "BTT_RESET_DAILY"
Me.BTT_RESET_DAILY.Size = New System.Drawing.Size(352, 22)
Me.BTT_RESET_DAILY.Text = "Reset current session"
Me.BTT_RESET_DAILY.ToolTipText = "A new file will be created for the current session"
' '
'DownloadFeedForm 'DownloadFeedForm
' '
@@ -483,5 +530,9 @@ Namespace DownloadObjects
Private WithEvents BTT_MOVE_TO As ToolStripMenuItem Private WithEvents BTT_MOVE_TO As ToolStripMenuItem
Private WithEvents BTT_VIEW_SAVE As ToolStripMenuItem Private WithEvents BTT_VIEW_SAVE As ToolStripMenuItem
Private WithEvents BTT_VIEW_LOAD As ToolStripMenuItem Private WithEvents BTT_VIEW_LOAD As ToolStripMenuItem
Private WithEvents BTT_CURR_SESSION_SET As ToolStripMenuItem
Private WithEvents BTT_COPY_SPEC_TO As ToolStripMenuItem
Private WithEvents BTT_MOVE_SPEC_TO As ToolStripMenuItem
Private WithEvents BTT_RESET_DAILY As ToolStripMenuItem
End Class End Class
End Namespace End Namespace

View File

@@ -159,10 +159,13 @@
<metadata name="MENU_LOAD_SEP_0.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="MENU_LOAD_SEP_0.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<metadata name="ToolbarTOP.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="MENU_LOAD_SEP_8.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="MENU_LOAD_SEP_8.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<metadata name="ToolbarTOP.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="MENU_LOAD_SEP_9.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
</root> </root>

View File

@@ -173,6 +173,7 @@ Namespace DownloadObjects
MENU_DOWN.Visible = OPT_SUBSCRIPTIONS.Checked MENU_DOWN.Visible = OPT_SUBSCRIPTIONS.Checked
UpdateSettings() UpdateSettings()
FeedChangeMode(FeedModes.Current) FeedChangeMode(FeedModes.Current)
Downloader.FilesLoadLastSession()
RefillList(True, False) RefillList(True, False)
.EndLoaderOperations(False) .EndLoaderOperations(False)
End With End With
@@ -275,7 +276,6 @@ Namespace DownloadObjects
End With End With
Catch ex As Exception Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "Feed removed") ErrorsDescriber.Execute(EDP.SendToLog, ex, "Feed removed")
MainFrameObj.UpdateLogButton()
End Try End Try
End Sub End Sub
Private Sub Feed_SPEC_LOAD(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs) Private Sub Feed_SPEC_LOAD(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs)
@@ -439,7 +439,9 @@ Namespace DownloadObjects
End Sub End Sub
Private Sub SessionChooser(ByVal GetLast As Boolean, Optional ByVal GetFilesOnly As Boolean = False, Private Sub SessionChooser(ByVal GetLast As Boolean, Optional ByVal GetFilesOnly As Boolean = False,
Optional ByRef ResultFilesList As List(Of SFile) = Nothing, Optional ByRef ResultFilesList As List(Of SFile) = Nothing,
Optional ByVal SelectedMode As FeedModes = -1) Optional ByVal SelectedMode As FeedModes = -1,
Optional ByVal GetSessionFile As Boolean = False,
Optional ByRef SessionFile As SFile = Nothing)
Try Try
LoadedSessionName = String.Empty LoadedSessionName = String.Empty
Downloader.ClearSessions() Downloader.ClearSessions()
@@ -474,6 +476,12 @@ Namespace DownloadObjects
If fList.ListExists Then If fList.ListExists Then
If GetFilesOnly Then If GetFilesOnly Then
ResultFilesList.AddRange(fList) ResultFilesList.AddRange(fList)
ElseIf GetSessionFile Then
If fList.Count > 1 Then
MsgBoxE({"You must select one session file", "Get session file"}, vbExclamation)
Else
SessionFile = fList(0)
End If
Else Else
DataList.Clear() DataList.Clear()
If SelectedMode >= 0 Then If SelectedMode >= 0 Then
@@ -532,14 +540,19 @@ Namespace DownloadObjects
Private Sub BTT_COPY_MOVE_TO_Click(sender As Object, e As EventArgs) Handles BTT_COPY_TO.Click, BTT_MOVE_TO.Click Private Sub BTT_COPY_MOVE_TO_Click(sender As Object, e As EventArgs) Handles BTT_COPY_TO.Click, BTT_MOVE_TO.Click
MoveCopyFiles(True, sender, Nothing, Nothing) MoveCopyFiles(True, sender, Nothing, Nothing)
End Sub End Sub
Private Function MoveCopyFiles(ByVal IsInternal As Boolean, ByVal Sender As Object, ByVal MCTOptions As FeedMoveCopyTo, ByVal FeedMediaData As FeedMedia) As Boolean Private Sub BTT_COPY_MOVE_SPEC_TO_Click(sender As Object, e As EventArgs) Handles BTT_COPY_SPEC_TO.Click, BTT_MOVE_SPEC_TO.Click
MoveCopyFiles(True, sender, Nothing, Nothing, False)
End Sub
Private Function MoveCopyFiles(ByVal IsInternal As Boolean, ByVal Sender As Object, ByVal MCTOptions As FeedMoveCopyTo,
ByVal FeedMediaData As FeedMedia, Optional ByVal GetChecked As Boolean = True) As Boolean
Const MsgTitle$ = "Copy/Move checked files" Const MsgTitle$ = "Copy/Move checked files"
Try Try
Dim isCopy As Boolean = Not Sender Is Nothing AndAlso Sender Is BTT_COPY_TO Dim isCopy As Boolean = Not Sender Is Nothing AndAlso (Sender Is BTT_COPY_TO OrElse Sender Is BTT_COPY_SPEC_TO)
Dim moveOptions As FeedMoveCopyTo = Nothing Dim moveOptions As FeedMoveCopyTo = Nothing
Dim ff As SFile = Nothing, df As SFile Dim ff As SFile = Nothing, df As SFile
Dim data As IEnumerable(Of UserMediaD) = Nothing Dim data As IEnumerable(Of UserMediaD) = Nothing
Dim dd As UserMediaD Dim dd As UserMediaD
Dim __user As UserInfo
Dim data_files As IEnumerable(Of SFile) = Nothing Dim data_files As IEnumerable(Of SFile) = Nothing
Dim new_files As New List(Of SFile) Dim new_files As New List(Of SFile)
Dim mm As UserMediaD Dim mm As UserMediaD
@@ -558,7 +571,12 @@ Namespace DownloadObjects
Dim result As Boolean = False Dim result As Boolean = False
If FeedMediaData Is Nothing Then If FeedMediaData Is Nothing Then
data = GetCheckedMedia() If GetChecked Then
data = GetCheckedMedia()
ElseIf DataList.Count > 0 Then
data = DataList.Where(Function(__dd) Not If(__dd.User?.IsSubscription, __dd.UserInfo.IsSubscription) AndAlso __dd.Data.File.Exists)
End If
With data With data
If .ListExists Then data_files = .Select(Function(m) m.Data.File) If .ListExists Then data_files = .Select(Function(m) m.Data.File)
End With End With
@@ -579,7 +597,6 @@ Namespace DownloadObjects
With moveOptions With moveOptions
If Not .Destination.IsEmptyString And .ReplaceUserProfile And .ReplaceUserProfile_CreateIfNull And .ReplaceUserProfile_Profile Is Nothing Then If Not .Destination.IsEmptyString And .ReplaceUserProfile And .ReplaceUserProfile_CreateIfNull And .ReplaceUserProfile_Profile Is Nothing Then
Dim existingPathInstances As IEnumerable(Of String) = Nothing Dim existingPathInstances As IEnumerable(Of String) = Nothing
Dim __user As UserInfo
Dim __host As Plugin.Hosts.SettingsHost = Settings(API.PathPlugin.PluginKey).Default Dim __host As Plugin.Hosts.SettingsHost = Settings(API.PathPlugin.PluginKey).Default
Dim __userName$ = .Destination.Segments.LastOrDefault Dim __userName$ = .Destination.Segments.LastOrDefault
If Settings.UsersList.Count > 0 Then _ If Settings.UsersList.Count > 0 Then _
@@ -651,9 +668,11 @@ Namespace DownloadObjects
indx = Downloader.Files.FindIndex(finder) indx = Downloader.Files.FindIndex(finder)
If indx >= 0 Then If indx >= 0 Then
mm = Downloader.Files(indx) mm = Downloader.Files(indx)
__user = mm.UserInfo
mm_data = mm.Data mm_data = mm.Data
mm_data.File = df mm_data.File = df
mm = New UserMediaD(mm_data, If(moveOptions.ReplaceUserProfile_Profile, mm.User), mm.Session, mm.Date) mm = New UserMediaD(mm_data, If(moveOptions.ReplaceUserProfile_Profile, mm.User), mm.Session, mm.Date) With {.IsSavedPosts = mm.IsSavedPosts}
If moveOptions.ReplaceUserProfile_Profile Is Nothing And mm.IsSavedPosts Then mm.UserInfo = __user
Downloader.Files(indx) = mm Downloader.Files(indx) = mm
downloaderFilesUpdated = True downloaderFilesUpdated = True
End If End If
@@ -679,9 +698,11 @@ Namespace DownloadObjects
indx = sessionData.FindIndex(finder) indx = sessionData.FindIndex(finder)
If indx >= 0 Then If indx >= 0 Then
mm = sessionData(indx) mm = sessionData(indx)
__user = mm.UserInfo
mm_data = mm.Data mm_data = mm.Data
mm_data.File = df mm_data.File = df
mm = New UserMediaD(mm_data, If(moveOptions.ReplaceUserProfile_Profile, mm.User), mm.Session, mm.Date) mm = New UserMediaD(mm_data, If(moveOptions.ReplaceUserProfile_Profile, mm.User), mm.Session, mm.Date) With {.IsSavedPosts = mm.IsSavedPosts}
If moveOptions.ReplaceUserProfile_Profile Is Nothing And mm.IsSavedPosts Then mm.UserInfo = __user
sessionData(indx) = mm sessionData(indx) = mm
sesFilesReplaced = True sesFilesReplaced = True
If DataList.Count > 0 Then If DataList.Count > 0 Then
@@ -860,7 +881,6 @@ Namespace DownloadObjects
End If End If
Catch ex As Exception Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "Delete daily sessions (by list)") ErrorsDescriber.Execute(EDP.SendToLog, ex, "Delete daily sessions (by list)")
MainFrameObj.UpdateLogButton()
End Try End Try
End Sub End Sub
Private Sub BTT_FEED_DELETE_DAILY_DATE_Click(sender As Object, e As EventArgs) Handles BTT_FEED_DELETE_DAILY_DATE.Click Private Sub BTT_FEED_DELETE_DAILY_DATE_Click(sender As Object, e As EventArgs) Handles BTT_FEED_DELETE_DAILY_DATE.Click
@@ -898,20 +918,23 @@ Namespace DownloadObjects
End Using End Using
Catch ex As Exception Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "Delete daily sessions (by date)") ErrorsDescriber.Execute(EDP.SendToLog, ex, "Delete daily sessions (by date)")
MainFrameObj.UpdateLogButton()
End Try End Try
End Sub End Sub
#End Region #End Region
#Region "Clear session" #Region "Sessions set, merge, clear"
Private Sub BTT_CLEAR_DAILY_Click(sender As Object, e As EventArgs) Handles BTT_CLEAR_DAILY.Click Private Sub BTT_CURR_SESSION_SET_Click(sender As Object, e As EventArgs) Handles BTT_CURR_SESSION_SET.Click
If MsgBoxE({"Are you sure you want to clear this session data?", "Clear session"}, vbExclamation,,, {"Process", "Cancel"}) = 0 Then Try
Downloader.Files.Clear() Dim f As SFile = Nothing
ClearTable() SessionChooser(False,,,, True, f)
RefillList() If Not f.IsEmptyString AndAlso f.Exists Then
End If Downloader.FilesLoadLastSession(f)
FeedChangeMode(FeedModes.Current)
RefillList(True, False)
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Replace current session")
End Try
End Sub End Sub
#End Region
#Region "Merge feeds"
Private Sub BTT_MERGE_SESSIONS_Click(sender As Object, e As EventArgs) Handles BTT_MERGE_SESSIONS.Click Private Sub BTT_MERGE_SESSIONS_Click(sender As Object, e As EventArgs) Handles BTT_MERGE_SESSIONS.Click
Try Try
Const msgTitle$ = "Merge feeds" Const msgTitle$ = "Merge feeds"
@@ -972,6 +995,23 @@ Namespace DownloadObjects
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[DownloadFeedForm.MergeSessions]") ErrorsDescriber.Execute(EDP.SendToLog, ex, "[DownloadFeedForm.MergeSessions]")
End Try End Try
End Sub End Sub
Private Sub BTT_CLEAR_DAILY_Click(sender As Object, e As EventArgs) Handles BTT_CLEAR_DAILY.Click
If MsgBoxE({"Are you sure you want to clear this session data?", "Clear session"}, vbExclamation,,, {"Process", "Cancel"}) = 0 Then
Downloader.Files.Clear()
ClearTable()
RefillList()
End If
End Sub
Private Sub BTT_RESET_DAILY_Click(sender As Object, e As EventArgs) Handles BTT_RESET_DAILY.Click
If MsgBoxE({"Are you sure you want to reset the current session?" & vbCr &
"A new file will be created for the current session", "Reset current session"}, vbExclamation,,, {"Process", "Cancel"}) = 0 Then
Downloader.ResetSession()
FeedChangeMode(FeedModes.Current)
RefillList(True, False)
End If
End Sub
#End Region
#Region "Merge feeds"
Private Sub BTT_MERGE_FEEDS_Click(sender As Object, e As EventArgs) Handles BTT_MERGE_FEEDS.Click Private Sub BTT_MERGE_FEEDS_Click(sender As Object, e As EventArgs) Handles BTT_MERGE_FEEDS.Click
Try Try
Const msgTitle$ = "Merge feeds" Const msgTitle$ = "Merge feeds"

View File

@@ -221,8 +221,8 @@ Namespace DownloadObjects
Information = $"Type: {Media.Data.Type}" Information = $"Type: {Media.Data.Type}"
Information.StringAppendLine($"File: {File.File}") Information.StringAppendLine($"File: {File.File}")
Information.StringAppendLine($"Address: {File}") Information.StringAppendLine($"Address: {File}")
Information.StringAppendLine($"Downloaded: {Media.Date.ToStringDate(ADateTime.Formats.BaseDateTime)}") Information.StringAppendLine($"Downloaded: {Media.Date.ToStringDateDef}")
If Media.Data.Post.Date.HasValue Then Information.StringAppendLine($"Posted: {Media.Data.Post.Date.Value.ToStringDate(ADateTime.Formats.BaseDateTime)}") If Media.Data.Post.Date.HasValue Then Information.StringAppendLine($"Post date: {Media.Data.Post.Date.Value.ToStringDateDef}")
Dim infoType As UserMedia.Types = If(IsSubscription, UserMedia.Types.Picture, Media.Data.Type) Dim infoType As UserMedia.Types = If(IsSubscription, UserMedia.Types.Picture, Media.Data.Type)
Dim h% Dim h%
Dim s As Size Dim s As Size
@@ -267,23 +267,27 @@ Namespace DownloadObjects
BTT_CONTEXT_OPEN_MEDIA.Text &= " video" BTT_CONTEXT_OPEN_MEDIA.Text &= " video"
BTT_CONTEXT_DELETE.Text &= " video" BTT_CONTEXT_DELETE.Text &= " video"
h = VideoHeight h = VideoHeight
AddHandler MyVideo.DoubleClick, AddressOf MyPicture_DoubleClick
Case Else : Throw New ArgumentNullException With {.HelpLink = 1} Case Else : Throw New ArgumentNullException With {.HelpLink = 1}
End Select End Select
Dim info$ = $"[{infoType}] - " Dim info$ = If(Settings.FeedAddTypeToCaption.Value And Not IsSubscription, $"[{infoType}] - ", String.Empty)
If Not Media.User Is Nothing Then If Not Media.User Is Nothing Then
With Media.User With Media.User
Dim otherName$ = If(Media.IsSavedPosts, "Saved", Media.UserInfo.Name)
Dim site$ = If(Settings.FeedAddSiteToCaption.Value, $"{ .Site} - ", String.Empty)
UserKey = .Key UserKey = .Key
Information &= vbNewLine.StringDup(2) Information &= vbNewLine.StringDup(2)
If .IncludedInCollection Then Information.StringAppendLine($"User collection: { .CollectionName}") If .IncludedInCollection Then Information.StringAppendLine($"User collection: { .CollectionName}")
Information.StringAppendLine($"User site: { .Site}") Information.StringAppendLine($"User site: { .Site}")
Information.StringAppendLine($"User name: {IIf(Not .FriendlyName.IsEmptyString And Not .IncludedInCollection, .FriendlyName, .Name)}") Information.StringAppendLine($"User name: {CStr(IIf(Not .FriendlyName.IsEmptyString And Not .IncludedInCollection, .FriendlyName, .Name)).IfNullOrEmpty(otherName)}")
If .IncludedInCollection Then info &= $"[{ .CollectionName}]: " If .IncludedInCollection Then info &= $"[{ .CollectionName}]: "
If Settings.FeedShowFriendlyNames Or Not DirectCast(.Self, UserDataBase).FeedIsUser Then If Settings.FeedShowFriendlyNames Or Not DirectCast(.Self, UserDataBase).FeedIsUser Then
info &= $"{ .Site} - { .FriendlyName.IfNullOrEmpty(.Name)}" info &= $"{site}{ .FriendlyName.IfNullOrEmpty(.Name).IfNullOrEmpty(otherName)}"
Else Else
info &= $"{ .Site} - {IIf(Not .FriendlyName.IsEmptyString And Not .IncludedInCollection, .FriendlyName, .Name)}" info &= $"{site}{CStr(IIf(Not .FriendlyName.IsEmptyString And Not .IncludedInCollection, .FriendlyName, .Name)).IfNullOrEmpty(otherName)}"
End If End If
End With End With
End If End If

View File

@@ -139,7 +139,6 @@ Namespace DownloadObjects
End If End If
Catch ex As Exception Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[FeedSpecial.UpdateUsers]") ErrorsDescriber.Execute(EDP.SendToLog, ex, "[FeedSpecial.UpdateUsers]")
MainFrameObj.UpdateLogButton()
End Try End Try
End Sub End Sub
Friend Overloads Shared Function UpdateUsers(ByVal Item As UserMediaD, ByVal InitialUser As UserInfo, ByVal NewUser As UserInfo, Friend Overloads Shared Function UpdateUsers(ByVal Item As UserMediaD, ByVal InitialUser As UserInfo, ByVal NewUser As UserInfo,
@@ -148,6 +147,7 @@ Namespace DownloadObjects
Dim user As IUserData Dim user As IUserData
Dim path$ = InitialUser.File.CutPath.PathWithSeparator Dim path$ = InitialUser.File.CutPath.PathWithSeparator
Dim pathNew$ = NewUser.File.CutPath.PathWithSeparator Dim pathNew$ = NewUser.File.CutPath.PathWithSeparator
Dim isSaved As Boolean = Item.IsSavedPosts
If Item.UserInfo.Equals(InitialUser) Or Item.UserInfo.Equals(NewUser) Then If Item.UserInfo.Equals(InitialUser) Or Item.UserInfo.Equals(NewUser) Then
If Item.Data.File.PathWithSeparator.Contains(path) Then If Item.Data.File.PathWithSeparator.Contains(path) Then
data = Item.Data data = Item.Data
@@ -158,7 +158,7 @@ Namespace DownloadObjects
user = Item.User user = Item.User
End If End If
If Not If(user?.IsSubscription, False) Then If Not If(user?.IsSubscription, False) Then
Item = New UserMediaD(data, user, Item.Session, Item.Date) Item = New UserMediaD(data, user, Item.Session, Item.Date) With {.IsSavedPosts = isSaved}
Result = True Result = True
Return Item Return Item
End If End If
@@ -175,8 +175,10 @@ Namespace DownloadObjects
If indx >= 0 Then If indx >= 0 Then
Dim m As UserMediaD = Items(indx) Dim m As UserMediaD = Items(indx)
Dim mm As UserMedia = m.Data Dim mm As UserMedia = m.Data
Dim user As UserInfo = m.UserInfo
mm.File = NewFile mm.File = NewFile
m = New UserMediaD(mm, If(MCTOptions.ReplaceUserProfile_Profile, m.User), m.Session, m.Date) m = New UserMediaD(mm, If(MCTOptions.ReplaceUserProfile_Profile, m.User), m.Session, m.Date) With {.IsSavedPosts = m.IsSavedPosts}
If MCTOptions.ReplaceUserProfile_Profile Is Nothing And m.IsSavedPosts Then m.UserInfo = user
Items(indx) = m Items(indx) = m
_FilesUpdated = True _FilesUpdated = True
End If End If

View File

@@ -111,7 +111,6 @@ Namespace DownloadObjects
End If End If
Catch ex As Exception Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[FeedSpecialCollection.Load]") ErrorsDescriber.Execute(EDP.SendToLog, ex, "[FeedSpecialCollection.Load]")
MainFrameObj.UpdateLogButton()
End Try End Try
End Sub End Sub
Private Sub Feeds_FeedDeleted(ByVal Source As FeedSpecialCollection, ByVal Feed As FeedSpecial) Private Sub Feeds_FeedDeleted(ByVal Source As FeedSpecialCollection, ByVal Feed As FeedSpecial)
@@ -236,7 +235,7 @@ Namespace DownloadObjects
Friend Sub UpdateUsers(ByVal InitialUser As UserInfo, ByVal NewUser As UserInfo) Friend Sub UpdateUsers(ByVal InitialUser As UserInfo, ByVal NewUser As UserInfo)
Try Try
Load() Load()
If Count > 0 Then If Count > 0 AndAlso Not UserInfo.ExactEquals(InitialUser, NewUser) Then
Feeds.ForEach(Sub(f) f.UpdateUsers(InitialUser, NewUser)) Feeds.ForEach(Sub(f) f.UpdateUsers(InitialUser, NewUser))
If Downloader.Files.Count > 0 Then If Downloader.Files.Count > 0 Then
PendingUsersToUpdate.Add(New KeyValuePair(Of UserInfo, UserInfo)(InitialUser, NewUser)) PendingUsersToUpdate.Add(New KeyValuePair(Of UserInfo, UserInfo)(InitialUser, NewUser))
@@ -245,7 +244,6 @@ Namespace DownloadObjects
End If End If
Catch ex As Exception Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[FeedSpecialCollection.UpdateUsers]") ErrorsDescriber.Execute(EDP.SendToLog, ex, "[FeedSpecialCollection.UpdateUsers]")
MainFrameObj.UpdateLogButton()
End Try End Try
End Sub End Sub
#End Region #End Region

View File

@@ -176,5 +176,9 @@ Namespace DownloadObjects
ErrorsDescriber.Execute(EDP.SendToLog, ex, $"An error occurred while performing action [{ActionName}] on file [{MediaFile}]") ErrorsDescriber.Execute(EDP.SendToLog, ex, $"An error occurred while performing action [{ActionName}] on file [{MediaFile}]")
End Try End Try
End Function End Function
Private Sub MyVideo_DoubleClick(sender As Object, e As EventArgs) Handles MyVideo.DoubleClick
[Stop]()
OnDoubleClick(e)
End Sub
End Class End Class
End Namespace End Namespace

View File

@@ -20,6 +20,7 @@ Namespace DownloadObjects.Groups
Private Const Name_FilterViewMode As String = "FilterViewMode" Private Const Name_FilterViewMode As String = "FilterViewMode"
Private Const Name_FilterGroupUsers As String = "FilterGroupUsers" Private Const Name_FilterGroupUsers As String = "FilterGroupUsers"
Private Const Name_FilterShowGroupsInsteadLabels As String = "FilterShowGroupsInsteadLabels" Private Const Name_FilterShowGroupsInsteadLabels As String = "FilterShowGroupsInsteadLabels"
Private Const Name_FilterShowAllUsers As String = "FilterShowAllUsers"
#End Region #End Region
#Region "Declarations" #Region "Declarations"
#Region "Controls" #Region "Controls"
@@ -36,6 +37,7 @@ Namespace DownloadObjects.Groups
Friend Property FilterViewMode As ViewModes = ViewModes.IconLarge Friend Property FilterViewMode As ViewModes = ViewModes.IconLarge
Friend Property FilterGroupUsers As Boolean = True Friend Property FilterGroupUsers As Boolean = True
Friend Property FilterShowGroupsInsteadLabels As Boolean = True Friend Property FilterShowGroupsInsteadLabels As Boolean = True
Friend Property FilterShowAllUsers As Boolean = False
#End Region #End Region
Private File As SFile = Nothing Private File As SFile = Nothing
Friend Overrides Property Name As String Friend Overrides Property Name As String
@@ -144,13 +146,15 @@ Namespace DownloadObjects.Groups
FilterViewMode = e.Value(Name_FilterViewMode).FromXML(Of Integer)(ViewModes.IconLarge) FilterViewMode = e.Value(Name_FilterViewMode).FromXML(Of Integer)(ViewModes.IconLarge)
FilterGroupUsers = e.Value(Name_FilterGroupUsers).FromXML(Of Boolean)(True) FilterGroupUsers = e.Value(Name_FilterGroupUsers).FromXML(Of Boolean)(True)
FilterShowGroupsInsteadLabels = e.Value(Name_FilterShowGroupsInsteadLabels).FromXML(Of Boolean)(True) FilterShowGroupsInsteadLabels = e.Value(Name_FilterShowGroupsInsteadLabels).FromXML(Of Boolean)(True)
FilterShowAllUsers = e.Value(Name_FilterShowAllUsers).FromXML(Of Boolean)(False)
End If End If
End Sub End Sub
Protected Overrides Function Export(ByVal e As EContainer) As EContainer Protected Overrides Function Export(ByVal e As EContainer) As EContainer
MyBase.Export(e) MyBase.Export(e)
e.AddRange({New EContainer(Name_FilterViewMode, CInt(FilterViewMode)), e.AddRange({New EContainer(Name_FilterViewMode, CInt(FilterViewMode)),
New EContainer(Name_FilterGroupUsers, FilterGroupUsers.BoolToInteger), New EContainer(Name_FilterGroupUsers, FilterGroupUsers.BoolToInteger),
New EContainer(Name_FilterShowGroupsInsteadLabels, FilterShowGroupsInsteadLabels.BoolToInteger)}) New EContainer(Name_FilterShowGroupsInsteadLabels, FilterShowGroupsInsteadLabels.BoolToInteger),
New EContainer(Name_FilterShowAllUsers, FilterShowAllUsers.BoolToInteger)})
Return e Return e
End Function End Function
#End Region #End Region
@@ -166,6 +170,7 @@ Namespace DownloadObjects.Groups
FilterViewMode = .FilterViewMode FilterViewMode = .FilterViewMode
FilterGroupUsers = .FilterGroupUsers FilterGroupUsers = .FilterGroupUsers
FilterShowGroupsInsteadLabels = .FilterShowGroupsInsteadLabels FilterShowGroupsInsteadLabels = .FilterShowGroupsInsteadLabels
FilterShowAllUsers = .FilterShowAllUsers
End If End If
End With End With
End If End If

View File

@@ -117,6 +117,8 @@ Namespace DownloadObjects.Groups
RefillList() RefillList()
If Not IsViewFilter Then Settings.Groups.BeginUpdate() If Not IsViewFilter Then Settings.Groups.BeginUpdate()
If IsViewFilter And LIST_GROUPS.Items.Count > 0 Then .MyOkCancel.EnableOK = True : _LatestSelected = 0
.DelegateClosingChecker = False .DelegateClosingChecker = False
.EndLoaderOperations() .EndLoaderOperations()

View File

@@ -93,7 +93,6 @@ Namespace DownloadObjects.STDownloader
End With End With
Catch ex As Exception Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[STDownloader.DownloaderUrlForm.TXT_URL_ActionOnTextChanged]") ErrorsDescriber.Execute(EDP.SendToLog, ex, "[STDownloader.DownloaderUrlForm.TXT_URL_ActionOnTextChanged]")
MainFrameObj.UpdateLogButton()
End Try End Try
End Sub End Sub
Private Sub TXT_PATH_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_PATH.ActionOnButtonClick Private Sub TXT_PATH_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_PATH.ActionOnButtonClick

View File

@@ -108,7 +108,6 @@ Namespace DownloadObjects.STDownloader
Catch ex As Exception Catch ex As Exception
_UseAccountName = True _UseAccountName = True
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[STDownloader.DownloaderUrlsArrForm.TXT_URLS_TextChanged]") ErrorsDescriber.Execute(EDP.SendToLog, ex, "[STDownloader.DownloaderUrlsArrForm.TXT_URLS_TextChanged]")
MainFrameObj.UpdateLogButton()
End Try End Try
End Sub End Sub
End Class End Class

View File

@@ -226,9 +226,5 @@ Namespace DownloadObjects.STDownloader
RemoveControls(ControlNonYT, False) RemoveControls(ControlNonYT, False)
End If End If
End Sub End Sub
Protected Overrides Sub MyJob_Finished(ByVal Sender As Object, ByVal e As EventArgs)
MainFrameObj.UpdateLogButton()
MyBase.MyJob_Finished(Sender, e)
End Sub
End Class End Class
End Namespace End Namespace

View File

@@ -39,7 +39,7 @@ Namespace DownloadObjects
#End Region #End Region
Friend ReadOnly User As IUserData Friend ReadOnly User As IUserData
Friend ReadOnly Data As UserMedia Friend ReadOnly Data As UserMedia
Friend ReadOnly UserInfo As UserInfo Friend UserInfo As UserInfo
Friend ReadOnly [Date] As Date Friend ReadOnly [Date] As Date
Friend Session As Integer Friend Session As Integer
Friend IsSavedPosts As Boolean Friend IsSavedPosts As Boolean
@@ -116,8 +116,10 @@ Namespace DownloadObjects
Friend Const SessionsPath As String = "Settings\Sessions\" Friend Const SessionsPath As String = "Settings\Sessions\"
Private _FilesSessionCleared As Boolean = False Private _FilesSessionCleared As Boolean = False
Private _FilesSessionActual As SFile = Nothing Private _FilesSessionActual As SFile = Nothing
Private _FilesSessionChecked As Boolean = False
Friend ReadOnly Property FilesSessionActual(Optional ByVal GenerateFileName As Boolean = True) As SFile Friend ReadOnly Property FilesSessionActual(Optional ByVal GenerateFileName As Boolean = True) As SFile
Get Get
FilesLoadLastSession()
If _FilesSessionActual.IsEmptyString And GenerateFileName Then _ If _FilesSessionActual.IsEmptyString And GenerateFileName Then _
_FilesSessionActual = $"{SessionsPath}{AConvert(Of String)(Now, SessionDateTimeProvider)}.xml" _FilesSessionActual = $"{SessionsPath}{AConvert(Of String)(Now, SessionDateTimeProvider)}.xml"
Return _FilesSessionActual Return _FilesSessionActual
@@ -146,11 +148,58 @@ Namespace DownloadObjects
_FilesSaving = False _FilesSaving = False
End Try End Try
End Function End Function
Private _FilesSessionChecked_Impl As Boolean = False
Friend Sub FilesLoadLastSession(Optional ByVal SelectedSessionFile As SFile = Nothing)
Try
If Not SelectedSessionFile.IsEmptyString Or (Not _FilesSessionChecked And Not _FilesSessionChecked_Impl And _FilesSessionActual.IsEmptyString) Then
_FilesSessionChecked = True
_FilesSessionChecked_Impl = True
Dim settingValue% = Settings.FeedCurrentTryLoadLastSession
Dim ssfExists As Boolean = Not SelectedSessionFile.IsEmptyString AndAlso SelectedSessionFile.Exists
If settingValue >= 0 Or ssfExists Then
Dim startTime As Date = Process.GetCurrentProcess.StartTime
Dim files As List(Of SFile)
If ssfExists Then
files = New List(Of SFile) From {SelectedSessionFile}
Else
files = SFile.GetFiles(SessionsPath.CSFileP, "*.xml",, EDP.ReturnValue)
If files.ListExists Then files.RemoveAll(Settings.Feeds.FeedSpecialRemover)
If files.ListExists Then
Dim nd$ = Now.ToString("yyyyMMdd")
files.RemoveAll(Function(f) Not f.Name.StartsWith(nd))
End If
End If
If files.ListExists Then
files.Sort()
Dim lastDate As Date = AConvert(Of Date)(files.Last.Name, SessionDateTimeProvider)
If ssfExists Or lastDate.Date = startTime.Date Then
Dim __files As New List(Of UserMediaD)
Using x As New XmlFile(files.Last, Protector.Modes.All, False) With {.AllowSameNames = True, .XmlReadOnly = True}
x.LoadData()
If x.Count > 0 Then __files.ListAddList(x, LAP.IgnoreICopier)
If __files.Count > 0 AndAlso (settingValue = 0 OrElse ssfExists OrElse
(startTime - {lastDate, __files.Max(Function(f) f.Date)}.Max).TotalMinutes <= settingValue) Then
_Session = __files.Max(Function(f) f.Session)
Me.Files.AddRange(__files)
_FilesSessionActual = files.Last
End If
__files.Clear()
End Using
End If
End If
End If
_FilesSessionChecked_Impl = False
End If
Catch ex As Exception
_FilesSessionChecked_Impl = False
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[TDownloader.FilesLoadLastSession]")
End Try
End Sub
Private _FilesUpdating As Boolean = False Private _FilesUpdating As Boolean = False
Friend Sub FilesUpdatePendingUsers() Friend Sub FilesUpdatePendingUsers()
_FilesUpdating = True
Try Try
If Files.Count > 0 Then If Files.Count > 0 Then
_FilesUpdating = True
With Settings.Feeds With Settings.Feeds
Dim pUsers As List(Of KeyValuePair(Of UserInfo, UserInfo)) Dim pUsers As List(Of KeyValuePair(Of UserInfo, UserInfo))
Dim pendingUser As KeyValuePair(Of UserInfo, UserInfo) Dim pendingUser As KeyValuePair(Of UserInfo, UserInfo)
@@ -171,19 +220,20 @@ Namespace DownloadObjects
Next Next
End If End If
End With End With
If changed Then FilesSave() If changed Then _FilesUpdating = False : FilesSave()
Next Next
pUsers.Clear() pUsers.Clear()
End While End While
End With End With
_FilesUpdating = False
End If End If
Catch aex As ArgumentOutOfRangeException Catch aex As ArgumentOutOfRangeException
Catch iex As IndexOutOfRangeException
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[TDownloader.FilesUpdatePendingUsers]")
MainFrameObj.UpdateLogButton()
Finally
_FilesUpdating = False _FilesUpdating = False
Catch iex As IndexOutOfRangeException
_FilesUpdating = False
Catch ex As Exception
_FilesUpdating = False
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[TDownloader.FilesUpdatePendingUsers]")
End Try End Try
End Sub End Sub
Friend Sub ClearSessions() Friend Sub ClearSessions()
@@ -207,6 +257,13 @@ Namespace DownloadObjects
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[DownloadObjects.TDownloader.ClearSessions]") ErrorsDescriber.Execute(EDP.SendToLog, ex, "[DownloadObjects.TDownloader.ClearSessions]")
End Try End Try
End Sub End Sub
Friend Sub ResetSession()
Files.Clear()
_FilesSessionActual = Nothing
_FilesSessionChecked = True
_Session = 0
_SessionSavedPosts = -1
End Sub
#End Region #End Region
Friend ReadOnly Property Downloaded As List(Of IUserData) Friend ReadOnly Property Downloaded As List(Of IUserData)
Private ReadOnly NProv As IFormatProvider Private ReadOnly NProv As IFormatProvider
@@ -444,7 +501,16 @@ Namespace DownloadObjects
End If End If
End Set End Set
End Property End Property
Private Session As Integer = 0 Private _Session As Integer = 0
Private Property Session As Integer
Get
FilesLoadLastSession()
Return _Session
End Get
Set(ByVal _Session As Integer)
Me._Session = _Session
End Set
End Property
Private Sub [Start]() 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 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 If Not If(CheckerThread?.IsAlive, False) Then
@@ -482,10 +548,8 @@ Namespace DownloadObjects
If Pool.Count > 0 Then Pool.ForEach(Sub(p) If Not p.Progress Is Nothing Then p.Progress.Maximum = 0) If Pool.Count > 0 Then Pool.ForEach(Sub(p) If Not p.Progress Is Nothing Then p.Progress.Maximum = 0)
ExecuteCommand(Settings.DownloadsCompleteCommand) ExecuteCommand(Settings.DownloadsCompleteCommand)
UpdateJobsLabel() UpdateJobsLabel()
If MissingPostsDetected And Settings.AddMissingToLog Then If MissingPostsDetected And Settings.AddMissingToLog Then _
MyMainLOG = "Some posts didn't download. You can see them in the 'Missing posts' form." MyMainLOG = "Some posts didn't download. You can see them in the 'Missing posts' form."
MainFrameObj.UpdateLogButton()
End If
Files.Sort() Files.Sort()
FilesChanged = Not fBefore = Files.Count FilesChanged = Not fBefore = Files.Count
RaiseEvent Downloading(False) RaiseEvent Downloading(False)
@@ -558,6 +622,7 @@ Namespace DownloadObjects
Dim limitIndex% Dim limitIndex%
Dim limits As New List(Of HostLimit) Dim limits As New List(Of HostLimit)
Dim Keys As New List(Of String) Dim Keys As New List(Of String)
Dim KeysSkipped As New List(Of String)
Dim h As Boolean = False Dim h As Boolean = False
Dim host As SettingsHost = Nothing Dim host As SettingsHost = Nothing
Dim hostAvailable As Boolean Dim hostAvailable As Boolean
@@ -584,6 +649,8 @@ Namespace DownloadObjects
limit = limit.Next limit = limit.Next
limits(limitIndex) = limit limits(limitIndex) = limit
If limit.Value >= limit.Limit Then Exit For If limit.Value >= limit.Limit Then Exit For
Else
KeysSkipped.Add(_Item.Key)
End If End If
End If End If
End If End If
@@ -601,24 +668,27 @@ Namespace DownloadObjects
For Each k$ In Keys For Each k$ In Keys
i = _Job.Items.FindIndex(Function(ii) ii.Key = k) i = _Job.Items.FindIndex(Function(ii) ii.Key = k)
If i >= 0 Then If i >= 0 Then
With _Job.Items(i) If KeysSkipped.Count = 0 OrElse Not KeysSkipped.Contains(k) Then
If DirectCast(.Self, UserDataBase).ContentMissingExists Then MissingPostsDetected = True With _Job.Items(i)
RaiseEvent UserDownloadStateChanged(.Self, False) If DirectCast(.Self, UserDataBase).ContentMissingExists Then MissingPostsDetected = True
host = _Job.UserHost(.Self) RaiseEvent UserDownloadStateChanged(.Self, False)
host.AfterDownload(.Self, Download.Main) host = _Job.UserHost(.Self)
If Not .Disposed AndAlso Not .IsCollection AndAlso .DownloadedTotal(False) > 0 Then host.AfterDownload(.Self, Download.Main)
If Not Downloaded.Contains(.Self) Then Downloaded.Add(Settings.GetUser(.Self)) If Not .Disposed AndAlso Not .IsCollection AndAlso .DownloadedTotal(False) > 0 Then
With DirectCast(.Self, UserDataBase) If Not Downloaded.Contains(.Self) Then Downloaded.Add(Settings.GetUser(.Self))
If .LatestData.Count > 0 And .IncludeInTheFeed Then Files.ListAddList(.LatestData.Select(Function(d) New UserMediaD(d, .Self, Session)), FilesLP) With DirectCast(.Self, UserDataBase)
End With If .LatestData.Count > 0 And .IncludeInTheFeed Then Files.ListAddList(.LatestData.Select(Function(d) New UserMediaD(d, .Self, Session)), FilesLP)
dcc = True End With
End If dcc = True
End With End If
End With
End If
_Job.Items.RemoveAt(i) _Job.Items.RemoveAt(i)
End If End If
Next Next
End If End If
Keys.Clear() Keys.Clear()
KeysSkipped.Clear()
_Job.Items.RemoveAll(Function(ii) ii.Disposed) _Job.Items.RemoveAll(Function(ii) ii.Disposed)
If dcc Then Downloaded.RemoveAll(Function(u) u Is Nothing) If dcc Then Downloaded.RemoveAll(Function(u) u Is Nothing)
If dcc And Downloaded.Count > 0 Then RaiseEvent DownloadCountChange() If dcc And Downloaded.Count > 0 Then RaiseEvent DownloadCountChange()

View File

@@ -59,11 +59,12 @@ Namespace Editors
Dim TAB_FEED As System.Windows.Forms.TabPage Dim TAB_FEED As System.Windows.Forms.TabPage
Dim TP_FEED As System.Windows.Forms.TableLayoutPanel Dim TP_FEED As System.Windows.Forms.TableLayoutPanel
Dim TP_FEED_IMG_COUNT As System.Windows.Forms.TableLayoutPanel Dim TP_FEED_IMG_COUNT As System.Windows.Forms.TableLayoutPanel
Dim TP_FEED_SES As System.Windows.Forms.TableLayoutPanel
Dim ActionButton13 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton14 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TAB_NOTIFY As System.Windows.Forms.TabPage Dim TAB_NOTIFY As System.Windows.Forms.TabPage
Dim TP_NOTIFY_MAIN As System.Windows.Forms.TableLayoutPanel Dim TP_NOTIFY_MAIN As System.Windows.Forms.TableLayoutPanel
Dim TP_ENVIR As System.Windows.Forms.TableLayoutPanel Dim TP_ENVIR As System.Windows.Forms.TableLayoutPanel
Dim ActionButton13 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton14 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton15 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton15 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton16 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton16 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton17 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton17 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
@@ -76,23 +77,25 @@ Namespace Editors
Dim ActionButton24 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton24 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton25 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton25 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton26 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton26 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton27 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton28 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TAB_STD As System.Windows.Forms.TabPage Dim TAB_STD As System.Windows.Forms.TabPage
Dim TP_STD As System.Windows.Forms.TableLayoutPanel Dim TP_STD As System.Windows.Forms.TableLayoutPanel
Dim ActionButton27 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton29 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ListColumn1 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn() Dim ListColumn1 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
Dim ListColumn2 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn() Dim ListColumn2 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
Dim TAB_DESIGN As System.Windows.Forms.TabPage Dim TAB_DESIGN As System.Windows.Forms.TabPage
Dim TP_DESIGN As System.Windows.Forms.TableLayoutPanel Dim TP_DESIGN As System.Windows.Forms.TableLayoutPanel
Dim ActionButton28 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton29 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton30 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton30 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton31 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton31 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TP_HEADERS_DEF As System.Windows.Forms.TableLayoutPanel
Dim ActionButton32 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton32 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton33 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton33 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TP_HEADERS_DEF As System.Windows.Forms.TableLayoutPanel
Dim ActionButton34 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton34 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton35 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton35 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton36 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton36 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton37 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton38 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TAB_HEADERS As System.Windows.Forms.TabPage Dim TAB_HEADERS As System.Windows.Forms.TabPage
Me.TXT_GLOBAL_PATH = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_GLOBAL_PATH = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_IMAGE_LARGE = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_IMAGE_LARGE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
@@ -164,16 +167,19 @@ Namespace Editors
Me.TXT_DOWN_COMPLETE_SCRIPT = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_DOWN_COMPLETE_SCRIPT = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.CH_UNAME_UP = New System.Windows.Forms.CheckBox() Me.CH_UNAME_UP = New System.Windows.Forms.CheckBox()
Me.CH_UICON_UP = New System.Windows.Forms.CheckBox() Me.CH_UICON_UP = New System.Windows.Forms.CheckBox()
Me.TXT_AUTO_BRUSH_MIN = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_FEED_ROWS = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_FEED_ROWS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_FEED_COLUMNS = 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_ENDLESS = New System.Windows.Forms.CheckBox()
Me.CH_FEED_ADD_SESSION = 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.CH_FEED_ADD_DATE = New System.Windows.Forms.CheckBox()
Me.NUM_FEED_STORE_SESSION_DATA = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_FEED_CENTER_IMAGE = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_FEED_CENTER_IMAGE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.COLORS_FEED = New SCrawler.Editors.ColorPicker() Me.COLORS_FEED = New SCrawler.Editors.ColorPicker()
Me.CH_FEED_SHOW_FRIENDLY = New System.Windows.Forms.CheckBox() Me.CH_FEED_SHOW_FRIENDLY = New System.Windows.Forms.CheckBox()
Me.CH_FEED_SHOW_SPEC_MEDIAITEM = New System.Windows.Forms.CheckBox() Me.CH_FEED_SHOW_SPEC_MEDIAITEM = New System.Windows.Forms.CheckBox()
Me.NUM_FEED_STORE_SESSION_DATA = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.NUM_FEED_SES_CURR_LOAD_LAST = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.CH_FEED_ADD_SITE = New System.Windows.Forms.CheckBox()
Me.TXT_YTDLP = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_YTDLP = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_FFMPEG = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_FFMPEG = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_CURL = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_CURL = New PersonalUtilities.Forms.Controls.TextBoxExtended()
@@ -199,6 +205,7 @@ Namespace Editors
Me.TAB_MAIN = New System.Windows.Forms.TabControl() Me.TAB_MAIN = New System.Windows.Forms.TabControl()
Me.TAB_ENVIR = New System.Windows.Forms.TabPage() Me.TAB_ENVIR = New System.Windows.Forms.TabPage()
Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer() Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
Me.CH_FEED_ADD_TYPE = New System.Windows.Forms.CheckBox()
TP_BASIS = New System.Windows.Forms.TableLayoutPanel() TP_BASIS = New System.Windows.Forms.TableLayoutPanel()
TP_IMAGES = New System.Windows.Forms.TableLayoutPanel() TP_IMAGES = New System.Windows.Forms.TableLayoutPanel()
TP_FILE_NAME = New System.Windows.Forms.TableLayoutPanel() TP_FILE_NAME = New System.Windows.Forms.TableLayoutPanel()
@@ -222,6 +229,7 @@ Namespace Editors
TAB_FEED = New System.Windows.Forms.TabPage() TAB_FEED = New System.Windows.Forms.TabPage()
TP_FEED = New System.Windows.Forms.TableLayoutPanel() TP_FEED = New System.Windows.Forms.TableLayoutPanel()
TP_FEED_IMG_COUNT = New System.Windows.Forms.TableLayoutPanel() TP_FEED_IMG_COUNT = New System.Windows.Forms.TableLayoutPanel()
TP_FEED_SES = New System.Windows.Forms.TableLayoutPanel()
TAB_NOTIFY = New System.Windows.Forms.TabPage() TAB_NOTIFY = New System.Windows.Forms.TabPage()
TP_NOTIFY_MAIN = New System.Windows.Forms.TableLayoutPanel() TP_NOTIFY_MAIN = New System.Windows.Forms.TableLayoutPanel()
TP_ENVIR = New System.Windows.Forms.TableLayoutPanel() TP_ENVIR = New System.Windows.Forms.TableLayoutPanel()
@@ -264,13 +272,16 @@ Namespace Editors
CType(Me.TXT_SCRIPT, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_SCRIPT, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_DOWN_COMPLETE_SCRIPT, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_DOWN_COMPLETE_SCRIPT, System.ComponentModel.ISupportInitialize).BeginInit()
TP_MISSING_DATA.SuspendLayout() TP_MISSING_DATA.SuspendLayout()
CType(Me.TXT_AUTO_BRUSH_MIN, System.ComponentModel.ISupportInitialize).BeginInit()
TAB_FEED.SuspendLayout() TAB_FEED.SuspendLayout()
TP_FEED.SuspendLayout() TP_FEED.SuspendLayout()
TP_FEED_IMG_COUNT.SuspendLayout() TP_FEED_IMG_COUNT.SuspendLayout()
CType(Me.TXT_FEED_ROWS, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_FEED_ROWS, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_FEED_COLUMNS, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_FEED_COLUMNS, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.NUM_FEED_STORE_SESSION_DATA, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_FEED_CENTER_IMAGE, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_FEED_CENTER_IMAGE, System.ComponentModel.ISupportInitialize).BeginInit()
TP_FEED_SES.SuspendLayout()
CType(Me.NUM_FEED_STORE_SESSION_DATA, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.NUM_FEED_SES_CURR_LOAD_LAST, System.ComponentModel.ISupportInitialize).BeginInit()
TAB_NOTIFY.SuspendLayout() TAB_NOTIFY.SuspendLayout()
TP_NOTIFY_MAIN.SuspendLayout() TP_NOTIFY_MAIN.SuspendLayout()
TP_ENVIR.SuspendLayout() TP_ENVIR.SuspendLayout()
@@ -940,10 +951,10 @@ Namespace Editors
' '
Me.CH_FEED_OPEN_LAST_MODE.AutoSize = True Me.CH_FEED_OPEN_LAST_MODE.AutoSize = True
Me.CH_FEED_OPEN_LAST_MODE.Dock = System.Windows.Forms.DockStyle.Fill Me.CH_FEED_OPEN_LAST_MODE.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_FEED_OPEN_LAST_MODE.Location = New System.Drawing.Point(4, 195) Me.CH_FEED_OPEN_LAST_MODE.Location = New System.Drawing.Point(4, 247)
Me.CH_FEED_OPEN_LAST_MODE.Name = "CH_FEED_OPEN_LAST_MODE" Me.CH_FEED_OPEN_LAST_MODE.Name = "CH_FEED_OPEN_LAST_MODE"
Me.CH_FEED_OPEN_LAST_MODE.Size = New System.Drawing.Size(613, 19) Me.CH_FEED_OPEN_LAST_MODE.Size = New System.Drawing.Size(613, 19)
Me.CH_FEED_OPEN_LAST_MODE.TabIndex = 7 Me.CH_FEED_OPEN_LAST_MODE.TabIndex = 9
Me.CH_FEED_OPEN_LAST_MODE.Text = "Open last mode (users or subscriptions)" Me.CH_FEED_OPEN_LAST_MODE.Text = "Open last mode (users or subscriptions)"
TT_MAIN.SetToolTip(Me.CH_FEED_OPEN_LAST_MODE, "If disabled, the user mode will be used when initializing the feed.") TT_MAIN.SetToolTip(Me.CH_FEED_OPEN_LAST_MODE, "If disabled, the user mode will be used when initializing the feed.")
Me.CH_FEED_OPEN_LAST_MODE.UseVisualStyleBackColor = True Me.CH_FEED_OPEN_LAST_MODE.UseVisualStyleBackColor = True
@@ -1053,10 +1064,10 @@ Namespace Editors
' '
Me.CH_FEED_UP_FILE_LOC_MOVE.AutoSize = True Me.CH_FEED_UP_FILE_LOC_MOVE.AutoSize = True
Me.CH_FEED_UP_FILE_LOC_MOVE.Dock = System.Windows.Forms.DockStyle.Fill Me.CH_FEED_UP_FILE_LOC_MOVE.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_FEED_UP_FILE_LOC_MOVE.Location = New System.Drawing.Point(4, 273) Me.CH_FEED_UP_FILE_LOC_MOVE.Location = New System.Drawing.Point(4, 325)
Me.CH_FEED_UP_FILE_LOC_MOVE.Name = "CH_FEED_UP_FILE_LOC_MOVE" Me.CH_FEED_UP_FILE_LOC_MOVE.Name = "CH_FEED_UP_FILE_LOC_MOVE"
Me.CH_FEED_UP_FILE_LOC_MOVE.Size = New System.Drawing.Size(613, 19) Me.CH_FEED_UP_FILE_LOC_MOVE.Size = New System.Drawing.Size(613, 19)
Me.CH_FEED_UP_FILE_LOC_MOVE.TabIndex = 10 Me.CH_FEED_UP_FILE_LOC_MOVE.TabIndex = 12
Me.CH_FEED_UP_FILE_LOC_MOVE.Text = "Update file location when moved" Me.CH_FEED_UP_FILE_LOC_MOVE.Text = "Update file location when moved"
TT_MAIN.SetToolTip(Me.CH_FEED_UP_FILE_LOC_MOVE, "The file location will be updated in the session data and in the feeds data") TT_MAIN.SetToolTip(Me.CH_FEED_UP_FILE_LOC_MOVE, "The file location will be updated in the session data and in the feeds data")
Me.CH_FEED_UP_FILE_LOC_MOVE.UseVisualStyleBackColor = True Me.CH_FEED_UP_FILE_LOC_MOVE.UseVisualStyleBackColor = True
@@ -1481,10 +1492,11 @@ Namespace Editors
TP_DOWNLOADING.Controls.Add(Me.CH_UNAME_UP, 0, 1) TP_DOWNLOADING.Controls.Add(Me.CH_UNAME_UP, 0, 1)
TP_DOWNLOADING.Controls.Add(Me.CH_UICON_UP, 0, 2) TP_DOWNLOADING.Controls.Add(Me.CH_UICON_UP, 0, 2)
TP_DOWNLOADING.Controls.Add(Me.CH_USE_DEF_ACC, 0, 9) TP_DOWNLOADING.Controls.Add(Me.CH_USE_DEF_ACC, 0, 9)
TP_DOWNLOADING.Controls.Add(Me.TXT_AUTO_BRUSH_MIN, 0, 10)
TP_DOWNLOADING.Dock = System.Windows.Forms.DockStyle.Fill TP_DOWNLOADING.Dock = System.Windows.Forms.DockStyle.Fill
TP_DOWNLOADING.Location = New System.Drawing.Point(0, 0) TP_DOWNLOADING.Location = New System.Drawing.Point(0, 0)
TP_DOWNLOADING.Name = "TP_DOWNLOADING" TP_DOWNLOADING.Name = "TP_DOWNLOADING"
TP_DOWNLOADING.RowCount = 11 TP_DOWNLOADING.RowCount = 12
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, 25.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.Absolute, 25.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.Absolute, 25.0!))
@@ -1495,6 +1507,7 @@ Namespace Editors
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, 25.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.Absolute, 25.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.Absolute, 25.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.Percent, 100.0!)) TP_DOWNLOADING.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_DOWNLOADING.Size = New System.Drawing.Size(621, 399) TP_DOWNLOADING.Size = New System.Drawing.Size(621, 399)
TP_DOWNLOADING.TabIndex = 1 TP_DOWNLOADING.TabIndex = 1
@@ -1577,12 +1590,30 @@ Namespace Editors
Me.CH_UICON_UP.Text = "Update user icon and banner every time (where supported)" Me.CH_UICON_UP.Text = "Update user icon and banner every time (where supported)"
Me.CH_UICON_UP.UseVisualStyleBackColor = True Me.CH_UICON_UP.UseVisualStyleBackColor = True
' '
'TXT_AUTO_BRUSH_MIN
'
Me.TXT_AUTO_BRUSH_MIN.CaptionText = "Highlight undownloaded plans (minutes)"
Me.TXT_AUTO_BRUSH_MIN.CaptionToolTipEnabled = True
Me.TXT_AUTO_BRUSH_MIN.CaptionToolTipText = "Highlight (in gray) the scheduler plans that have not been downloaded in 'x' minu" &
"tes." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "-1 to disable."
Me.TXT_AUTO_BRUSH_MIN.CaptionWidth = 200.0R
Me.TXT_AUTO_BRUSH_MIN.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown
Me.TXT_AUTO_BRUSH_MIN.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_AUTO_BRUSH_MIN.Location = New System.Drawing.Point(4, 280)
Me.TXT_AUTO_BRUSH_MIN.Name = "TXT_AUTO_BRUSH_MIN"
Me.TXT_AUTO_BRUSH_MIN.NumberMaximum = New Decimal(New Integer() {2147483646, 0, 0, 0})
Me.TXT_AUTO_BRUSH_MIN.NumberMinimum = New Decimal(New Integer() {1, 0, 0, -2147483648})
Me.TXT_AUTO_BRUSH_MIN.NumberUpDownAlign = System.Windows.Forms.LeftRightAlignment.Left
Me.TXT_AUTO_BRUSH_MIN.Size = New System.Drawing.Size(613, 22)
Me.TXT_AUTO_BRUSH_MIN.TabIndex = 10
Me.TXT_AUTO_BRUSH_MIN.Text = "-1"
'
'TAB_FEED 'TAB_FEED
' '
TAB_FEED.Controls.Add(TP_FEED) TAB_FEED.Controls.Add(TP_FEED)
TAB_FEED.Location = New System.Drawing.Point(4, 22) TAB_FEED.Location = New System.Drawing.Point(4, 22)
TAB_FEED.Name = "TAB_FEED" TAB_FEED.Name = "TAB_FEED"
TAB_FEED.Size = New System.Drawing.Size(621, 399) TAB_FEED.Size = New System.Drawing.Size(621, 374)
TAB_FEED.TabIndex = 7 TAB_FEED.TabIndex = 7
TAB_FEED.Text = "Feed" TAB_FEED.Text = "Feed"
' '
@@ -1594,31 +1625,35 @@ Namespace Editors
TP_FEED.Controls.Add(TP_FEED_IMG_COUNT, 0, 0) TP_FEED.Controls.Add(TP_FEED_IMG_COUNT, 0, 0)
TP_FEED.Controls.Add(Me.CH_FEED_ENDLESS, 0, 3) TP_FEED.Controls.Add(Me.CH_FEED_ENDLESS, 0, 3)
TP_FEED.Controls.Add(Me.CH_FEED_ADD_SESSION, 0, 4) TP_FEED.Controls.Add(Me.CH_FEED_ADD_SESSION, 0, 4)
TP_FEED.Controls.Add(Me.CH_FEED_ADD_DATE, 0, 5) TP_FEED.Controls.Add(Me.CH_FEED_ADD_DATE, 0, 7)
TP_FEED.Controls.Add(Me.NUM_FEED_STORE_SESSION_DATA, 0, 6)
TP_FEED.Controls.Add(Me.TXT_FEED_CENTER_IMAGE, 0, 1) TP_FEED.Controls.Add(Me.TXT_FEED_CENTER_IMAGE, 0, 1)
TP_FEED.Controls.Add(Me.COLORS_FEED, 0, 2) TP_FEED.Controls.Add(Me.COLORS_FEED, 0, 2)
TP_FEED.Controls.Add(Me.CH_FEED_OPEN_LAST_MODE, 0, 7) TP_FEED.Controls.Add(Me.CH_FEED_OPEN_LAST_MODE, 0, 9)
TP_FEED.Controls.Add(Me.CH_FEED_SHOW_FRIENDLY, 0, 8) TP_FEED.Controls.Add(Me.CH_FEED_SHOW_FRIENDLY, 0, 10)
TP_FEED.Controls.Add(Me.CH_FEED_SHOW_SPEC_MEDIAITEM, 0, 9) TP_FEED.Controls.Add(Me.CH_FEED_SHOW_SPEC_MEDIAITEM, 0, 11)
TP_FEED.Controls.Add(Me.CH_FEED_UP_FILE_LOC_MOVE, 0, 10) TP_FEED.Controls.Add(Me.CH_FEED_UP_FILE_LOC_MOVE, 0, 12)
TP_FEED.Controls.Add(TP_FEED_SES, 0, 8)
TP_FEED.Controls.Add(Me.CH_FEED_ADD_SITE, 0, 5)
TP_FEED.Controls.Add(Me.CH_FEED_ADD_TYPE, 0, 6)
TP_FEED.Dock = System.Windows.Forms.DockStyle.Fill TP_FEED.Dock = System.Windows.Forms.DockStyle.Fill
TP_FEED.Location = New System.Drawing.Point(0, 0) TP_FEED.Location = New System.Drawing.Point(0, 0)
TP_FEED.Name = "TP_FEED" TP_FEED.Name = "TP_FEED"
TP_FEED.RowCount = 12 TP_FEED.RowCount = 14
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, 28.0!))
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, 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.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.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.Absolute, 25.0!))
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, 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.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.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.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_FEED.Size = New System.Drawing.Size(621, 399) TP_FEED.Size = New System.Drawing.Size(621, 374)
TP_FEED.TabIndex = 0 TP_FEED.TabIndex = 0
' '
'TP_FEED_IMG_COUNT 'TP_FEED_IMG_COUNT
@@ -1696,34 +1731,13 @@ Namespace Editors
' '
Me.CH_FEED_ADD_DATE.AutoSize = True Me.CH_FEED_ADD_DATE.AutoSize = True
Me.CH_FEED_ADD_DATE.Dock = System.Windows.Forms.DockStyle.Fill Me.CH_FEED_ADD_DATE.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_FEED_ADD_DATE.Location = New System.Drawing.Point(4, 140) Me.CH_FEED_ADD_DATE.Location = New System.Drawing.Point(4, 192)
Me.CH_FEED_ADD_DATE.Name = "CH_FEED_ADD_DATE" Me.CH_FEED_ADD_DATE.Name = "CH_FEED_ADD_DATE"
Me.CH_FEED_ADD_DATE.Size = New System.Drawing.Size(613, 19) Me.CH_FEED_ADD_DATE.Size = New System.Drawing.Size(613, 19)
Me.CH_FEED_ADD_DATE.TabIndex = 5 Me.CH_FEED_ADD_DATE.TabIndex = 7
Me.CH_FEED_ADD_DATE.Text = "Add the date to the post title" Me.CH_FEED_ADD_DATE.Text = "Add the date to the post title"
Me.CH_FEED_ADD_DATE.UseVisualStyleBackColor = True Me.CH_FEED_ADD_DATE.UseVisualStyleBackColor = True
' '
'NUM_FEED_STORE_SESSION_DATA
'
Me.NUM_FEED_STORE_SESSION_DATA.CaptionCheckAlign = System.Drawing.ContentAlignment.MiddleLeft
Me.NUM_FEED_STORE_SESSION_DATA.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox
Me.NUM_FEED_STORE_SESSION_DATA.CaptionText = "Store session data"
Me.NUM_FEED_STORE_SESSION_DATA.CaptionTextAlign = System.Drawing.ContentAlignment.MiddleLeft
Me.NUM_FEED_STORE_SESSION_DATA.CaptionToolTipEnabled = True
Me.NUM_FEED_STORE_SESSION_DATA.CaptionToolTipText = "If checked, session data will be stored in an xml file." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "The number indicates the" &
" number of sessions to be saved." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "-1 to save all sessions"
Me.NUM_FEED_STORE_SESSION_DATA.CaptionWidth = 115.0R
Me.NUM_FEED_STORE_SESSION_DATA.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown
Me.NUM_FEED_STORE_SESSION_DATA.Dock = System.Windows.Forms.DockStyle.Fill
Me.NUM_FEED_STORE_SESSION_DATA.Location = New System.Drawing.Point(4, 166)
Me.NUM_FEED_STORE_SESSION_DATA.Name = "NUM_FEED_STORE_SESSION_DATA"
Me.NUM_FEED_STORE_SESSION_DATA.NumberMaximum = New Decimal(New Integer() {100000, 0, 0, 0})
Me.NUM_FEED_STORE_SESSION_DATA.NumberMinimum = New Decimal(New Integer() {1, 0, 0, -2147483648})
Me.NUM_FEED_STORE_SESSION_DATA.NumberUpDownAlign = System.Windows.Forms.LeftRightAlignment.Left
Me.NUM_FEED_STORE_SESSION_DATA.Size = New System.Drawing.Size(613, 22)
Me.NUM_FEED_STORE_SESSION_DATA.TabIndex = 6
Me.NUM_FEED_STORE_SESSION_DATA.Text = "20"
'
'TXT_FEED_CENTER_IMAGE 'TXT_FEED_CENTER_IMAGE
' '
Me.TXT_FEED_CENTER_IMAGE.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox Me.TXT_FEED_CENTER_IMAGE.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox
@@ -1760,10 +1774,10 @@ Namespace Editors
' '
Me.CH_FEED_SHOW_FRIENDLY.AutoSize = True Me.CH_FEED_SHOW_FRIENDLY.AutoSize = True
Me.CH_FEED_SHOW_FRIENDLY.Dock = System.Windows.Forms.DockStyle.Fill Me.CH_FEED_SHOW_FRIENDLY.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_FEED_SHOW_FRIENDLY.Location = New System.Drawing.Point(4, 221) Me.CH_FEED_SHOW_FRIENDLY.Location = New System.Drawing.Point(4, 273)
Me.CH_FEED_SHOW_FRIENDLY.Name = "CH_FEED_SHOW_FRIENDLY" Me.CH_FEED_SHOW_FRIENDLY.Name = "CH_FEED_SHOW_FRIENDLY"
Me.CH_FEED_SHOW_FRIENDLY.Size = New System.Drawing.Size(613, 19) Me.CH_FEED_SHOW_FRIENDLY.Size = New System.Drawing.Size(613, 19)
Me.CH_FEED_SHOW_FRIENDLY.TabIndex = 8 Me.CH_FEED_SHOW_FRIENDLY.TabIndex = 10
Me.CH_FEED_SHOW_FRIENDLY.Text = "Show friendly names instead of usernames" Me.CH_FEED_SHOW_FRIENDLY.Text = "Show friendly names instead of usernames"
Me.CH_FEED_SHOW_FRIENDLY.UseVisualStyleBackColor = True Me.CH_FEED_SHOW_FRIENDLY.UseVisualStyleBackColor = True
' '
@@ -1771,13 +1785,88 @@ Namespace Editors
' '
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.AutoSize = True Me.CH_FEED_SHOW_SPEC_MEDIAITEM.AutoSize = True
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Dock = System.Windows.Forms.DockStyle.Fill Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Location = New System.Drawing.Point(4, 247) Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Location = New System.Drawing.Point(4, 299)
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Name = "CH_FEED_SHOW_SPEC_MEDIAITEM" Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Name = "CH_FEED_SHOW_SPEC_MEDIAITEM"
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Size = New System.Drawing.Size(613, 19) Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Size = New System.Drawing.Size(613, 19)
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.TabIndex = 9 Me.CH_FEED_SHOW_SPEC_MEDIAITEM.TabIndex = 11
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Text = "Show special feeds in media items" Me.CH_FEED_SHOW_SPEC_MEDIAITEM.Text = "Show special feeds in media items"
Me.CH_FEED_SHOW_SPEC_MEDIAITEM.UseVisualStyleBackColor = True Me.CH_FEED_SHOW_SPEC_MEDIAITEM.UseVisualStyleBackColor = True
' '
'TP_FEED_SES
'
TP_FEED_SES.ColumnCount = 2
TP_FEED_SES.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_FEED_SES.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_FEED_SES.Controls.Add(Me.NUM_FEED_STORE_SESSION_DATA, 0, 0)
TP_FEED_SES.Controls.Add(Me.NUM_FEED_SES_CURR_LOAD_LAST, 1, 0)
TP_FEED_SES.Dock = System.Windows.Forms.DockStyle.Fill
TP_FEED_SES.Location = New System.Drawing.Point(1, 215)
TP_FEED_SES.Margin = New System.Windows.Forms.Padding(0)
TP_FEED_SES.Name = "TP_FEED_SES"
TP_FEED_SES.RowCount = 1
TP_FEED_SES.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_FEED_SES.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_FEED_SES.Size = New System.Drawing.Size(619, 28)
TP_FEED_SES.TabIndex = 8
'
'NUM_FEED_STORE_SESSION_DATA
'
Me.NUM_FEED_STORE_SESSION_DATA.CaptionCheckAlign = System.Drawing.ContentAlignment.MiddleLeft
Me.NUM_FEED_STORE_SESSION_DATA.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox
Me.NUM_FEED_STORE_SESSION_DATA.CaptionText = "Store session data"
Me.NUM_FEED_STORE_SESSION_DATA.CaptionTextAlign = System.Drawing.ContentAlignment.MiddleLeft
Me.NUM_FEED_STORE_SESSION_DATA.CaptionToolTipEnabled = True
Me.NUM_FEED_STORE_SESSION_DATA.CaptionToolTipText = "If checked, session data will be stored in an xml file." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "The number indicates the" &
" number of sessions to be saved." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "-1 to save all sessions"
Me.NUM_FEED_STORE_SESSION_DATA.CaptionWidth = 115.0R
Me.NUM_FEED_STORE_SESSION_DATA.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown
Me.NUM_FEED_STORE_SESSION_DATA.Dock = System.Windows.Forms.DockStyle.Fill
Me.NUM_FEED_STORE_SESSION_DATA.Location = New System.Drawing.Point(3, 3)
Me.NUM_FEED_STORE_SESSION_DATA.Name = "NUM_FEED_STORE_SESSION_DATA"
Me.NUM_FEED_STORE_SESSION_DATA.NumberMaximum = New Decimal(New Integer() {100000, 0, 0, 0})
Me.NUM_FEED_STORE_SESSION_DATA.NumberMinimum = New Decimal(New Integer() {1, 0, 0, -2147483648})
Me.NUM_FEED_STORE_SESSION_DATA.NumberUpDownAlign = System.Windows.Forms.LeftRightAlignment.Left
Me.NUM_FEED_STORE_SESSION_DATA.Size = New System.Drawing.Size(303, 22)
Me.NUM_FEED_STORE_SESSION_DATA.TabIndex = 0
Me.NUM_FEED_STORE_SESSION_DATA.Text = "20"
'
'NUM_FEED_SES_CURR_LOAD_LAST
'
ActionButton13.BackgroundImage = CType(resources.GetObject("ActionButton13.BackgroundImage"), System.Drawing.Image)
ActionButton13.Name = "Refresh"
ActionButton13.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton14.BackgroundImage = CType(resources.GetObject("ActionButton14.BackgroundImage"), System.Drawing.Image)
ActionButton14.Name = "Clear"
ActionButton14.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.NUM_FEED_SES_CURR_LOAD_LAST.Buttons.Add(ActionButton13)
Me.NUM_FEED_SES_CURR_LOAD_LAST.Buttons.Add(ActionButton14)
Me.NUM_FEED_SES_CURR_LOAD_LAST.CaptionText = "Load last session"
Me.NUM_FEED_SES_CURR_LOAD_LAST.CaptionToolTipEnabled = True
Me.NUM_FEED_SES_CURR_LOAD_LAST.CaptionToolTipText = resources.GetString("NUM_FEED_SES_CURR_LOAD_LAST.CaptionToolTipText")
Me.NUM_FEED_SES_CURR_LOAD_LAST.CaptionWidth = 115.0R
Me.NUM_FEED_SES_CURR_LOAD_LAST.ClearTextByButtonClear = False
Me.NUM_FEED_SES_CURR_LOAD_LAST.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown
Me.NUM_FEED_SES_CURR_LOAD_LAST.Dock = System.Windows.Forms.DockStyle.Fill
Me.NUM_FEED_SES_CURR_LOAD_LAST.Location = New System.Drawing.Point(312, 3)
Me.NUM_FEED_SES_CURR_LOAD_LAST.Name = "NUM_FEED_SES_CURR_LOAD_LAST"
Me.NUM_FEED_SES_CURR_LOAD_LAST.NumberMaximum = New Decimal(New Integer() {10080, 0, 0, 0})
Me.NUM_FEED_SES_CURR_LOAD_LAST.NumberMinimum = New Decimal(New Integer() {1, 0, 0, -2147483648})
Me.NUM_FEED_SES_CURR_LOAD_LAST.NumberUpDownAlign = System.Windows.Forms.LeftRightAlignment.Left
Me.NUM_FEED_SES_CURR_LOAD_LAST.Size = New System.Drawing.Size(304, 22)
Me.NUM_FEED_SES_CURR_LOAD_LAST.TabIndex = 1
Me.NUM_FEED_SES_CURR_LOAD_LAST.Text = "0"
'
'CH_FEED_ADD_SITE
'
Me.CH_FEED_ADD_SITE.AutoSize = True
Me.CH_FEED_ADD_SITE.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_FEED_ADD_SITE.Location = New System.Drawing.Point(4, 140)
Me.CH_FEED_ADD_SITE.Name = "CH_FEED_ADD_SITE"
Me.CH_FEED_ADD_SITE.Size = New System.Drawing.Size(613, 19)
Me.CH_FEED_ADD_SITE.TabIndex = 5
Me.CH_FEED_ADD_SITE.Text = "Add the site name to the post title"
Me.CH_FEED_ADD_SITE.UseVisualStyleBackColor = True
'
'TAB_NOTIFY 'TAB_NOTIFY
' '
TAB_NOTIFY.Controls.Add(TP_NOTIFY_MAIN) TAB_NOTIFY.Controls.Add(TP_NOTIFY_MAIN)
@@ -1843,19 +1932,19 @@ Namespace Editors
' '
'TXT_YTDLP 'TXT_YTDLP
' '
ActionButton13.BackgroundImage = CType(resources.GetObject("ActionButton13.BackgroundImage"), System.Drawing.Image)
ActionButton13.Name = "Open"
ActionButton13.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton14.BackgroundImage = CType(resources.GetObject("ActionButton14.BackgroundImage"), System.Drawing.Image)
ActionButton14.Name = "Refresh"
ActionButton14.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton14.ToolTipText = "Try to find this program automatically (in SCrawler and/or system environment)"
ActionButton15.BackgroundImage = CType(resources.GetObject("ActionButton15.BackgroundImage"), System.Drawing.Image) ActionButton15.BackgroundImage = CType(resources.GetObject("ActionButton15.BackgroundImage"), System.Drawing.Image)
ActionButton15.Name = "Clear" ActionButton15.Name = "Open"
ActionButton15.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton15.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
Me.TXT_YTDLP.Buttons.Add(ActionButton13) ActionButton16.BackgroundImage = CType(resources.GetObject("ActionButton16.BackgroundImage"), System.Drawing.Image)
Me.TXT_YTDLP.Buttons.Add(ActionButton14) ActionButton16.Name = "Refresh"
ActionButton16.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton16.ToolTipText = "Try to find this program automatically (in SCrawler and/or system environment)"
ActionButton17.BackgroundImage = CType(resources.GetObject("ActionButton17.BackgroundImage"), System.Drawing.Image)
ActionButton17.Name = "Clear"
ActionButton17.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_YTDLP.Buttons.Add(ActionButton15) Me.TXT_YTDLP.Buttons.Add(ActionButton15)
Me.TXT_YTDLP.Buttons.Add(ActionButton16)
Me.TXT_YTDLP.Buttons.Add(ActionButton17)
Me.TXT_YTDLP.CaptionText = "yt-dlp" Me.TXT_YTDLP.CaptionText = "yt-dlp"
Me.TXT_YTDLP.CaptionToolTipEnabled = True Me.TXT_YTDLP.CaptionToolTipEnabled = True
Me.TXT_YTDLP.CaptionToolTipText = "Path to yt-dlp.exe file" Me.TXT_YTDLP.CaptionToolTipText = "Path to yt-dlp.exe file"
@@ -1869,19 +1958,19 @@ Namespace Editors
' '
'TXT_FFMPEG 'TXT_FFMPEG
' '
ActionButton16.BackgroundImage = CType(resources.GetObject("ActionButton16.BackgroundImage"), System.Drawing.Image)
ActionButton16.Name = "Open"
ActionButton16.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton17.BackgroundImage = CType(resources.GetObject("ActionButton17.BackgroundImage"), System.Drawing.Image)
ActionButton17.Name = "Refresh"
ActionButton17.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton17.ToolTipText = "Try to find this program automatically (in SCrawler and/or system environment)"
ActionButton18.BackgroundImage = CType(resources.GetObject("ActionButton18.BackgroundImage"), System.Drawing.Image) ActionButton18.BackgroundImage = CType(resources.GetObject("ActionButton18.BackgroundImage"), System.Drawing.Image)
ActionButton18.Name = "Clear" ActionButton18.Name = "Open"
ActionButton18.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton18.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
Me.TXT_FFMPEG.Buttons.Add(ActionButton16) ActionButton19.BackgroundImage = CType(resources.GetObject("ActionButton19.BackgroundImage"), System.Drawing.Image)
Me.TXT_FFMPEG.Buttons.Add(ActionButton17) ActionButton19.Name = "Refresh"
ActionButton19.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton19.ToolTipText = "Try to find this program automatically (in SCrawler and/or system environment)"
ActionButton20.BackgroundImage = CType(resources.GetObject("ActionButton20.BackgroundImage"), System.Drawing.Image)
ActionButton20.Name = "Clear"
ActionButton20.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_FFMPEG.Buttons.Add(ActionButton18) Me.TXT_FFMPEG.Buttons.Add(ActionButton18)
Me.TXT_FFMPEG.Buttons.Add(ActionButton19)
Me.TXT_FFMPEG.Buttons.Add(ActionButton20)
Me.TXT_FFMPEG.CaptionText = "ffmpeg" Me.TXT_FFMPEG.CaptionText = "ffmpeg"
Me.TXT_FFMPEG.CaptionToolTipEnabled = True Me.TXT_FFMPEG.CaptionToolTipEnabled = True
Me.TXT_FFMPEG.CaptionToolTipText = "Path to ffmpeg.exe file" Me.TXT_FFMPEG.CaptionToolTipText = "Path to ffmpeg.exe file"
@@ -1895,19 +1984,19 @@ Namespace Editors
' '
'TXT_CURL 'TXT_CURL
' '
ActionButton19.BackgroundImage = CType(resources.GetObject("ActionButton19.BackgroundImage"), System.Drawing.Image)
ActionButton19.Name = "Open"
ActionButton19.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton20.BackgroundImage = CType(resources.GetObject("ActionButton20.BackgroundImage"), System.Drawing.Image)
ActionButton20.Name = "Refresh"
ActionButton20.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton20.ToolTipText = "Try to find this program automatically (in SCrawler and/or system environment)"
ActionButton21.BackgroundImage = CType(resources.GetObject("ActionButton21.BackgroundImage"), System.Drawing.Image) ActionButton21.BackgroundImage = CType(resources.GetObject("ActionButton21.BackgroundImage"), System.Drawing.Image)
ActionButton21.Name = "Clear" ActionButton21.Name = "Open"
ActionButton21.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton21.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
Me.TXT_CURL.Buttons.Add(ActionButton19) ActionButton22.BackgroundImage = CType(resources.GetObject("ActionButton22.BackgroundImage"), System.Drawing.Image)
Me.TXT_CURL.Buttons.Add(ActionButton20) ActionButton22.Name = "Refresh"
ActionButton22.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton22.ToolTipText = "Try to find this program automatically (in SCrawler and/or system environment)"
ActionButton23.BackgroundImage = CType(resources.GetObject("ActionButton23.BackgroundImage"), System.Drawing.Image)
ActionButton23.Name = "Clear"
ActionButton23.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_CURL.Buttons.Add(ActionButton21) Me.TXT_CURL.Buttons.Add(ActionButton21)
Me.TXT_CURL.Buttons.Add(ActionButton22)
Me.TXT_CURL.Buttons.Add(ActionButton23)
Me.TXT_CURL.CaptionText = "cURL" Me.TXT_CURL.CaptionText = "cURL"
Me.TXT_CURL.CaptionToolTipEnabled = True Me.TXT_CURL.CaptionToolTipEnabled = True
Me.TXT_CURL.CaptionToolTipText = "Path to curl.exe file" Me.TXT_CURL.CaptionToolTipText = "Path to curl.exe file"
@@ -1921,19 +2010,19 @@ Namespace Editors
' '
'TXT_GALLERYDL 'TXT_GALLERYDL
' '
ActionButton22.BackgroundImage = CType(resources.GetObject("ActionButton22.BackgroundImage"), System.Drawing.Image)
ActionButton22.Name = "Open"
ActionButton22.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton23.BackgroundImage = CType(resources.GetObject("ActionButton23.BackgroundImage"), System.Drawing.Image)
ActionButton23.Name = "Refresh"
ActionButton23.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton23.ToolTipText = "Try to find this program automatically (in SCrawler and/or system environment)"
ActionButton24.BackgroundImage = CType(resources.GetObject("ActionButton24.BackgroundImage"), System.Drawing.Image) ActionButton24.BackgroundImage = CType(resources.GetObject("ActionButton24.BackgroundImage"), System.Drawing.Image)
ActionButton24.Name = "Clear" ActionButton24.Name = "Open"
ActionButton24.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton24.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
Me.TXT_GALLERYDL.Buttons.Add(ActionButton22) ActionButton25.BackgroundImage = CType(resources.GetObject("ActionButton25.BackgroundImage"), System.Drawing.Image)
Me.TXT_GALLERYDL.Buttons.Add(ActionButton23) ActionButton25.Name = "Refresh"
ActionButton25.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton25.ToolTipText = "Try to find this program automatically (in SCrawler and/or system environment)"
ActionButton26.BackgroundImage = CType(resources.GetObject("ActionButton26.BackgroundImage"), System.Drawing.Image)
ActionButton26.Name = "Clear"
ActionButton26.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_GALLERYDL.Buttons.Add(ActionButton24) Me.TXT_GALLERYDL.Buttons.Add(ActionButton24)
Me.TXT_GALLERYDL.Buttons.Add(ActionButton25)
Me.TXT_GALLERYDL.Buttons.Add(ActionButton26)
Me.TXT_GALLERYDL.CaptionText = "gallery-dl" Me.TXT_GALLERYDL.CaptionText = "gallery-dl"
Me.TXT_GALLERYDL.CaptionToolTipText = "Path to gallery-dl.exe file" Me.TXT_GALLERYDL.CaptionToolTipText = "Path to gallery-dl.exe file"
Me.TXT_GALLERYDL.CaptionWidth = 80.0R Me.TXT_GALLERYDL.CaptionWidth = 80.0R
@@ -1946,14 +2035,14 @@ Namespace Editors
' '
'TXT_CMD_ENCODING 'TXT_CMD_ENCODING
' '
ActionButton25.BackgroundImage = CType(resources.GetObject("ActionButton25.BackgroundImage"), System.Drawing.Image) ActionButton27.BackgroundImage = CType(resources.GetObject("ActionButton27.BackgroundImage"), System.Drawing.Image)
ActionButton25.Name = "Refresh" ActionButton27.Name = "Refresh"
ActionButton25.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh ActionButton27.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton26.BackgroundImage = CType(resources.GetObject("ActionButton26.BackgroundImage"), System.Drawing.Image) ActionButton28.BackgroundImage = CType(resources.GetObject("ActionButton28.BackgroundImage"), System.Drawing.Image)
ActionButton26.Name = "Clear" ActionButton28.Name = "Clear"
ActionButton26.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton28.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_CMD_ENCODING.Buttons.Add(ActionButton25) Me.TXT_CMD_ENCODING.Buttons.Add(ActionButton27)
Me.TXT_CMD_ENCODING.Buttons.Add(ActionButton26) Me.TXT_CMD_ENCODING.Buttons.Add(ActionButton28)
Me.TXT_CMD_ENCODING.CaptionText = "CMD Encoding" Me.TXT_CMD_ENCODING.CaptionText = "CMD Encoding"
Me.TXT_CMD_ENCODING.CaptionToolTipEnabled = True Me.TXT_CMD_ENCODING.CaptionToolTipEnabled = True
Me.TXT_CMD_ENCODING.CaptionToolTipText = "Command line encoding" Me.TXT_CMD_ENCODING.CaptionToolTipText = "Command line encoding"
@@ -2056,10 +2145,10 @@ Namespace Editors
' '
'CMB_STD_OPEN_DBL 'CMB_STD_OPEN_DBL
' '
ActionButton27.BackgroundImage = CType(resources.GetObject("ActionButton27.BackgroundImage"), System.Drawing.Image) ActionButton29.BackgroundImage = CType(resources.GetObject("ActionButton29.BackgroundImage"), System.Drawing.Image)
ActionButton27.Name = "ArrowDown" ActionButton29.Name = "ArrowDown"
ActionButton27.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.ArrowDown ActionButton29.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.ArrowDown
Me.CMB_STD_OPEN_DBL.Buttons.Add(ActionButton27) Me.CMB_STD_OPEN_DBL.Buttons.Add(ActionButton29)
Me.CMB_STD_OPEN_DBL.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.Label Me.CMB_STD_OPEN_DBL.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.Label
Me.CMB_STD_OPEN_DBL.CaptionText = "DoubleClick opens" Me.CMB_STD_OPEN_DBL.CaptionText = "DoubleClick opens"
Me.CMB_STD_OPEN_DBL.CaptionToolTipEnabled = True Me.CMB_STD_OPEN_DBL.CaptionToolTipEnabled = True
@@ -2141,10 +2230,10 @@ Namespace Editors
' '
'TXT_PRG_TITLE 'TXT_PRG_TITLE
' '
ActionButton28.BackgroundImage = CType(resources.GetObject("ActionButton28.BackgroundImage"), System.Drawing.Image) ActionButton30.BackgroundImage = CType(resources.GetObject("ActionButton30.BackgroundImage"), System.Drawing.Image)
ActionButton28.Name = "Clear" ActionButton30.Name = "Clear"
ActionButton28.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton30.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_PRG_TITLE.Buttons.Add(ActionButton28) Me.TXT_PRG_TITLE.Buttons.Add(ActionButton30)
Me.TXT_PRG_TITLE.CaptionText = "Program title" Me.TXT_PRG_TITLE.CaptionText = "Program title"
Me.TXT_PRG_TITLE.CaptionToolTipEnabled = True Me.TXT_PRG_TITLE.CaptionToolTipEnabled = True
Me.TXT_PRG_TITLE.CaptionToolTipText = "Change the title of the main window if you need to" Me.TXT_PRG_TITLE.CaptionToolTipText = "Change the title of the main window if you need to"
@@ -2156,10 +2245,10 @@ Namespace Editors
' '
'TXT_PRG_DESCR 'TXT_PRG_DESCR
' '
ActionButton29.BackgroundImage = CType(resources.GetObject("ActionButton29.BackgroundImage"), System.Drawing.Image) ActionButton31.BackgroundImage = CType(resources.GetObject("ActionButton31.BackgroundImage"), System.Drawing.Image)
ActionButton29.Name = "Clear" ActionButton31.Name = "Clear"
ActionButton29.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton31.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_PRG_DESCR.Buttons.Add(ActionButton29) Me.TXT_PRG_DESCR.Buttons.Add(ActionButton31)
Me.TXT_PRG_DESCR.CaptionText = "Program description" Me.TXT_PRG_DESCR.CaptionText = "Program description"
Me.TXT_PRG_DESCR.CaptionToolTipEnabled = True Me.TXT_PRG_DESCR.CaptionToolTipEnabled = True
Me.TXT_PRG_DESCR.CaptionToolTipText = "Add some additional info to the program info if you need" Me.TXT_PRG_DESCR.CaptionToolTipText = "Add some additional info to the program info if you need"
@@ -2171,14 +2260,14 @@ Namespace Editors
' '
'TXT_USER_LIST_IMAGE 'TXT_USER_LIST_IMAGE
' '
ActionButton30.BackgroundImage = CType(resources.GetObject("ActionButton30.BackgroundImage"), System.Drawing.Image) ActionButton32.BackgroundImage = CType(resources.GetObject("ActionButton32.BackgroundImage"), System.Drawing.Image)
ActionButton30.Name = "Open" ActionButton32.Name = "Open"
ActionButton30.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open ActionButton32.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton31.BackgroundImage = CType(resources.GetObject("ActionButton31.BackgroundImage"), System.Drawing.Image) ActionButton33.BackgroundImage = CType(resources.GetObject("ActionButton33.BackgroundImage"), System.Drawing.Image)
ActionButton31.Name = "Clear" ActionButton33.Name = "Clear"
ActionButton31.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton33.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_USER_LIST_IMAGE.Buttons.Add(ActionButton30) Me.TXT_USER_LIST_IMAGE.Buttons.Add(ActionButton32)
Me.TXT_USER_LIST_IMAGE.Buttons.Add(ActionButton31) Me.TXT_USER_LIST_IMAGE.Buttons.Add(ActionButton33)
Me.TXT_USER_LIST_IMAGE.CaptionText = "Userlist image" Me.TXT_USER_LIST_IMAGE.CaptionText = "Userlist image"
Me.TXT_USER_LIST_IMAGE.CaptionToolTipEnabled = True Me.TXT_USER_LIST_IMAGE.CaptionToolTipEnabled = True
Me.TXT_USER_LIST_IMAGE.CaptionToolTipText = "Background image for user list" Me.TXT_USER_LIST_IMAGE.CaptionToolTipText = "Background image for user list"
@@ -2252,10 +2341,10 @@ Namespace Editors
' '
'TXT_H_DEF_UserAgent 'TXT_H_DEF_UserAgent
' '
ActionButton32.BackgroundImage = CType(resources.GetObject("ActionButton32.BackgroundImage"), System.Drawing.Image) ActionButton34.BackgroundImage = CType(resources.GetObject("ActionButton34.BackgroundImage"), System.Drawing.Image)
ActionButton32.Name = "Clear" ActionButton34.Name = "Clear"
ActionButton32.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton34.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_H_DEF_UserAgent.Buttons.Add(ActionButton32) Me.TXT_H_DEF_UserAgent.Buttons.Add(ActionButton34)
Me.TXT_H_DEF_UserAgent.CaptionText = "UserAgent" Me.TXT_H_DEF_UserAgent.CaptionText = "UserAgent"
Me.TXT_H_DEF_UserAgent.CaptionWidth = 140.0R Me.TXT_H_DEF_UserAgent.CaptionWidth = 140.0R
Me.TXT_H_DEF_UserAgent.Dock = System.Windows.Forms.DockStyle.Fill Me.TXT_H_DEF_UserAgent.Dock = System.Windows.Forms.DockStyle.Fill
@@ -2266,10 +2355,10 @@ Namespace Editors
' '
'TXT_H_DEF_sec_ch_ua 'TXT_H_DEF_sec_ch_ua
' '
ActionButton33.BackgroundImage = CType(resources.GetObject("ActionButton33.BackgroundImage"), System.Drawing.Image) ActionButton35.BackgroundImage = CType(resources.GetObject("ActionButton35.BackgroundImage"), System.Drawing.Image)
ActionButton33.Name = "Clear" ActionButton35.Name = "Clear"
ActionButton33.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton35.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_H_DEF_sec_ch_ua.Buttons.Add(ActionButton33) Me.TXT_H_DEF_sec_ch_ua.Buttons.Add(ActionButton35)
Me.TXT_H_DEF_sec_ch_ua.CaptionText = "sec-ch-ua" Me.TXT_H_DEF_sec_ch_ua.CaptionText = "sec-ch-ua"
Me.TXT_H_DEF_sec_ch_ua.CaptionWidth = 140.0R Me.TXT_H_DEF_sec_ch_ua.CaptionWidth = 140.0R
Me.TXT_H_DEF_sec_ch_ua.Dock = System.Windows.Forms.DockStyle.Fill Me.TXT_H_DEF_sec_ch_ua.Dock = System.Windows.Forms.DockStyle.Fill
@@ -2280,10 +2369,10 @@ Namespace Editors
' '
'TXT_H_DEF_sec_ch_ua_full_version_list 'TXT_H_DEF_sec_ch_ua_full_version_list
' '
ActionButton34.BackgroundImage = CType(resources.GetObject("ActionButton34.BackgroundImage"), System.Drawing.Image) ActionButton36.BackgroundImage = CType(resources.GetObject("ActionButton36.BackgroundImage"), System.Drawing.Image)
ActionButton34.Name = "Clear" ActionButton36.Name = "Clear"
ActionButton34.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton36.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_H_DEF_sec_ch_ua_full_version_list.Buttons.Add(ActionButton34) Me.TXT_H_DEF_sec_ch_ua_full_version_list.Buttons.Add(ActionButton36)
Me.TXT_H_DEF_sec_ch_ua_full_version_list.CaptionText = "sec-ch-ua-full-version-list" Me.TXT_H_DEF_sec_ch_ua_full_version_list.CaptionText = "sec-ch-ua-full-version-list"
Me.TXT_H_DEF_sec_ch_ua_full_version_list.CaptionWidth = 140.0R Me.TXT_H_DEF_sec_ch_ua_full_version_list.CaptionWidth = 140.0R
Me.TXT_H_DEF_sec_ch_ua_full_version_list.Dock = System.Windows.Forms.DockStyle.Fill Me.TXT_H_DEF_sec_ch_ua_full_version_list.Dock = System.Windows.Forms.DockStyle.Fill
@@ -2294,10 +2383,10 @@ Namespace Editors
' '
'TXT_H_DEF_sec_ch_ua_platform 'TXT_H_DEF_sec_ch_ua_platform
' '
ActionButton35.BackgroundImage = CType(resources.GetObject("ActionButton35.BackgroundImage"), System.Drawing.Image) ActionButton37.BackgroundImage = CType(resources.GetObject("ActionButton37.BackgroundImage"), System.Drawing.Image)
ActionButton35.Name = "Clear" ActionButton37.Name = "Clear"
ActionButton35.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton37.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_H_DEF_sec_ch_ua_platform.Buttons.Add(ActionButton35) Me.TXT_H_DEF_sec_ch_ua_platform.Buttons.Add(ActionButton37)
Me.TXT_H_DEF_sec_ch_ua_platform.CaptionText = "sec-ch-ua-platform" Me.TXT_H_DEF_sec_ch_ua_platform.CaptionText = "sec-ch-ua-platform"
Me.TXT_H_DEF_sec_ch_ua_platform.CaptionWidth = 140.0R Me.TXT_H_DEF_sec_ch_ua_platform.CaptionWidth = 140.0R
Me.TXT_H_DEF_sec_ch_ua_platform.Dock = System.Windows.Forms.DockStyle.Fill Me.TXT_H_DEF_sec_ch_ua_platform.Dock = System.Windows.Forms.DockStyle.Fill
@@ -2308,10 +2397,10 @@ Namespace Editors
' '
'TXT_H_DEF_sec_ch_ua_platform_version 'TXT_H_DEF_sec_ch_ua_platform_version
' '
ActionButton36.BackgroundImage = CType(resources.GetObject("ActionButton36.BackgroundImage"), System.Drawing.Image) ActionButton38.BackgroundImage = CType(resources.GetObject("ActionButton38.BackgroundImage"), System.Drawing.Image)
ActionButton36.Name = "Clear" ActionButton38.Name = "Clear"
ActionButton36.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton38.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_H_DEF_sec_ch_ua_platform_version.Buttons.Add(ActionButton36) Me.TXT_H_DEF_sec_ch_ua_platform_version.Buttons.Add(ActionButton38)
Me.TXT_H_DEF_sec_ch_ua_platform_version.CaptionText = "sec-ch-ua-platform-version" Me.TXT_H_DEF_sec_ch_ua_platform_version.CaptionText = "sec-ch-ua-platform-version"
Me.TXT_H_DEF_sec_ch_ua_platform_version.CaptionWidth = 140.0R Me.TXT_H_DEF_sec_ch_ua_platform_version.CaptionWidth = 140.0R
Me.TXT_H_DEF_sec_ch_ua_platform_version.Dock = System.Windows.Forms.DockStyle.Fill Me.TXT_H_DEF_sec_ch_ua_platform_version.Dock = System.Windows.Forms.DockStyle.Fill
@@ -2346,7 +2435,7 @@ Namespace Editors
Me.TAB_MAIN.Location = New System.Drawing.Point(0, 0) Me.TAB_MAIN.Location = New System.Drawing.Point(0, 0)
Me.TAB_MAIN.Name = "TAB_MAIN" Me.TAB_MAIN.Name = "TAB_MAIN"
Me.TAB_MAIN.SelectedIndex = 0 Me.TAB_MAIN.SelectedIndex = 0
Me.TAB_MAIN.Size = New System.Drawing.Size(629, 425) Me.TAB_MAIN.Size = New System.Drawing.Size(629, 400)
Me.TAB_MAIN.TabIndex = 1 Me.TAB_MAIN.TabIndex = 1
' '
'TAB_ENVIR 'TAB_ENVIR
@@ -2364,7 +2453,7 @@ Namespace Editors
'CONTAINER_MAIN.ContentPanel 'CONTAINER_MAIN.ContentPanel
' '
Me.CONTAINER_MAIN.ContentPanel.Controls.Add(Me.TAB_MAIN) Me.CONTAINER_MAIN.ContentPanel.Controls.Add(Me.TAB_MAIN)
Me.CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(629, 425) Me.CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(629, 400)
Me.CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill Me.CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
Me.CONTAINER_MAIN.LeftToolStripPanelVisible = False Me.CONTAINER_MAIN.LeftToolStripPanelVisible = False
Me.CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0) Me.CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
@@ -2374,6 +2463,17 @@ Namespace Editors
Me.CONTAINER_MAIN.TabIndex = 0 Me.CONTAINER_MAIN.TabIndex = 0
Me.CONTAINER_MAIN.TopToolStripPanelVisible = False Me.CONTAINER_MAIN.TopToolStripPanelVisible = False
' '
'CH_FEED_ADD_TYPE
'
Me.CH_FEED_ADD_TYPE.AutoSize = True
Me.CH_FEED_ADD_TYPE.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_FEED_ADD_TYPE.Location = New System.Drawing.Point(4, 166)
Me.CH_FEED_ADD_TYPE.Name = "CH_FEED_ADD_TYPE"
Me.CH_FEED_ADD_TYPE.Size = New System.Drawing.Size(613, 19)
Me.CH_FEED_ADD_TYPE.TabIndex = 6
Me.CH_FEED_ADD_TYPE.Text = "Add the file type to the post title"
Me.CH_FEED_ADD_TYPE.UseVisualStyleBackColor = True
'
'GlobalSettingsForm 'GlobalSettingsForm
' '
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
@@ -2435,14 +2535,17 @@ Namespace Editors
CType(Me.TXT_DOWN_COMPLETE_SCRIPT, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_DOWN_COMPLETE_SCRIPT, System.ComponentModel.ISupportInitialize).EndInit()
TP_MISSING_DATA.ResumeLayout(False) TP_MISSING_DATA.ResumeLayout(False)
TP_MISSING_DATA.PerformLayout() TP_MISSING_DATA.PerformLayout()
CType(Me.TXT_AUTO_BRUSH_MIN, System.ComponentModel.ISupportInitialize).EndInit()
TAB_FEED.ResumeLayout(False) TAB_FEED.ResumeLayout(False)
TP_FEED.ResumeLayout(False) TP_FEED.ResumeLayout(False)
TP_FEED.PerformLayout() TP_FEED.PerformLayout()
TP_FEED_IMG_COUNT.ResumeLayout(False) TP_FEED_IMG_COUNT.ResumeLayout(False)
CType(Me.TXT_FEED_ROWS, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_FEED_ROWS, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_FEED_COLUMNS, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_FEED_COLUMNS, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.NUM_FEED_STORE_SESSION_DATA, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_FEED_CENTER_IMAGE, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_FEED_CENTER_IMAGE, System.ComponentModel.ISupportInitialize).EndInit()
TP_FEED_SES.ResumeLayout(False)
CType(Me.NUM_FEED_STORE_SESSION_DATA, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.NUM_FEED_SES_CURR_LOAD_LAST, System.ComponentModel.ISupportInitialize).EndInit()
TAB_NOTIFY.ResumeLayout(False) TAB_NOTIFY.ResumeLayout(False)
TP_NOTIFY_MAIN.ResumeLayout(False) TP_NOTIFY_MAIN.ResumeLayout(False)
TP_NOTIFY_MAIN.PerformLayout() TP_NOTIFY_MAIN.PerformLayout()
@@ -2582,5 +2685,9 @@ Namespace Editors
Private WithEvents CH_DOWN_ALL_F6_NOTIFY As CheckBox Private WithEvents CH_DOWN_ALL_F6_NOTIFY As CheckBox
Private WithEvents CH_DOWN_ALL_NOTIFY As CheckBox Private WithEvents CH_DOWN_ALL_NOTIFY As CheckBox
Private WithEvents CH_CHANNELS_USERS_READY_MARK As CheckBox Private WithEvents CH_CHANNELS_USERS_READY_MARK As CheckBox
Private WithEvents NUM_FEED_SES_CURR_LOAD_LAST As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents TXT_AUTO_BRUSH_MIN As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents CH_FEED_ADD_SITE As CheckBox
Private WithEvents CH_FEED_ADD_TYPE As CheckBox
End Class End Class
End Namespace End Namespace

View File

@@ -331,6 +331,39 @@ You can find more detailed information about the missing posts in the form that
<metadata name="TP_FEED_IMG_COUNT.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TP_FEED_IMG_COUNT.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<metadata name="TP_FEED_SES.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<data name="ActionButton13.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
QVQ4T2P4//8/QczOJyyqHpzfiE0OQwAZC8iqszAzs7CJ69o4BR768V/W2jcGXQ0KB4aFNS3dDQtnrbCb
ePCK48wTN1wXXXzge/jXf/clV55zC4hIIatF0cjIyMikElzc57z0wX+XHd/+2+//99/ywP//xlu//tdb
+eK/4Zp3/1WTOhYzARViNUAluKjTdf37/0ZTTn9TbdhwXblhwwW1/qOP1Ja9+K8w+95/6cm3/6v2Xvkv
qKjniGGAoIqRpW3/4e8S9uGdzFz82gwMDFxAzCxm4ZegtuLDf+VJ1/8rZM25IqLvnM/CximCYYCic1QN
v7x2JIwPwyrJ3XNUylddE9G2TWNmZOBDl4czmJiZMSRBmFdSyYyJgUEQmxwIYxWEYXZBCUls4sgYq6CA
prWNbtG8nXKeaVPR5XiVjSxEzf0yYXy4BBMLO6eQjoOXZvrkbbazrv53Xf/2v4CSbjBMXkhBl1/CMyNZ
qWnvGy5pNQ+YONwAfjXzAOupl/47LLr333L50/96q9/8l23YdES6cO5KuYqVW+R7Tj6SnfP0v4hryjyY
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value>
</data>
<data name="ActionButton14.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="NUM_FEED_SES_CURR_LOAD_LAST.CaptionToolTipText" xml:space="preserve">
<value>Try loading the last session of the current day (if it exists) as the current session after restarting SCrawler.
-1 - disabled.
0 - only the session of the current day.
&gt;0 - the value (in minutes) that must elapse since last file download in a session for that session to be considered current.</value>
</data>
<metadata name="TAB_NOTIFY.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TAB_NOTIFY.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
@@ -340,7 +373,7 @@ You can find more detailed information about the missing posts in the form that
<metadata name="TP_ENVIR.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TP_ENVIR.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<data name="ActionButton13.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton15.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
@@ -351,7 +384,7 @@ You can find more detailed information about the missing posts in the form that
cMaRN0UdBBkAAAAASUVORK5CYII= cMaRN0UdBBkAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="ActionButton14.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton16.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
@@ -367,50 +400,15 @@ You can find more detailed information about the missing posts in the form that
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg== VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="ActionButton15.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton17.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton16.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
cMaRN0UdBBkAAAAASUVORK5CYII=
</value>
</data>
<data name="ActionButton17.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
QVQ4T2P4//8/QczOJyyqHpzfiE0OQwAZC8iqszAzs7CJ69o4BR768V/W2jcGXQ0KB4aFNS3dDQtnrbCb
ePCK48wTN1wXXXzge/jXf/clV55zC4hIIatF0cjIyMikElzc57z0wX+XHd/+2+//99/ywP//xlu//tdb
+eK/4Zp3/1WTOhYzARViNUAluKjTdf37/0ZTTn9TbdhwXblhwwW1/qOP1Ja9+K8w+95/6cm3/6v2Xvkv
qKjniGGAoIqRpW3/4e8S9uGdzFz82gwMDFxAzCxm4ZegtuLDf+VJ1/8rZM25IqLvnM/CximCYYCic1QN
v7x2JIwPwyrJ3XNUylddE9G2TWNmZOBDl4czmJiZMSRBmFdSyYyJgUEQmxwIYxWEYXZBCUls4sgYq6CA
prWNbtG8nXKeaVPR5XiVjSxEzf0yYXy4BBMLO6eQjoOXZvrkbbazrv53Xf/2v4CSbjBMXkhBl1/CMyNZ
qWnvGy5pNQ+YONwAfjXzAOupl/47LLr333L50/96q9/8l23YdES6cO5KuYqVW+R7Tj6SnfP0v4hryjyY
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="ActionButton18.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton18.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton19.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
@@ -421,7 +419,7 @@ You can find more detailed information about the missing posts in the form that
cMaRN0UdBBkAAAAASUVORK5CYII= cMaRN0UdBBkAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="ActionButton20.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton19.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
@@ -435,17 +433,17 @@ You can find more detailed information about the missing posts in the form that
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74 HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg== VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value>
</data>
<data name="ActionButton20.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<data name="ActionButton21.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton21.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton22.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
@@ -456,7 +454,7 @@ You can find more detailed information about the missing posts in the form that
cMaRN0UdBBkAAAAASUVORK5CYII= cMaRN0UdBBkAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="ActionButton23.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton22.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
@@ -472,12 +470,23 @@ You can find more detailed information about the missing posts in the form that
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg== VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="ActionButton24.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton23.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton24.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
cMaRN0UdBBkAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="ActionButton25.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton25.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
@@ -502,6 +511,30 @@ You can find more detailed information about the missing posts in the form that
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton27.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
QVQ4T2P4//8/QczOJyyqHpzfiE0OQwAZC8iqszAzs7CJ69o4BR768V/W2jcGXQ0KB4aFNS3dDQtnrbCb
ePCK48wTN1wXXXzge/jXf/clV55zC4hIIatF0cjIyMikElzc57z0wX+XHd/+2+//99/ywP//xlu//tdb
+eK/4Zp3/1WTOhYzARViNUAluKjTdf37/0ZTTn9TbdhwXblhwwW1/qOP1Ja9+K8w+95/6cm3/6v2Xvkv
qKjniGGAoIqRpW3/4e8S9uGdzFz82gwMDFxAzCxm4ZegtuLDf+VJ1/8rZM25IqLvnM/CximCYYCic1QN
v7x2JIwPwyrJ3XNUylddE9G2TWNmZOBDl4czmJiZMSRBmFdSyYyJgUEQmxwIYxWEYXZBCUls4sgYq6CA
prWNbtG8nXKeaVPR5XiVjSxEzf0yYXy4BBMLO6eQjoOXZvrkbbazrv53Xf/2v4CSbjBMXkhBl1/CMyNZ
qWnvGy5pNQ+YONwAfjXzAOupl/47LLr333L50/96q9/8l23YdES6cO5KuYqVW+R7Tj6SnfP0v4hryjyY
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value>
</data>
<data name="ActionButton28.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<metadata name="TAB_STD.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TAB_STD.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
@@ -510,7 +543,7 @@ You can find more detailed information about the missing posts in the form that
<metadata name="TP_STD.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TP_STD.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<data name="ActionButton27.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton29.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE65JREFUeF7t iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE65JREFUeF7t
3X2sJWddB/DdLi2lQG2hdOHuvfM887J7Cxca4ELTQMDWKigIFpBAEAgi9g+CJpJo9Q8NJhgBiYZIYspL 3X2sJWddB/DdLi2lQG2hdOHuvfM887J7Cxca4ELTQMDWKigIFpBAEAgi9g+CJpJo9Q8NJhgBiYZIYspL
@@ -606,31 +639,12 @@ You can find more detailed information about the missing posts in the form that
<metadata name="TP_DESIGN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TP_DESIGN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<data name="ActionButton28.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton29.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton30.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton30.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+ AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
cMaRN0UdBBkAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="ActionButton31.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton31.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
@@ -641,15 +655,15 @@ You can find more detailed information about the missing posts in the form that
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<metadata name="TP_HEADERS_DEF.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<data name="ActionButton32.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton32.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
cMaRN0UdBBkAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="ActionButton33.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton33.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
@@ -660,6 +674,9 @@ You can find more detailed information about the missing posts in the form that
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<metadata name="TP_HEADERS_DEF.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<data name="ActionButton34.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton34.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
@@ -682,6 +699,22 @@ You can find more detailed information about the missing posts in the form that
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton37.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton38.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<metadata name="TAB_HEADERS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TAB_HEADERS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">

View File

@@ -19,6 +19,7 @@ Namespace Editors
Friend Property HeadersChanged As Boolean = False Friend Property HeadersChanged As Boolean = False
Friend Property PictureChanged As Boolean = False Friend Property PictureChanged As Boolean = False
Friend Property EnvironmentProgramsChanged As Boolean = False Friend Property EnvironmentProgramsChanged As Boolean = False
Friend Property UserAgentChanged As Boolean = False
Friend Sub New() Friend Sub New()
InitializeComponent() InitializeComponent()
MyDefs = New DefaultFormOptions(Me, Settings.Design) MyDefs = New DefaultFormOptions(Me, Settings.Design)
@@ -122,6 +123,7 @@ Namespace Editors
CH_ADD_MISSING_ERROS_TO_LOG.Checked = .AddMissingErrorsToLog CH_ADD_MISSING_ERROS_TO_LOG.Checked = .AddMissingErrorsToLog
CH_DOWN_REPARSE_MISSING.Checked = .ReparseMissingInTheRoutine CH_DOWN_REPARSE_MISSING.Checked = .ReparseMissingInTheRoutine
CH_USE_DEF_ACC.Checked = .UseDefaultAccountIfMissing CH_USE_DEF_ACC.Checked = .UseDefaultAccountIfMissing
TXT_AUTO_BRUSH_MIN.Value = .AutomationBrushUndownloadedPlansMinutes.Value
'Downloading: file names 'Downloading: file names
CH_FILE_NAME_CHANGE.Checked = Not .FileReplaceNameByDate.Value = FileNameReplaceMode.None CH_FILE_NAME_CHANGE.Checked = Not .FileReplaceNameByDate.Value = FileNameReplaceMode.None
OPT_FILE_NAME_REPLACE.Checked = .FileReplaceNameByDate.Value = FileNameReplaceMode.Replace OPT_FILE_NAME_REPLACE.Checked = .FileReplaceNameByDate.Value = FileNameReplaceMode.Replace
@@ -149,9 +151,12 @@ Namespace Editors
COLORS_FEED.ColorsSet(.FeedBackColor, .FeedForeColor, SystemColors.Window, SystemColors.WindowText) COLORS_FEED.ColorsSet(.FeedBackColor, .FeedForeColor, SystemColors.Window, SystemColors.WindowText)
CH_FEED_ENDLESS.Checked = .FeedEndless CH_FEED_ENDLESS.Checked = .FeedEndless
CH_FEED_ADD_SESSION.Checked = .FeedAddSessionToCaption CH_FEED_ADD_SESSION.Checked = .FeedAddSessionToCaption
CH_FEED_ADD_SITE.Checked = .FeedAddSiteToCaption
CH_FEED_ADD_TYPE.Checked = .FeedAddTypeToCaption
CH_FEED_ADD_DATE.Checked = .FeedAddDateToCaption CH_FEED_ADD_DATE.Checked = .FeedAddDateToCaption
NUM_FEED_STORE_SESSION_DATA.Checked = .FeedStoreSessionsData NUM_FEED_STORE_SESSION_DATA.Checked = .FeedStoreSessionsData
NUM_FEED_STORE_SESSION_DATA.Value = .FeedStoredSessionsNumber.Value NUM_FEED_STORE_SESSION_DATA.Value = .FeedStoredSessionsNumber.Value
NUM_FEED_SES_CURR_LOAD_LAST.Value = .FeedCurrentTryLoadLastSession.Value
CH_FEED_OPEN_LAST_MODE.Checked = .FeedOpenLastMode CH_FEED_OPEN_LAST_MODE.Checked = .FeedOpenLastMode
CH_FEED_SHOW_FRIENDLY.Checked = .FeedShowFriendlyNames CH_FEED_SHOW_FRIENDLY.Checked = .FeedShowFriendlyNames
CH_FEED_SHOW_SPEC_MEDIAITEM.Checked = .FeedShowSpecialFeedsMediaItem CH_FEED_SHOW_SPEC_MEDIAITEM.Checked = .FeedShowSpecialFeedsMediaItem
@@ -182,6 +187,7 @@ Namespace Editors
"Do you really want to continue?", "Do you really want to continue?",
"Increasing download tasks"}, "Increasing download tasks"},
vbExclamation,,, {"Confirm", $"Set to default ({SettingsCLS.DefaultMaxDownloadingTasks})", "Cancel"}) vbExclamation,,, {"Confirm", $"Set to default ({SettingsCLS.DefaultMaxDownloadingTasks})", "Cancel"})
If CInt(TXT_MAX_JOBS_USERS.Value) > SettingsCLS.DefaultMaxDownloadingTasks Then If CInt(TXT_MAX_JOBS_USERS.Value) > SettingsCLS.DefaultMaxDownloadingTasks Then
Select Case a.Invoke("users", TXT_MAX_JOBS_USERS.Value) Select Case a.Invoke("users", TXT_MAX_JOBS_USERS.Value)
Case 1 : TXT_MAX_JOBS_USERS.Value = SettingsCLS.DefaultMaxDownloadingTasks Case 1 : TXT_MAX_JOBS_USERS.Value = SettingsCLS.DefaultMaxDownloadingTasks
@@ -212,6 +218,25 @@ Namespace Editors
"If this case, the functionality of SCrawler will be limited, and some sites will not work at all.", "If this case, the functionality of SCrawler will be limited, and some sites will not work at all.",
"Environment missing"}, vbExclamation,,, {"Process", "Cancel"}) = 1 Then Exit Sub "Environment missing"}, vbExclamation,,, {"Process", "Cancel"}) = 1 Then Exit Sub
If Not .GlobalPath.Value.PathWithSeparator = TXT_GLOBAL_PATH.Text.CSFilePS Or Not .CollectionsPath.Value = TXT_COLLECTIONS_PATH.Text Then
If Not Plugin.Hosts.SettingsHostCollection.UpdateHostPath_CheckDownloader Then Exit Sub
If MsgBoxE({"You have changed the global path or collections folder!" & vbCr & vbCr &
$"Global path ({IIf(.GlobalPath.Value.PathWithSeparator = TXT_GLOBAL_PATH.Text.CSFilePS, "not changed", "CHANGED")})" & vbCr &
$"Current: { .GlobalPath.Value}" & vbCr &
$"New: {TXT_GLOBAL_PATH.Text}" & vbCr & vbCr &
$"Collections folder ({IIf(.CollectionsPath.Value = TXT_COLLECTIONS_PATH.Text, "not changed", "CHANGED")})" & vbCr &
$"Current: { .CollectionsPath.Value}" & vbCr &
$"New: {TXT_COLLECTIONS_PATH.Text}" & vbCr & vbCr &
"Are you sure you want to continue?",
"Global path changed"}, vbExclamation,,, {"Process", "Cancel"}) = 0 Then
If Not Plugin.Hosts.SettingsHostCollection.UpdateHostPath(.GlobalPath, TXT_GLOBAL_PATH.Text.CSFileP,
.CollectionsPath, TXT_COLLECTIONS_PATH.Text) Then _
MsgBoxE({"Something went wrong while updating the global paths.", "Global path changed"}, vbCritical)
Else
Exit Sub
End If
End If
Dim detector As Func(Of IXMLValue, Boolean) = Function(hh) hh.ChangesDetected Dim detector As Func(Of IXMLValue, Boolean) = Function(hh) hh.ChangesDetected
.BeginUpdate() .BeginUpdate()
@@ -224,7 +249,7 @@ Namespace Editors
.ChannelsMaxJobsCount.Value = TXT_MAX_JOBS_CHANNELS.Value .ChannelsMaxJobsCount.Value = TXT_MAX_JOBS_CHANNELS.Value
.CheckUpdatesAtStart.Value = CH_CHECK_VER_START.Checked .CheckUpdatesAtStart.Value = CH_CHECK_VER_START.Checked
.UserAgent.Value = TXT_USER_AGENT.Text .UserAgent.Value = TXT_USER_AGENT.Text
DefaultUserAgent = TXT_USER_AGENT.Text UserAgentChanged = .UserAgent.ChangesDetected
.ImgurClientID.Value = TXT_IMGUR_CLIENT_ID.Text .ImgurClientID.Value = TXT_IMGUR_CLIENT_ID.Text
'Design 'Design
.ProgramText.Value = TXT_PRG_TITLE.Text .ProgramText.Value = TXT_PRG_TITLE.Text
@@ -309,6 +334,7 @@ Namespace Editors
.AddMissingErrorsToLog.Value = CH_ADD_MISSING_ERROS_TO_LOG.Checked .AddMissingErrorsToLog.Value = CH_ADD_MISSING_ERROS_TO_LOG.Checked
.ReparseMissingInTheRoutine.Value = CH_DOWN_REPARSE_MISSING.Checked .ReparseMissingInTheRoutine.Value = CH_DOWN_REPARSE_MISSING.Checked
.UseDefaultAccountIfMissing.Value = CH_USE_DEF_ACC.Checked .UseDefaultAccountIfMissing.Value = CH_USE_DEF_ACC.Checked
.AutomationBrushUndownloadedPlansMinutes.Value = TXT_AUTO_BRUSH_MIN.Value
'Downloading: file names 'Downloading: file names
If CH_FILE_NAME_CHANGE.Checked Then If CH_FILE_NAME_CHANGE.Checked Then
.FileReplaceNameByDate.Value = If(OPT_FILE_NAME_REPLACE.Checked, FileNameReplaceMode.Replace, FileNameReplaceMode.Add) .FileReplaceNameByDate.Value = If(OPT_FILE_NAME_REPLACE.Checked, FileNameReplaceMode.Replace, FileNameReplaceMode.Add)
@@ -337,9 +363,12 @@ Namespace Editors
COLORS_FEED.ColorsGet(.FeedBackColor, .FeedForeColor) COLORS_FEED.ColorsGet(.FeedBackColor, .FeedForeColor)
.FeedEndless.Value = CH_FEED_ENDLESS.Checked .FeedEndless.Value = CH_FEED_ENDLESS.Checked
.FeedAddSessionToCaption.Value = CH_FEED_ADD_SESSION.Checked .FeedAddSessionToCaption.Value = CH_FEED_ADD_SESSION.Checked
.FeedAddSiteToCaption.Value = CH_FEED_ADD_SITE.Checked
.FeedAddTypeToCaption.Value = CH_FEED_ADD_TYPE.Checked
.FeedAddDateToCaption.Value = CH_FEED_ADD_DATE.Checked .FeedAddDateToCaption.Value = CH_FEED_ADD_DATE.Checked
.FeedStoreSessionsData.Value = NUM_FEED_STORE_SESSION_DATA.Checked .FeedStoreSessionsData.Value = NUM_FEED_STORE_SESSION_DATA.Checked
.FeedStoredSessionsNumber.Value = NUM_FEED_STORE_SESSION_DATA.Value .FeedStoredSessionsNumber.Value = NUM_FEED_STORE_SESSION_DATA.Value
.FeedCurrentTryLoadLastSession.Value = NUM_FEED_SES_CURR_LOAD_LAST.Value
.FeedOpenLastMode.Value = CH_FEED_OPEN_LAST_MODE.Checked .FeedOpenLastMode.Value = CH_FEED_OPEN_LAST_MODE.Checked
.FeedShowFriendlyNames.Value = CH_FEED_SHOW_FRIENDLY.Checked .FeedShowFriendlyNames.Value = CH_FEED_SHOW_FRIENDLY.Checked
.FeedShowSpecialFeedsMediaItem.Value = CH_FEED_SHOW_SPEC_MEDIAITEM.Checked .FeedShowSpecialFeedsMediaItem.Value = CH_FEED_SHOW_SPEC_MEDIAITEM.Checked
@@ -403,6 +432,12 @@ Namespace Editors
Private Sub TXT_FEED_COLUMNS_ActionOnValueChanged(sender As Object, e As EventArgs) Handles TXT_FEED_COLUMNS.ActionOnValueChanged Private Sub TXT_FEED_COLUMNS_ActionOnValueChanged(sender As Object, e As EventArgs) Handles TXT_FEED_COLUMNS.ActionOnValueChanged
TXT_FEED_CENTER_IMAGE.Enabled = TXT_FEED_COLUMNS.Value = 1 TXT_FEED_CENTER_IMAGE.Enabled = TXT_FEED_COLUMNS.Value = 1
End Sub End Sub
Private Sub NUM_FEED_SES_CURR_LOAD_LAST_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles NUM_FEED_SES_CURR_LOAD_LAST.ActionOnButtonClick
Select Case e.DefaultButton
Case ADB.Clear : NUM_FEED_SES_CURR_LOAD_LAST.Value = -1
Case ADB.Refresh : NUM_FEED_SES_CURR_LOAD_LAST.Value = SettingsCLS.FeedCurrentLoadLastSessionDefault
End Select
End Sub
Private Sub EnvirPrograms_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_FFMPEG.ActionOnButtonClick, Private Sub EnvirPrograms_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_FFMPEG.ActionOnButtonClick,
TXT_CURL.ActionOnButtonClick, TXT_CURL.ActionOnButtonClick,
TXT_YTDLP.ActionOnButtonClick, TXT_YTDLP.ActionOnButtonClick,

View File

@@ -27,6 +27,7 @@ Friend Class LabelsForm
End Property End Property
Friend Property WithDeleteButton As Boolean = False Friend Property WithDeleteButton As Boolean = False
Private ReadOnly AddNoParsed As Boolean = False Private ReadOnly AddNoParsed As Boolean = False
Friend Property IsGroups As Boolean = False
Friend Sub New(ByVal LabelsArr As IEnumerable(Of String), Optional ByVal AddNoParsed As Boolean = True) Friend Sub New(ByVal LabelsArr As IEnumerable(Of String), Optional ByVal AddNoParsed As Boolean = True)
InitializeComponent() InitializeComponent()
Me.AddNoParsed = AddNoParsed Me.AddNoParsed = AddNoParsed
@@ -65,7 +66,15 @@ Friend Class LabelsForm
End Try End Try
End Sub End Sub
Private Sub LabelsForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown Private Sub LabelsForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If e.KeyCode = Keys.Insert And _Source Is Nothing Then AddNewLabel() : e.Handled = True Dim b As Boolean = True
If e.KeyCode = Keys.Insert And _Source Is Nothing Then
AddNewLabel()
ElseIf e.KeyCode = Keys.F3 And IsGroups Then
EditSelectedGroup()
Else
b = False
End If
If b Then e.Handled = True
End Sub End Sub
Private Sub LabelsForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed Private Sub LabelsForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
LabelsList.Clear() LabelsList.Clear()
@@ -101,4 +110,20 @@ Friend Class LabelsForm
End If End If
End If End If
End Sub End Sub
Private Sub EditSelectedGroup()
Try
If CMB_LABELS.Count > 0 And CMB_LABELS.SelectedIndex >= 0 Then
Dim gName$ = CMB_LABELS.Value
Dim i%
If Not gName.IsEmptyString Then
i = Settings.Groups.IndexOf(gName)
If i >= 0 Then
Using f As New DownloadObjects.Groups.GroupEditorForm(Settings.Groups(i)) : f.ShowDialog() : End Using
End If
End If
End If
Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Show group")
End Try
End Sub
End Class End Class

View File

@@ -7,6 +7,7 @@
' This program is distributed in the hope that it will be useful, ' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY ' but WITHOUT ANY WARRANTY
Imports SCrawler.Plugin Imports SCrawler.Plugin
Imports SCrawler.Plugin.Attributes
Imports SCrawler.Plugin.Hosts Imports SCrawler.Plugin.Hosts
Imports PersonalUtilities.Forms Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Controls Imports PersonalUtilities.Forms.Controls
@@ -15,12 +16,13 @@ Imports PersonalUtilities.Tools.Web.Cookies
Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons
Namespace Editors Namespace Editors
Friend Class SiteEditorForm Friend Class SiteEditorForm
Private ReadOnly LBL_AUTH As Label
Private ReadOnly LBL_OTHER As Label
Private WithEvents MyDefs As DefaultFormOptions Private WithEvents MyDefs As DefaultFormOptions
Private WithEvents SpecialButton As Button Private WithEvents SpecialButton As Button
Private Property Cookies As CookieKeeper Private Property Cookies As CookieKeeper
Private ReadOnly CookiesControlsInteraction As List(Of PropertyValueHost)
Private CookiesChanged As Boolean = False Private CookiesChanged As Boolean = False
Private Const OtherOptionsText As String = "Other Parameters"
Private ReadOnly LabelControls As List(Of Label)
#Region "Providers" #Region "Providers"
Private Class SavedPostsChecker : Inherits AccountsNameChecker Private Class SavedPostsChecker : Inherits AccountsNameChecker
Friend ReadOnly PathControl As TextBoxExtended Friend ReadOnly PathControl As TextBoxExtended
@@ -137,6 +139,108 @@ Namespace Editors
Return Nothing Return Nothing
End Function End Function
End Class End Class
#End Region
#Region "CatReorder"
Private Class CatReorder : Implements IDisposable
Private ReadOnly Items As Dictionary(Of String, List(Of PropertyValueHost))
Private Const EmptyCat As String = "----"
Friend Sub New()
Items = New Dictionary(Of String, List(Of PropertyValueHost))
End Sub
Friend ReadOnly Property Count As Integer
Get
Return Items.Count
End Get
End Property
Friend Sub Add(ByVal Item As PropertyValueHost)
Dim category$ = Item.Category.IfNullOrEmpty(EmptyCat)
If Items.ContainsKey(category) Then
Items(category).Add(Item)
Else
Items.Add(category, New List(Of PropertyValueHost) From {Item})
End If
End Sub
Friend Overloads Shared Sub AddToTable(ByRef Form As SiteEditorForm, ByVal cnt As Control, ByVal _height As Integer,
ByRef h As Integer, ByRef c As Integer)
With Form.TP_SITE_PROPS
.RowStyles.Add(New RowStyle(SizeType.Absolute, _height))
.RowCount += 1
.Controls.Add(cnt, 0, .RowStyles.Count - 1)
End With
h += _height
c += 1
End Sub
Friend Overloads Sub AddToTable(ByRef Form As SiteEditorForm, ByRef h As Integer, ByRef c As Integer, ByRef offset As Integer)
If Items.Count > 0 Then
Dim iCount% = Items.Count
Dim otherOptionsCat As KeyValuePair(Of String, List(Of PropertyValueHost)) = Nothing
Dim otherOptionsCatExists As Boolean = False
Dim AuthCat As KeyValuePair(Of String, List(Of PropertyValueHost)) = Nothing
Dim AuthCatExists As Boolean = False
If Items.Count > 1 Then
Dim catIndx% = Items.ListIndexOf(Function(cc) Not cc.Key.IsEmptyString AndAlso (cc.Key = EmptyCat Or cc.Key = OtherOptionsText))
If catIndx >= 0 Then
otherOptionsCat = New KeyValuePair(Of String, List(Of PropertyValueHost))(Items.Keys(catIndx), Items(Items.Keys(catIndx)))
otherOptionsCatExists = True
Items.Remove(otherOptionsCat.Key)
End If
catIndx = Items.ListIndexOf(Function(cc) Not cc.Key.IsEmptyString AndAlso (cc.Key = PropertyOption.CategoryAuth))
If catIndx >= 0 Then
AuthCat = New KeyValuePair(Of String, List(Of PropertyValueHost))(Items.Keys(catIndx), Items(Items.Keys(catIndx)))
AuthCatExists = True
Items.Remove(AuthCat.Key)
End If
End If
If AuthCatExists Then AddToTable(Form, iCount, AuthCat, h, c, offset)
For Each obj As KeyValuePair(Of String, List(Of PropertyValueHost)) In Items
AddToTable(Form, iCount, obj, h, c, offset)
Next
If otherOptionsCatExists Then AddToTable(Form, iCount, otherOptionsCat, h, c, offset)
End If
End Sub
Private Overloads Sub AddToTable(ByRef Form As SiteEditorForm, ByVal ItemsCount As Integer,
ByVal obj As KeyValuePair(Of String, List(Of PropertyValueHost)),
ByRef h As Integer, ByRef c As Integer, ByRef offset As Integer)
If ItemsCount > 1 And obj.Value.Count > 0 Then
Dim category$ = obj.Key.IfNullOrEmpty(OtherOptionsText)
If category = EmptyCat Then category = OtherOptionsText
Form.LabelControls.Add(New Label With {.Text = category,
.TextAlign = ContentAlignment.MiddleCenter,
.Dock = DockStyle.Fill})
AddToTable(Form, Form.LabelControls.Last, 25, h, c)
End If
If obj.Value.Count > 0 Then
For Each prop As PropertyValueHost In obj.Value
With prop
If .CookieValueExtractorExists Then Form.CookiesControlsInteraction.Add(prop)
.CreateControl(Form.TT_MAIN)
AddToTable(Form, .Control, .ControlHeight, h, c)
If .LeftOffset > offset Then offset = .LeftOffset
If Not .Options.AllowNull Or Not .ProviderFieldsChecker Is Nothing Then _
Form.MyDefs.MyFieldsCheckerE.AddControl(.Control, .Options.ControlText, .Type,
.Options.AllowNull, .ProviderFieldsChecker)
End With
Next
End If
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 And Items.Count > 0 Then Items.Clear()
disposedValue = True
End If
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub
Friend Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
#End Region #End Region
Private ReadOnly PropertyValid As Predicate(Of PropertyValueHost) = Function(p) (Not p.IsHidden Or SiteSettingsShowHiddenControls) And Not p.Options Is Nothing Private ReadOnly PropertyValid As Predicate(Of PropertyValueHost) = Function(p) (Not p.IsHidden Or SiteSettingsShowHiddenControls) And Not p.Options Is Nothing
Private ReadOnly Property Host As SettingsHost Private ReadOnly Property Host As SettingsHost
@@ -145,9 +249,9 @@ Namespace Editors
InitializeComponent() InitializeComponent()
MyDefs = New DefaultFormOptions(Me, Settings.Design) MyDefs = New DefaultFormOptions(Me, Settings.Design)
Host = h Host = h
CookiesControlsInteraction = New List(Of PropertyValueHost)
If Not Host.Responser Is Nothing Then Cookies = Host.Responser.Cookies.Copy If Not Host.Responser Is Nothing Then Cookies = Host.Responser.Cookies.Copy
LBL_AUTH = New Label With {.Text = "Authorization", .TextAlign = ContentAlignment.MiddleCenter, .Dock = DockStyle.Fill} LabelControls = New List(Of Label)
LBL_OTHER = New Label With {.Text = "Other Parameters", .TextAlign = ContentAlignment.MiddleCenter, .Dock = DockStyle.Fill}
Host.BeginEdit() Host.BeginEdit()
End Sub End Sub
Private Sub SiteEditorForm_Load(sender As Object, e As EventArgs) Handles Me.Load Private Sub SiteEditorForm_Load(sender As Object, e As EventArgs) Handles Me.Load
@@ -189,13 +293,6 @@ Namespace Editors
Dim offset% = PropertyValueHost.LeftOffsetDefault Dim offset% = PropertyValueHost.LeftOffsetDefault
Dim h% = 0, c% = 0 Dim h% = 0, c% = 0
Dim AddTpControl As Action(Of Control, Integer) = Sub(ByVal cnt As Control, ByVal _height As Integer)
TP_SITE_PROPS.RowStyles.Add(New RowStyle(SizeType.Absolute, _height))
TP_SITE_PROPS.RowCount += 1
TP_SITE_PROPS.Controls.Add(cnt, 0, TP_SITE_PROPS.RowStyles.Count - 1)
h += _height
c += 1
End Sub
If Host.Responser Is Nothing Then If Host.Responser Is Nothing Then
h -= 28 h -= 28
@@ -212,39 +309,17 @@ Namespace Editors
Dim laAdded As Boolean = False Dim laAdded As Boolean = False
Dim loAdded As Boolean = False Dim loAdded As Boolean = False
Dim pArr() As Boolean
If .PropList.Exists(Function(p) If(p.Options?.IsAuth, False)) Then pArr = {True, False} Else pArr = {False}
If .PropList.Exists(Function(p) p.ControlNumber >= 0) Then .PropList.Sort() If .PropList.Exists(Function(p) p.ControlNumber >= 0) Then .PropList.Sort()
For Each pAuth As Boolean In pArr Using pc As New CatReorder
For Each prop As PropertyValueHost In .PropList For Each prop As PropertyValueHost In .PropList
If PropertyValid.Invoke(prop) Then If PropertyValid.Invoke(prop) Then pc.Add(prop)
With prop
If .Options.IsAuth = pAuth Then
If pArr.Length = 2 Then
Select Case pAuth
Case True
If Not laAdded Then AddTpControl(LBL_AUTH, 25) : laAdded = True
Case False
If Not loAdded Then AddTpControl(LBL_OTHER, 25) : loAdded = True
End Select
End If
.CreateControl(TT_MAIN)
AddTpControl(.Control, .ControlHeight)
If .LeftOffset > offset Then offset = .LeftOffset
If Not .Options.AllowNull Or Not .ProviderFieldsChecker Is Nothing Then _
MyDefs.MyFieldsCheckerE.AddControl(.Control, .Options.ControlText, .Type,
.Options.AllowNull, .ProviderFieldsChecker)
End If
End With
End If
Next Next
Next If pc.Count > 0 Then pc.AddToTable(Me, h, c, offset)
End Using
End If End If
SpecialButton = .GetSettingsButtonInternal SpecialButton = .GetSettingsButtonInternal
If Not SpecialButton Is Nothing Then AddTpControl(SpecialButton, 28) If Not SpecialButton Is Nothing Then CatReorder.AddToTable(Me, SpecialButton, 28, h, c)
TP_SITE_PROPS.BaseControlsPadding = New Padding(offset, 0, 0, 0) TP_SITE_PROPS.BaseControlsPadding = New Padding(offset, 0, 0, 0)
offset += PaddingE.GetOf({TP_SITE_PROPS}).Left offset += PaddingE.GetOf({TP_SITE_PROPS}).Left
TXT_PATH.CaptionWidth = offset TXT_PATH.CaptionWidth = offset
@@ -285,8 +360,8 @@ Namespace Editors
Private Sub SiteEditorForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed Private Sub SiteEditorForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
If Host.PropList.Count > 0 Then Host.PropList.ForEach(Sub(p) p.DisposeControl()) If Host.PropList.Count > 0 Then Host.PropList.ForEach(Sub(p) p.DisposeControl())
If Not SpecialButton Is Nothing Then SpecialButton.Dispose() If Not SpecialButton Is Nothing Then SpecialButton.Dispose()
LBL_AUTH.Dispose() CookiesControlsInteraction.Clear()
LBL_OTHER.Dispose() LabelControls.ListClearDispose
Host.EndEdit() Host.EndEdit()
If Not Cookies Is Nothing Then Cookies.Dispose() If Not Cookies Is Nothing Then Cookies.Dispose()
End Sub End Sub
@@ -312,6 +387,13 @@ Namespace Editors
Next Next
End If End If
If TXT_PATH.Text.IsEmptyString Then TXT_PATH.Text = .PathGenerate.CSFilePS
If Not .Path.PathWithSeparator = TXT_PATH.Text Then
If Not SettingsHostCollection.UpdateHostPath_CheckDownloader Then Exit Sub
If Not SettingsHostCollection.UpdateHostPath(.Self, .Path, TXT_PATH.Text.CSFileP, True) Then _
MsgBoxE({"Something went wrong while updating the site path.", "Site path changed"}, vbCritical)
End If
SiteDefaultsFunctions.SetPropByChecker(TP_SITE_PROPS, Host) SiteDefaultsFunctions.SetPropByChecker(TP_SITE_PROPS, Host)
If TXT_PATH.IsEmptyString Then .Path = Nothing Else .Path = TXT_PATH.Text If TXT_PATH.IsEmptyString Then .Path = Nothing Else .Path = TXT_PATH.Text
.SavedPostsPath = TXT_PATH_SAVED_POSTS.Text .SavedPostsPath = TXT_PATH_SAVED_POSTS.Text
@@ -378,6 +460,7 @@ Namespace Editors
CookiesChanged = True CookiesChanged = True
f.GetCollection(Cookies) f.GetCollection(Cookies)
MyDefs.MyOkCancel.EnableOK = True MyDefs.MyOkCancel.EnableOK = True
If Cookies.ListExists And CookiesControlsInteraction.Count > 0 Then CookiesControlsInteraction.ForEach(Sub(c) c.GetValueFromCookies(Cookies))
End If End If
End Using End Using
SetCookieText() SetCookieText()

View File

@@ -313,7 +313,6 @@ Namespace Editors
BTT_START.Enabled = Not Working BTT_START.Enabled = Not Working
BTT_CANCEL.Enabled = Working BTT_CANCEL.Enabled = Working
End Sub, EDP.None) End Sub, EDP.None)
If Not Working Then MainFrameObj.UpdateLogButton()
Catch Catch
End Try End Try
End Sub End Sub

View File

@@ -131,7 +131,6 @@ Public Class MainFrame
Await .Automation.Start(True) Await .Automation.Start(True)
End With End With
UpdatePauseButtonsVisibility() UpdatePauseButtonsVisibility()
MainFrameObj.UpdateLogButton()
End Sub End Sub
Private _CloseInvoked As Boolean = False Private _CloseInvoked As Boolean = False
Private _IgnoreTrayOptions As Boolean = False Private _IgnoreTrayOptions As Boolean = False
@@ -325,9 +324,10 @@ CloseResume:
TrayIcon.Visible = .CloseToTray TrayIcon.Visible = .CloseToTray
If f.EnvironmentProgramsChanged Then Settings.UpdateEnvironmentPrograms() If f.EnvironmentProgramsChanged Then Settings.UpdateEnvironmentPrograms()
If f.FeedParametersChanged And Not MyFeed Is Nothing Then MyFeed.UpdateSettings() If f.FeedParametersChanged And Not MyFeed Is Nothing Then MyFeed.UpdateSettings()
If f.HeadersChanged Then If f.HeadersChanged Or (f.UserAgentChanged And Not Settings.UserAgent.IsEmptyString) Then
Settings.BeginUpdate() Settings.BeginUpdate()
Settings.Plugins.ForEach(Sub(p) p.Settings.UpdateInheritance()) If f.UserAgentChanged Then Settings.UpdatePluginsUserAgent(False)
If f.HeadersChanged Then Settings.Plugins.ForEach(Sub(p) p.Settings.UpdateInheritance())
Settings.EndUpdate() Settings.EndUpdate()
End If End If
UpdateSilentButtons() UpdateSilentButtons()
@@ -624,7 +624,6 @@ CloseResume:
End Using End Using
Catch ex As Exception Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[MainFrame.ShowGroups]") ErrorsDescriber.Execute(EDP.SendToLog, ex, "[MainFrame.ShowGroups]")
MainFrameObj.UpdateLogButton()
End Try End Try
End Sub End Sub
#End Region #End Region
@@ -651,7 +650,6 @@ CloseResume:
MainFrameObj.PauseButtons.UpdatePauseButtons() MainFrameObj.PauseButtons.UpdatePauseButtons()
Catch ex As Exception Catch ex As Exception
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Start automation") ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Start automation")
MainFrameObj.UpdateLogButton()
End Try End Try
End Sub End Sub
Private Sub BTT_DOWN_AUTOMATION_PAUSE_Click(sender As Object, e As EventArgs) Handles BTT_DOWN_AUTOMATION_PAUSE.Click, BTT_TRAY_PAUSE_AUTOMATION.Click Private Sub BTT_DOWN_AUTOMATION_PAUSE_Click(sender As Object, e As EventArgs) Handles BTT_DOWN_AUTOMATION_PAUSE.Click, BTT_TRAY_PAUSE_AUTOMATION.Click
@@ -781,6 +779,7 @@ CloseResume:
f.FilterViewMode = Settings.ViewMode f.FilterViewMode = Settings.ViewMode
f.FilterGroupUsers = Settings.GroupUsers f.FilterGroupUsers = Settings.GroupUsers
f.FilterShowGroupsInsteadLabels = Settings.ShowGroupsInsteadLabels f.FilterShowGroupsInsteadLabels = Settings.ShowGroupsInsteadLabels
f.FilterShowAllUsers = Settings.ShowAllUsers
f.Name = fName f.Name = fName
Settings.Groups.Add(f, isFilter, True) Settings.Groups.Add(f, isFilter, True)
MsgBoxE({$"The '{fName}' {IIf(isFilter, "filter", "group")} has been saved", $"Save {IIf(isFilter, "filter", "group")}"}) MsgBoxE({$"The '{fName}' {IIf(isFilter, "filter", "group")} has been saved", $"Save {IIf(isFilter, "filter", "group")}"})
@@ -825,8 +824,11 @@ CloseResume:
Settings.ViewMode.Value = .FilterViewMode Settings.ViewMode.Value = .FilterViewMode
Settings.GroupUsers.Value = .FilterGroupUsers Settings.GroupUsers.Value = .FilterGroupUsers
Settings.ShowGroupsInsteadLabels.Value = .FilterShowGroupsInsteadLabels Settings.ShowGroupsInsteadLabels.Value = .FilterShowGroupsInsteadLabels
Settings.ShowAllUsers.Value = .FilterShowAllUsers
End With End With
ApplyViewPattern(Settings.ViewMode.Value, True) ApplyViewPattern(Settings.ViewMode.Value, True)
Else
Settings.ShowAllUsers.Value = False
End If End If
Settings.AdvancedFilter.Copy(filter) Settings.AdvancedFilter.Copy(filter)
Settings.AdvancedFilter.UpdateFile() Settings.AdvancedFilter.UpdateFile()
@@ -2017,7 +2019,6 @@ ResumeDownloadingOperation:
End Sub End Sub
Private Sub Downloader_UpdateJobsCount(ByVal TotalCount As Integer) Private Sub Downloader_UpdateJobsCount(ByVal TotalCount As Integer)
ControlInvokeFast(Toolbar_BOTTOM, LBL_JOBS_COUNT, Sub() LBL_JOBS_COUNT.Text = IIf(TotalCount = 0, String.Empty, $"[Jobs {TotalCount}]")) ControlInvokeFast(Toolbar_BOTTOM, LBL_JOBS_COUNT, Sub() LBL_JOBS_COUNT.Text = IIf(TotalCount = 0, String.Empty, $"[Jobs {TotalCount}]"))
MainFrameObj.UpdateLogButton()
End Sub End Sub
Private Sub Downloader_Downloading(ByVal Value As Boolean) Private Sub Downloader_Downloading(ByVal Value As Boolean)
Dim __isDownloading As Boolean = Value Or Downloader.Working(False) Dim __isDownloading As Boolean = Value Or Downloader.Working(False)

View File

@@ -66,17 +66,17 @@ Friend Class MainFrameObjects : Implements INotificator
ControlInvokeFast(MF.TRAY_CONTEXT, Sub() MF.BTT_TRAY_CLOSE_NO_SCRIPT.Visible = ControlInvokeFast(MF.TRAY_CONTEXT, Sub() MF.BTT_TRAY_CLOSE_NO_SCRIPT.Visible =
Settings.ClosingCommand.Attribute And Not Settings.ClosingCommand.IsEmptyString) Settings.ClosingCommand.Attribute And Not Settings.ClosingCommand.IsEmptyString)
End Sub End Sub
Friend Sub UpdateLogButton() Private Sub UpdateLogButton()
MyMainLOG_UpdateLogButton(MF.BTT_LOG, MF.Toolbar_TOP) Try : MyMainLOG_UpdateLogButton(MF.BTT_LOG, MF.Toolbar_TOP) : Catch : End Try
End Sub End Sub
Friend Function GetUserListProvider(ByVal WithCollections As Boolean) As IFormatProvider Friend Function GetUserListProvider(ByVal WithCollections As Boolean) As IFormatProvider
Return MF.GetUserListProvider(WithCollections) Return MF.GetUserListProvider(WithCollections)
End Function End Function
Friend Sub ShowLog() Friend Sub ShowLog()
MyMainLOG_ShowForm(Settings.Design,,,, Sub() Try : MyMainLOG_ShowForm(Settings.Design,,,, Sub()
UpdateLogButton() UpdateLogButton()
LogFormClosed() LogFormClosed()
End Sub) End Sub) : Catch : End Try
End Sub End Sub
#End Region #End Region
#Region "Notifications" #Region "Notifications"

View File

@@ -77,10 +77,15 @@ Friend Module MainMod
''' <summary>Alt+F1</summary> ''' <summary>Alt+F1</summary>
Friend ReadOnly ShowUsersButtonKey As New PersonalUtilities.Forms.ButtonKey(Keys.F1,, True) Friend ReadOnly ShowUsersButtonKey As New PersonalUtilities.Forms.ButtonKey(Keys.F1,, True)
Friend ReadOnly DateTimeDefaultProvider As New ADateTime(ADateTime.Formats.BaseDateTime) Friend ReadOnly DateTimeDefaultProvider As New ADateTime(ADateTime.Formats.BaseDateTime)
<Extension> Friend Function ToStringDateDef(ByVal _DateN As Date?) As String
Return If(_DateN.HasValue, AConvert(Of String)(_DateN, DateTimeDefaultProvider, String.Empty), String.Empty)
End Function
<Extension> Friend Function ToStringDateDef(ByVal _Date As Date) As String
Return ToStringDateDef(_DateN:=_Date)
End Function
Friend ReadOnly SessionDateTimeProvider As New ADateTime("yyyyMMdd_HHmmss") Friend ReadOnly SessionDateTimeProvider As New ADateTime("yyyyMMdd_HHmmss")
Friend ReadOnly FeedVideoLengthProvider As New ADateTime("hh\:mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan} Friend ReadOnly FeedVideoLengthProvider As New ADateTime("hh\:mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan}
Friend ReadOnly LogConnector As New LogHost Friend ReadOnly LogConnector As New LogHost
Friend DefaultUserAgent As String = String.Empty
Friend SiteSettingsShowHiddenControls As Boolean = False Friend SiteSettingsShowHiddenControls As Boolean = False
#Region "NonExistingUsersLog" #Region "NonExistingUsersLog"
Friend ReadOnly NonExistingUsersLog As New TextSaver($"LOGs\NonExistingUsers.txt") With {.LogMode = True, .AutoSave = True} Friend ReadOnly NonExistingUsersLog As New TextSaver($"LOGs\NonExistingUsers.txt") With {.LogMode = True, .AutoSave = True}

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