Compare commits
9 Commits
2024.4.26.
...
2024.6.10.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aef4ce1c8f | ||
|
|
93ea2a55ac | ||
|
|
2ae8c3acfc | ||
|
|
53dcb3e2c6 | ||
|
|
ca384e54d6 | ||
|
|
5a1b5c828a | ||
|
|
22c59b41f0 | ||
|
|
444b3521eb | ||
|
|
ec2266f1bf |
99
Changelog.md
@@ -1,3 +1,102 @@
|
||||
# 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*
|
||||
|
||||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 25 KiB |
10
README.md
@@ -1,5 +1,5 @@
|
||||
<!-- # :rainbow_flag: Happy LGBT Pride Month :tada:
|
||||
-->
|
||||
# 🏳️🌈 Happy LGBT Pride Month 🎉
|
||||
|
||||
# 🏳️🌈 Social networks crawler 🏳️🌈
|
||||
|
||||
[](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;
|
||||
- Reddit images, galleries of images, videos, saved posts;
|
||||
- Redgifs videos (https://www.redgifs.com/);
|
||||
- Twitter images and videos, saved (bookmarked) posts;
|
||||
- OnlyFans images and videos, saved (bookmarked) posts;
|
||||
- Twitter images and videos, saved (bookmarked) posts, likes, communities;
|
||||
- OnlyFans images and videos, saved (bookmarked) posts, stories;
|
||||
- JustForFans images and videos, saved (bookmarked) posts;
|
||||
- Mastodon images and videos, saved (bookmarked) 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**
|
||||
- **Twitter**
|
||||
- **OnlyFans** *(partial support)*[^1]
|
||||
- **Mastodon**
|
||||
- **Instagram**
|
||||
- **Threads**
|
||||
- **Facebook**
|
||||
- JustForFans *(partial support)*[^1]
|
||||
- Mastodon *(out of support)*
|
||||
- TikTok
|
||||
- RedGifs
|
||||
- Pinterest
|
||||
|
||||
@@ -36,8 +36,22 @@ Namespace Plugin.Attributes
|
||||
Public Property IsInformationLabel As Boolean = False
|
||||
''' <summary>Label text alignment.<br/>Default: <see cref="Drawing.ContentAlignment.TopCenter"/></summary>
|
||||
Public Property LabelTextAlign As Drawing.ContentAlignment = Drawing.ContentAlignment.TopCenter
|
||||
Private _IsAuth As Boolean = False
|
||||
''' <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 InheritanceName As String = Nothing
|
||||
''' <summary>Initialize a new property option attribute</summary>
|
||||
|
||||
@@ -19,6 +19,7 @@ Namespace Plugin
|
||||
ReadOnly Property Site As String
|
||||
Property CMDEncoding As String
|
||||
Property EnvironmentPrograms As IEnumerable(Of String)
|
||||
Property UserAgentDefault As String
|
||||
Sub EnvironmentProgramsUpdated()
|
||||
Property AccountName As String
|
||||
Property Temporary As Boolean
|
||||
|
||||
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
|
||||
' by using the '*' as shown below:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("2024.4.13.0")>
|
||||
<Assembly: AssemblyFileVersion("2024.4.13.0")>
|
||||
<Assembly: AssemblyVersion("2024.5.18.0")>
|
||||
<Assembly: AssemblyFileVersion("2024.5.18.0")>
|
||||
<Assembly: NeutralResourcesLanguage("en")>
|
||||
|
||||
@@ -78,6 +78,12 @@ Namespace API.YouTube.Base
|
||||
https = 1
|
||||
m3u8 = 2
|
||||
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 Type As Plugin.UserMediaTypes
|
||||
Public ID As String
|
||||
|
||||
@@ -22,6 +22,7 @@ Namespace API.YouTube.Base
|
||||
End Sub
|
||||
Public Shared Function StandardizeURL(ByVal URL As String) As String
|
||||
Try
|
||||
URL = URL.StringTrim
|
||||
Dim isMusic As Boolean = False, isShorts As Boolean = False
|
||||
If Info_GetUrlType(URL, isMusic, isShorts) = YouTubeMediaType.Single Then
|
||||
If Not isMusic And Not isShorts Then
|
||||
@@ -45,6 +46,7 @@ Namespace API.YouTube.Base
|
||||
End Function
|
||||
Public Shared Function StandardizeURL_Channel(ByVal URL As String, Optional ByVal Process As Boolean = True) As String
|
||||
Try
|
||||
URL = URL.StringTrim
|
||||
Dim ct As YouTubeChannelTab = YouTubeChannelTab.All
|
||||
Dim isMusic As Boolean = False
|
||||
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,
|
||||
Optional ByRef IsChannelUser As Boolean = False, Optional ByRef Id As String = Nothing,
|
||||
Optional ByRef ChannelOptions As YouTubeChannelTab = YouTubeChannelTab.All) As YouTubeMediaType
|
||||
URL = URL.StringTrim
|
||||
If Not URL.IsEmptyString Then
|
||||
IsMusic = URL.Contains("music.youtube.com")
|
||||
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 DateAfter As Date? = Nothing, Optional ByVal DateBefore As Date? = Nothing,
|
||||
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 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
|
||||
@@ -162,7 +166,7 @@ Namespace API.YouTube.Base
|
||||
|
||||
If result Then
|
||||
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
|
||||
container.Dispose()
|
||||
End If
|
||||
|
||||
@@ -162,6 +162,12 @@ Namespace API.YouTube.Base
|
||||
<Browsable(True), GridVisible, XMLVN({"Info"}), Category("Info"), DisplayName("Create description files"),
|
||||
Description("Create video description files. Default: false.")>
|
||||
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)"),
|
||||
Description("Create video thumbnail files. Default: true.")>
|
||||
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"),
|
||||
Description("Add some additional info to the program info if you need")>
|
||||
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
|
||||
#Region "Defaults ChannelsDownload"
|
||||
<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'")
|
||||
End Function
|
||||
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
|
||||
#Region "Defaults Audio"
|
||||
<Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, "AAC"), Category("Defaults Audio"), DisplayName("Default codec"),
|
||||
|
||||
23
SCrawler.YouTube/Controls/ButtonRC.vb
Normal 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
|
||||
@@ -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 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 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
|
||||
|
||||
Dim sv% = m.Size / 1024
|
||||
|
||||
@@ -65,11 +65,11 @@ Namespace API.YouTube.Controls
|
||||
Me.LBL_TIME = New System.Windows.Forms.Label()
|
||||
Me.LBL_URL = New System.Windows.Forms.LinkLabel()
|
||||
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_CANCEL = New System.Windows.Forms.Button()
|
||||
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_AUDIO = New System.Windows.Forms.RadioButton()
|
||||
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_EXTRA_AUDIO_FORMATS As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||
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_CANCEL As Button
|
||||
Private WithEvents TP_HEADER_INFO_2 As TableLayoutPanel
|
||||
Private WithEvents TXT_FPS As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||
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
|
||||
End Class
|
||||
End Namespace
|
||||
@@ -121,7 +121,7 @@ Namespace API.YouTube.Controls
|
||||
img = ImageRenderer.GetImage(SFile.GetBytesFromNet(imgUrl, EDP.ReturnValue), EDP.ReturnValue)
|
||||
If Not img Is Nothing Then ICON_VIDEO.Image = img : ICON_VIDEO.InitialImage = img
|
||||
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)
|
||||
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()
|
||||
@@ -610,7 +610,7 @@ Namespace API.YouTube.Controls
|
||||
$"Video|{AvailableVideoFormats.Select(Function(vf) $"*.{vf.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.Extension = ext
|
||||
If Not f.IsEmptyString Then f.Extension = ext
|
||||
End If
|
||||
#Enable Warning
|
||||
f = CleanFileName(f)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
'
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Imports System.Runtime.CompilerServices
|
||||
Imports PersonalUtilities.Tools
|
||||
Imports PersonalUtilities.Forms.Toolbars
|
||||
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 ProgressProvider As IMyProgressNumberProvider = MyProgressNumberProvider.Percentage
|
||||
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
|
||||
If Not f.IsEmptyString And Not f.Name.IsEmptyString Then
|
||||
Dim ff As SFile = f
|
||||
ff.Name = ff.Name.StringRemoveWinForbiddenSymbols
|
||||
If Not ff.Name.IsEmptyString Then ff.Name = ff.Name.Replace("%", String.Empty)
|
||||
ff.Name = ff.Name.StringRemoveWinForbiddenSymbols.StringTrim
|
||||
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"
|
||||
Return ff
|
||||
Else
|
||||
|
||||
@@ -133,18 +133,25 @@ Namespace DownloadObjects.STDownloader
|
||||
|
||||
ICON_SITE.Image = .SiteIcon
|
||||
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
|
||||
LBL_INFO.Text = .File.Extension.StringToUpper
|
||||
ElseIf Not .IsMusic And Not (.MediaType = Plugin.UserMediaTypes.Audio Or .MediaType = Plugin.UserMediaTypes.AudioPre) Then
|
||||
If .Height > 0 Then
|
||||
LBL_INFO.Text = $"{ .File.Extension.StringToUpper}{d}{ .Height}p"
|
||||
If h > 0 Then
|
||||
LBL_INFO.Text = $"{ .File.Extension.StringToUpper}{d}{h}p"
|
||||
Else
|
||||
LBL_INFO.Text = .File.Extension.StringToUpper
|
||||
End If
|
||||
Else
|
||||
If .Bitrate > 0 Then
|
||||
LBL_INFO.Text = $"{ .File.Extension.StringToUpper}{d}{ .Bitrate}k"
|
||||
If b > 0 Then
|
||||
LBL_INFO.Text = $"{ .File.Extension.StringToUpper}{d}{b}k"
|
||||
Else
|
||||
LBL_INFO.Text = .File.Extension.StringToUpper
|
||||
End If
|
||||
@@ -221,7 +228,7 @@ Namespace DownloadObjects.STDownloader
|
||||
t = 0
|
||||
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
|
||||
|
||||
|
||||
@@ -57,6 +57,12 @@ Namespace DownloadObjects.STDownloader
|
||||
End If
|
||||
MyNotificator = New YTNotificator(Me)
|
||||
MyDownloaderSettings = MyYouTubeSettings
|
||||
ProgramLogInitialize()
|
||||
With ProgramLog
|
||||
AddHandler .TextAdded, AddressOf ProgramLog_TextAdded
|
||||
AddHandler .TextCleared, AddressOf ProgramLog_TextCleared
|
||||
End With
|
||||
UpdateLogButton()
|
||||
End If
|
||||
|
||||
With MyView : .Import() : .SetFormSize() : End With
|
||||
@@ -157,7 +163,7 @@ Namespace DownloadObjects.STDownloader
|
||||
If PerformClick Then cnt.PerformClick()
|
||||
If Not DisableDownload And MyDownloaderSettings.DownloadAutomatically Then AddToDownload(cnt, True)
|
||||
End With
|
||||
End Sub, EDP.None)
|
||||
End Sub, EDP.SendToLog)
|
||||
End Sub
|
||||
#Region "Controls rendering"
|
||||
Private Overloads Sub OffsetControls()
|
||||
@@ -247,7 +253,7 @@ Namespace DownloadObjects.STDownloader
|
||||
Dim useCookiesParse As Boolean? = Nothing
|
||||
If useCookies Then useCookiesParse = True
|
||||
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 url$ = String.Empty
|
||||
@@ -449,12 +455,26 @@ Namespace DownloadObjects.STDownloader
|
||||
End Try
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "LOG"
|
||||
Private Sub BTT_LOG_Click(sender As Object, e As EventArgs) Handles BTT_LOG.Click
|
||||
MyMainLOG_ShowForm(DesignXML,,,, AddressOf UpdateLogButton)
|
||||
End Sub
|
||||
Friend Sub UpdateLogButton()
|
||||
If AppMode Then MyMainLOG_UpdateLogButton(BTT_LOG, TOOLBAR_TOP)
|
||||
Private Sub UpdateLogButton()
|
||||
If AppMode Then
|
||||
Try : MyMainLOG_UpdateLogButton(BTT_LOG, TOOLBAR_TOP) : Catch : End Try
|
||||
End If
|
||||
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
|
||||
Try
|
||||
With MyYouTubeSettings
|
||||
|
||||
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
|
||||
' by using the '*' as shown below:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("2024.4.14.0")>
|
||||
<Assembly: AssemblyFileVersion("2024.4.14.0")>
|
||||
<Assembly: AssemblyVersion("2024.6.10.0")>
|
||||
<Assembly: AssemblyFileVersion("2024.6.10.0")>
|
||||
<Assembly: NeutralResourcesLanguage("en")>
|
||||
|
||||
@@ -267,12 +267,11 @@ Namespace API.YouTube.Objects
|
||||
<XMLEC(CollectionMode:=CollectionModes.String)>
|
||||
Friend ReadOnly Property PostProcessing_OutputAudioFormats As List(Of String)
|
||||
Friend Sub PostProcessing_OutputAudioFormats_Reset()
|
||||
PostProcessing_OutputAudioFormats.Clear()
|
||||
PostProcessing_OutputAudioFormats.ListAddList(MyYouTubeSettings.DefaultAudioCodecAddit)
|
||||
If PostProcessing_OutputAudioFormats.Count > 0 Then
|
||||
PostProcessing_OutputAudioFormats.Sort()
|
||||
PostProcessing_OutputAudioFormats.RemoveAll(Function(s) s = -1)
|
||||
End If
|
||||
With PostProcessing_OutputAudioFormats
|
||||
.Clear()
|
||||
.ListAddList(MyYouTubeSettings.DefaultAudioCodecAddit)
|
||||
If .Count > 0 Then .Sort()
|
||||
End With
|
||||
End Sub
|
||||
<XMLEC("OutputAudioBitrate")> Protected _OutputAudioBitrate As Integer = -1
|
||||
Friend Property OutputAudioBitrate As Integer
|
||||
@@ -322,21 +321,19 @@ Namespace API.YouTube.Objects
|
||||
<XMLEC(CollectionMode:=CollectionModes.String)>
|
||||
Friend ReadOnly Property PostProcessing_OutputSubtitlesFormats As List(Of String)
|
||||
Friend Sub PostProcessing_OutputSubtitlesFormats_Reset()
|
||||
PostProcessing_OutputSubtitlesFormats.Clear()
|
||||
PostProcessing_OutputSubtitlesFormats.ListAddList(MyYouTubeSettings.DefaultSubtitlesFormatAddit)
|
||||
If PostProcessing_OutputSubtitlesFormats.Count > 0 Then
|
||||
PostProcessing_OutputSubtitlesFormats.Sort()
|
||||
PostProcessing_OutputSubtitlesFormats.RemoveAll(Function(s) s = -1)
|
||||
End If
|
||||
With PostProcessing_OutputSubtitlesFormats
|
||||
.Clear()
|
||||
.ListAddList(MyYouTubeSettings.DefaultSubtitlesFormatAddit)
|
||||
If .Count > 0 Then .Sort()
|
||||
End With
|
||||
End Sub
|
||||
Friend Sub SubtitlesSelectedIndexesReset()
|
||||
SubtitlesSelectedIndexes.Clear()
|
||||
Dim subs As List(Of Subtitles) = Subtitles
|
||||
SubtitlesSelectedIndexes.ListAddList(MyYouTubeSettings.DefaultSubtitles.Select(Function(s) subs.FindIndex(Function(ss) ss.ID = s)))
|
||||
If SubtitlesSelectedIndexes.Count > 0 Then
|
||||
SubtitlesSelectedIndexes.Sort()
|
||||
SubtitlesSelectedIndexes.RemoveAll(Function(s) s = -1)
|
||||
End If
|
||||
With SubtitlesSelectedIndexes
|
||||
.Clear()
|
||||
Dim subs As List(Of Subtitles) = Subtitles
|
||||
.ListAddList(MyYouTubeSettings.DefaultSubtitles.Select(Function(s) subs.FindIndex(Function(ss) ss.ID = s)))
|
||||
If .Count > 0 Then .Sort() : .RemoveAll(Function(s) s = -1)
|
||||
End With
|
||||
End Sub
|
||||
Private Sub SetElementsSubtitles(ByVal Source As YouTubeMediaContainerBase)
|
||||
If Not Source Is Nothing And HasElements Then
|
||||
@@ -442,6 +439,19 @@ Namespace API.YouTube.Objects
|
||||
End Get
|
||||
End Property
|
||||
<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
|
||||
<XMLEC> Public Overridable Property Bitrate As Integer Implements IYouTubeMediaContainer.Bitrate
|
||||
Get
|
||||
@@ -459,6 +469,20 @@ Namespace API.YouTube.Objects
|
||||
Me._Bitrate = _Bitrate
|
||||
End Set
|
||||
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 DateAdded As Date Implements IYouTubeMediaContainer.DateAdded
|
||||
Private Property IUserMedia_PostDate As Date? Implements IUserMedia.PostDate
|
||||
@@ -656,6 +680,15 @@ Namespace API.YouTube.Objects
|
||||
End If
|
||||
End Set
|
||||
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
|
||||
Private Property IUserMedia_File As String Implements IUserMedia.File
|
||||
Get
|
||||
@@ -966,7 +999,7 @@ Namespace API.YouTube.Objects
|
||||
.Visible = True
|
||||
.Value = 0
|
||||
.Maximum = DownloadGetElemCountSingle()
|
||||
.Information = $"Download {ObjectType}"
|
||||
.Information = "Downloading"
|
||||
End With
|
||||
End If
|
||||
|
||||
@@ -1111,7 +1144,7 @@ Namespace API.YouTube.Objects
|
||||
.Value = 0
|
||||
.Maximum = 100
|
||||
.Provider = ProgressProvider
|
||||
.Information = $"Download {MediaType}"
|
||||
.Information = "Downloading"
|
||||
End With
|
||||
End If
|
||||
.MainProcessName = MyYouTubeSettings.YTDLP.Name '"yt-dlp"
|
||||
@@ -1143,12 +1176,22 @@ Namespace API.YouTube.Objects
|
||||
If fileUrl.Exists Then AddFile(fileUrl)
|
||||
End If
|
||||
|
||||
If MyYouTubeSettings.CreateDescriptionFiles And Not Description.IsEmptyString Then
|
||||
Dim fileDesr As SFile = File
|
||||
fileDesr.Extension = "txt"
|
||||
TextSaver.SaveTextToFile(Description, fileDesr,,, EDP.None)
|
||||
If fileDesr.Exists Then AddFile(fileDesr)
|
||||
End If
|
||||
With MyYouTubeSettings
|
||||
If .CreateDescriptionFiles And (Not Description.IsEmptyString Or
|
||||
(.CreateDescriptionFiles_CreateWithNoDescription And .CreateDescriptionFiles_AddUploadDate)) Then
|
||||
Dim fileDesr As SFile = File
|
||||
fileDesr.Extension = "txt"
|
||||
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 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 _
|
||||
embedThumbTo.Invoke(f) : mp3ThumbEmbedded = True
|
||||
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
|
||||
Next
|
||||
End If
|
||||
@@ -1534,7 +1578,7 @@ Namespace API.YouTube.Objects
|
||||
ID = .Value("id")
|
||||
Title = TitleHtmlConverter.Invoke(.Value("title"))
|
||||
Description = .Value("description")
|
||||
URL = .Value("webpage_url")
|
||||
URL = .Value("webpage_url").ToMusicUrl(IsMusic)
|
||||
|
||||
PlaylistID = .Value("playlist_id")
|
||||
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)
|
||||
End If
|
||||
DateAdded = AConvert(Of Date)(.Value("release_date").IfNullOrEmpty(.Value("upload_date")), DateAddedProvider, New Date)
|
||||
If Not IsMusic Then FileDateUpdate()
|
||||
|
||||
ParseFormats(.Self)
|
||||
|
||||
|
||||
@@ -115,6 +115,9 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Attributes\GridVisibleAttribute.vb" />
|
||||
<Compile Include="Base\TableControlsProcessor.vb" />
|
||||
<Compile Include="Controls\ButtonRC.vb">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ChannelTabsChooserForm.Designer.vb">
|
||||
<DependentUpon>ChannelTabsChooserForm.vb</DependentUpon>
|
||||
</Compile>
|
||||
|
||||
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
|
||||
' by using the '*' as shown below:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("2024.4.14.0")>
|
||||
<Assembly: AssemblyFileVersion("2024.4.14.0")>
|
||||
<Assembly: AssemblyVersion("2024.6.10.0")>
|
||||
<Assembly: AssemblyFileVersion("2024.6.10.0")>
|
||||
<Assembly: NeutralResourcesLanguage("en")>
|
||||
|
||||
@@ -11,6 +11,9 @@ Namespace API.Base
|
||||
Friend Const Header_Authorization As String = "authorization"
|
||||
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 ConcurrentDownloadsToolTip As String = "The number of concurrent downloads."
|
||||
Friend Const SavedPostsUserNameCaption As String = "Saved posts user"
|
||||
|
||||
@@ -77,7 +77,7 @@ Namespace API.Base
|
||||
''' </summary>
|
||||
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 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
|
||||
Sub OpenFolder()
|
||||
Property DownloadTopCount As Integer?
|
||||
|
||||
@@ -54,9 +54,8 @@ Namespace API.Base
|
||||
Dim aStr$ = String.Empty
|
||||
If Count > 1 Then aStr = $" ({Number}/{Count})"
|
||||
Try
|
||||
If Host.Source.ReadyToDownload(PDownload.SavedPosts) Then
|
||||
If Host.Available(PDownload.SavedPosts, Multiple Or Count > 1) Then
|
||||
Host.DownloadStarted(PDownload.SavedPosts)
|
||||
If Host.Available(PDownload.SavedPosts, Multiple Or Count > 1) Then
|
||||
If Host.Source.ReadyToDownload(PDownload.SavedPosts) Then
|
||||
If Count > 1 Then Progress.Information = $"{Host.Name} - {Host.AccountName.IfNullOrEmpty(SettingsHost.NameAccountNameDefault)}"
|
||||
Using user As IUserData = Host.GetInstance(PDownload.SavedPosts, Nothing, False, False)
|
||||
If Not user Is Nothing Then
|
||||
@@ -83,11 +82,11 @@ Namespace API.Base
|
||||
End Using
|
||||
Else
|
||||
_Unavailable += 1
|
||||
Progress.InformationTemporary = $"Host [{Host.Name}{aStr}] is unavailable"
|
||||
Progress.InformationTemporary = $"Host [{Host.Name}{aStr}] is not ready"
|
||||
End If
|
||||
Else
|
||||
_NotReady += 1
|
||||
Progress.InformationTemporary = $"Host [{Host.Name}{aStr}] is not ready"
|
||||
Progress.InformationTemporary = $"Host [{Host.Name}{aStr}] is unavailable"
|
||||
End If
|
||||
Catch oex As OperationCanceledException When Token.IsCancellationRequested
|
||||
_ErrorCount += 1
|
||||
@@ -96,9 +95,6 @@ Namespace API.Base
|
||||
_ErrorCount += 1
|
||||
Progress.InformationTemporary = $"{Host.Name}{aStr} downloading error"
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, $"[API.Base.ProfileSaved.Download({Host.Key}{aStr})]")
|
||||
Finally
|
||||
Host.DownloadDone(PDownload.SavedPosts)
|
||||
MainFrameObj.UpdateLogButton()
|
||||
End Try
|
||||
End Sub
|
||||
End Class
|
||||
|
||||
@@ -34,6 +34,16 @@ Namespace API.Base
|
||||
Friend Property AccountName As String Implements ISiteSettings.AccountName
|
||||
Friend Property Temporary As Boolean = False Implements ISiteSettings.Temporary
|
||||
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 _SubscriptionsAllowed As Boolean = False
|
||||
Friend ReadOnly Property SubscriptionsAllowed As Boolean Implements ISiteSettings.SubscriptionsAllowed
|
||||
@@ -138,7 +148,6 @@ Namespace API.Base
|
||||
Friend Overridable Sub BeginInit() Implements ISiteSettings.BeginInit
|
||||
End Sub
|
||||
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)
|
||||
End Sub
|
||||
#End Region
|
||||
|
||||
@@ -143,7 +143,7 @@ Namespace API.Base
|
||||
Protected Const Name_UserID As String = "UserID"
|
||||
Protected Const Name_Options As String = "Options"
|
||||
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_Temporary As String = "Temporary"
|
||||
Private Const Name_Favorite As String = "Favorite"
|
||||
@@ -950,7 +950,10 @@ BlockNullPicture:
|
||||
LogError(ex, "user information loading error")
|
||||
End Try
|
||||
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
|
||||
UpdateDataFiles()
|
||||
MyFileSettings.Exists(SFO.Path)
|
||||
@@ -1001,7 +1004,7 @@ BlockNullPicture:
|
||||
|
||||
x.Save(MyFileSettings)
|
||||
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
|
||||
LogError(ex, "user information saving error")
|
||||
End Try
|
||||
@@ -1934,7 +1937,18 @@ BlockNullPicture:
|
||||
Return 0
|
||||
End If
|
||||
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 Removed As Boolean = True
|
||||
Dim _TurnBack As Boolean = False
|
||||
@@ -1950,6 +1964,7 @@ BlockNullPicture:
|
||||
User.SpecialCollectionPath = String.Empty
|
||||
User.UserModel = UsageModel.Default
|
||||
User.CollectionModel = UsageModel.Default
|
||||
If NewUser.HasValue Then User.SpecialPath = NewUser.Value.UserNew.SpecialPath
|
||||
Else
|
||||
Settings.Users.Remove(Me)
|
||||
Removed = True
|
||||
|
||||
28
SCrawler/API/BaseObjects/SplitCollectionUserInfo.vb
Normal 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
|
||||
111
SCrawler/API/BaseObjects/SplitCollectionUserInfoChangePathsForm.Designer.vb
generated
Normal 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
|
||||
@@ -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>
|
||||
@@ -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
|
||||
134
SCrawler/API/BaseObjects/SplitCollectionUserInfoPathForm.Designer.vb
generated
Normal 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
|
||||
154
SCrawler/API/BaseObjects/SplitCollectionUserInfoPathForm.resx
Normal 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>
|
||||
68
SCrawler/API/BaseObjects/SplitCollectionUserInfoPathForm.vb
Normal 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
|
||||
@@ -11,6 +11,7 @@ Imports SCrawler.Plugin
|
||||
Imports SCrawler.Plugin.Attributes
|
||||
Imports PersonalUtilities.Tools.Web.Clients
|
||||
Imports PersonalUtilities.Functions.RegularExpressions
|
||||
Imports DN = SCrawler.API.Base.DeclaredNames
|
||||
Namespace API.Facebook
|
||||
<Manifest("AndyProgram_Facebook"), SavedPosts, SeparatedTasks(1), SpecialForm(False)>
|
||||
Friend Class SiteSettings : Inherits ThreadsNet.SiteSettings
|
||||
@@ -31,11 +32,11 @@ Namespace API.Facebook
|
||||
End Property
|
||||
#End Region
|
||||
#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
|
||||
<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
|
||||
<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
|
||||
#End Region
|
||||
#End Region
|
||||
|
||||
@@ -14,6 +14,7 @@ Imports PersonalUtilities.Functions.RegularExpressions
|
||||
Imports PersonalUtilities.Tools.Web.Clients
|
||||
Imports PersonalUtilities.Tools.Web.Cookies
|
||||
Imports Download = SCrawler.Plugin.ISiteSettings.Download
|
||||
Imports DN = SCrawler.API.Base.DeclaredNames
|
||||
Namespace API.Instagram
|
||||
<Manifest(InstagramSiteKey), SeparatedTasks(1), SavedPosts, SpecialForm(False)>
|
||||
Friend Class SiteSettings : Inherits SiteSettingsBase
|
||||
@@ -54,6 +55,9 @@ Namespace API.Instagram
|
||||
End Function
|
||||
End Class
|
||||
#End Region
|
||||
#Region "Categories"
|
||||
Private Const CAT_DOWN As String = "Download data"
|
||||
#End Region
|
||||
#Region "Authorization properties"
|
||||
Friend Const Header_IG_APP_ID As String = "x-ig-app-id"
|
||||
Friend Const Header_IG_WWW_CLAIM As String = "x-ig-www-claim"
|
||||
@@ -143,10 +147,19 @@ Namespace API.Instagram
|
||||
Friend ReadOnly Property USE_GQL As PropertyValue
|
||||
#End Region
|
||||
#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."
|
||||
<PropertyOption(ControlText:="Request timer (any)",
|
||||
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>
|
||||
Friend ReadOnly Property RequestsWaitTimer_Any As PropertyValue
|
||||
<Provider(NameOf(RequestsWaitTimer_Any), FieldsChecker:=True)>
|
||||
@@ -154,33 +167,33 @@ Namespace API.Instagram
|
||||
<PropertyOption(ControlText:="Request timer",
|
||||
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,
|
||||
AllowNull:=False), PXML, ControlNumber(20), PClonable>
|
||||
AllowNull:=False, Category:=DN.CAT_Timers), PXML, ControlNumber(20), PClonable>
|
||||
Friend ReadOnly Property RequestsWaitTimer As PropertyValue
|
||||
<Provider(NameOf(RequestsWaitTimer), FieldsChecker:=True)>
|
||||
Private ReadOnly Property RequestsWaitTimerProvider As IFormatProvider
|
||||
<PropertyOption(ControlText:="Request timer counter",
|
||||
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,
|
||||
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
|
||||
<Provider(NameOf(RequestsWaitTimerTaskCount), FieldsChecker:=True)>
|
||||
Private ReadOnly Property RequestsWaitTimerTaskCountProvider As IFormatProvider
|
||||
<PropertyOption(ControlText:="Posts limit timer",
|
||||
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,
|
||||
AllowNull:=False), PXML, ControlNumber(22), PClonable>
|
||||
AllowNull:=False, Category:=DN.CAT_Timers), PXML, ControlNumber(22), PClonable>
|
||||
Friend ReadOnly Property SleepTimerOnPostsLimit As PropertyValue
|
||||
<Provider(NameOf(SleepTimerOnPostsLimit), FieldsChecker:=True)>
|
||||
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
|
||||
<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
|
||||
<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
|
||||
<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
|
||||
<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
|
||||
<PropertyOption(ControlText:="Tagged notify limit",
|
||||
ControlToolTip:="If the number of tagged posts exceeds this number you will be notified." & vbCr &
|
||||
@@ -190,19 +203,19 @@ Namespace API.Instagram
|
||||
Private ReadOnly Property TaggedNotifyLimitProvider As IFormatProvider
|
||||
#End Region
|
||||
#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
|
||||
<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
|
||||
<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
|
||||
<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
|
||||
<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
|
||||
<PXML> Private ReadOnly Property DownloadTagged_Def As PropertyValue
|
||||
#End Region
|
||||
@@ -352,8 +365,11 @@ Namespace API.Instagram
|
||||
platform = .Value(Header_Platform_Verion)
|
||||
End If
|
||||
'.Add(Header_IG_WWW_CLAIM, 0)
|
||||
.Add("Origin", "https://www.instagram.com")
|
||||
.Add("authority", "www.instagram.com")
|
||||
.Add("Dnt", 1)
|
||||
.Add("Dpr", 1)
|
||||
'.Add("Dpr", 1)
|
||||
.Remove("Dpr")
|
||||
.Add("Sec-Ch-Ua-Mobile", "?0")
|
||||
.Add("Sec-Ch-Ua-Model", """""")
|
||||
.Add("Sec-Ch-Ua-Platform", """Windows""")
|
||||
@@ -396,6 +412,9 @@ Namespace API.Instagram
|
||||
DownloadTagged = New PropertyValue(False)
|
||||
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_AnyProvider = New TimersChecker(0)
|
||||
RequestsWaitTimer = New PropertyValue(1000)
|
||||
@@ -413,7 +432,7 @@ Namespace API.Instagram
|
||||
TaggedNotifyLimit = New PropertyValue(200)
|
||||
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))
|
||||
LastRequestsCount = New PropertyValue(0)
|
||||
LastRequestsCountLabel = New PropertyValue(String.Empty, GetType(String))
|
||||
@@ -427,6 +446,12 @@ Namespace API.Instagram
|
||||
Friend Overrides Sub EndInit()
|
||||
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 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()
|
||||
End Sub
|
||||
#End Region
|
||||
@@ -456,17 +481,101 @@ Namespace API.Instagram
|
||||
End Function
|
||||
#End Region
|
||||
#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 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
|
||||
Private ActiveJobs As Integer = 0
|
||||
Private ActiveSessionDate As Date
|
||||
Private ActiveSessionRequestsExists As Boolean = False
|
||||
Private _NextWNM As UserData.WNM = UserData.WNM.Notify
|
||||
Private _NextTagged As Boolean = True
|
||||
Friend Overrides Sub DownloadStarted(ByVal What As Download)
|
||||
ResetDownloadOptions()
|
||||
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
|
||||
(
|
||||
(CBool(HH_IG_WWW_CLAIM_USE_DEFAULT_ALGO.Value) AndAlso MyLastRequestsDate.AddMinutes(HH_IG_WWW_CLAIM_UPDATE_INTERVAL.Value) < Now) Or
|
||||
@@ -498,6 +607,7 @@ Namespace API.Instagram
|
||||
If _NextWNM = UserData.WNM.SkipTemp Or _NextWNM = UserData.WNM.SkipCurrent Then _NextWNM = UserData.WNM.Notify
|
||||
_NextTagged = .TaggedCheckSession
|
||||
MyLastRequestsCount = .RequestsCountSession
|
||||
If .RequestsCountSession > 0 Then ActiveSessionRequestsExists = True
|
||||
_FieldsChangerSuspended = True
|
||||
HH_IG_WWW_CLAIM.Value = Responser.Headers.Value(Header_IG_WWW_CLAIM)
|
||||
HH_CSRF_TOKEN.Value = Responser.Headers.Value(Header_CSRF_TOKEN)
|
||||
@@ -505,11 +615,8 @@ Namespace API.Instagram
|
||||
End With
|
||||
End Sub
|
||||
Friend Overrides Sub DownloadDone(ByVal What As Download)
|
||||
_NextWNM = UserData.WNM.Notify
|
||||
_NextTagged = True
|
||||
RefreshMyLastRequests(Now)
|
||||
ActiveJobs -= 1
|
||||
SkipUntilNextSession = False
|
||||
ResetDownloadOptions()
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Settings"
|
||||
|
||||
@@ -862,15 +862,20 @@ NextPageBlock:
|
||||
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}/"
|
||||
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,
|
||||
Optional ByVal SpecFolder As String = Nothing, Optional ByVal State As UStates = UStates.Unknown,
|
||||
Optional ByVal Attempts As Integer = 0) As Boolean
|
||||
ThrowAny(Token)
|
||||
If Items.Count > 0 Then
|
||||
If Items.ListExists Then
|
||||
Dim PostIDKV As PostKV
|
||||
Dim Pinned As Boolean
|
||||
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
|
||||
Select Case Section
|
||||
Case Sections.Tagged : SpecFolder = TaggedFolder
|
||||
@@ -879,14 +884,21 @@ NextPageBlock:
|
||||
End Select
|
||||
End If
|
||||
ProgressPre.ChangeMax(Items.Count)
|
||||
For Each nn In Items
|
||||
For i = 0 To Items.Count - 1
|
||||
nn = Items(i)
|
||||
ProgressPre.Perform()
|
||||
With If(Not DefaultParser_ElemNode Is Nothing, nn.ItemF(DefaultParser_ElemNode), nn)
|
||||
If .ListExists Then
|
||||
PostIDKV = New PostKV(.Value("code"), .Value("id"), Section)
|
||||
PostOriginUrl = DefaultParser_PostUrlCreator(PostIDKV)
|
||||
Pinned = .Contains("timeline_pinned_user_ids")
|
||||
If Not DefaultParser_IgnorePass AndAlso PostKvExists(PostIDKV) Then
|
||||
'Pinned = .Contains("timeline_pinned_user_ids")
|
||||
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
|
||||
Else
|
||||
_TempPostsList.Add(PostIDKV.ID)
|
||||
@@ -1269,6 +1281,9 @@ NextPageBlock:
|
||||
ElseIf Responser.StatusCode = 560 Or Responser.StatusCode = HttpStatusCode.InternalServerError Then '560, 500
|
||||
MySiteSettings.SkipUntilNextSession = True
|
||||
Err5xx = Responser.StatusCode
|
||||
ElseIf Responser.StatusCode = -1 And Responser.Status = -1 Then
|
||||
MySiteSettings.SkipUntilNextSession = True
|
||||
Err5xx = Responser.StatusCode
|
||||
Else
|
||||
MyMainLOG = $"Something is wrong. Your credentials may have expired [{CInt(Responser.StatusCode)}/{CInt(Responser.Status)}]: {ToString()} [{s}]"
|
||||
DisableSection(s)
|
||||
|
||||
@@ -14,6 +14,7 @@ Namespace API.Mastodon
|
||||
<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 DownloadModelForceApply As Boolean
|
||||
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadModelLikes As Boolean
|
||||
Friend Sub New(ByVal s As SiteSettings)
|
||||
MyBase.New(s)
|
||||
End Sub
|
||||
|
||||
@@ -63,15 +63,15 @@ Namespace API.Mastodon
|
||||
End Sub
|
||||
#End Region
|
||||
#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
|
||||
<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
|
||||
<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
|
||||
<Provider(NameOf(GifsSpecialFolder), Interaction:=True), Provider(NameOf(GifsPrefix), Interaction:=True)>
|
||||
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
|
||||
<PropertyOption(IsAuth:=False, ControlText:="User related to my domain",
|
||||
ControlToolTip:="Open user profiles and user posts through my domain."), PXML, PClonable>
|
||||
|
||||
@@ -11,5 +11,15 @@ Namespace API.OnlyFans
|
||||
Friend Module Declarations
|
||||
Friend ReadOnly DateProvider As New ADateTime("O")
|
||||
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 Namespace
|
||||
@@ -38,14 +38,18 @@
|
||||
},
|
||||
"advanced_options": {
|
||||
"code-execution": false,
|
||||
"dynamic-mode-default": "deviint",
|
||||
"dynamic-mode-default": "sneaky",
|
||||
"backend": "aio",
|
||||
"downloadbars": false,
|
||||
"cache-mode": "sqlite",
|
||||
"appendlog": true,
|
||||
"custom": null,
|
||||
"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": {
|
||||
"timeline": "Posts",
|
||||
|
||||
@@ -13,18 +13,22 @@ Imports PersonalUtilities.Forms
|
||||
Imports PersonalUtilities.Tools.Web.Clients
|
||||
Imports PersonalUtilities.Tools.Web.Cookies
|
||||
Imports PersonalUtilities.Functions.RegularExpressions
|
||||
Imports DN = SCrawler.API.Base.DeclaredNames
|
||||
Namespace API.OnlyFans
|
||||
<Manifest("AndyProgram_OnlyFans"), SavedPosts, SpecialForm(False), SeparatedTasks(1)>
|
||||
Friend Class SiteSettings : Inherits SiteSettingsBase
|
||||
#Region "Declarations"
|
||||
#Region "Categories"
|
||||
Private Const CAT_OFS As String = "OF-Scraper support"
|
||||
#End Region
|
||||
#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
|
||||
<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
|
||||
<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
|
||||
<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
|
||||
#End Region
|
||||
#Region "Headers"
|
||||
@@ -32,16 +36,16 @@ Namespace API.OnlyFans
|
||||
Private Const HeaderUserID As String = "User-Id"
|
||||
Friend Const HeaderXBC As String = "X-Bc"
|
||||
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
|
||||
<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
|
||||
<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
|
||||
<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
|
||||
<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
|
||||
Private Sub UpdateHeader(ByVal PropertyName As String, ByVal Value As String)
|
||||
Dim hName$ = String.Empty
|
||||
@@ -82,20 +86,21 @@ Namespace API.OnlyFans
|
||||
End Property
|
||||
<PropertyOption(ControlText:="Use old authorization rules",
|
||||
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
|
||||
<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
|
||||
<Provider(NameOf(DynamicRulesUpdateInterval), FieldsChecker:=True)>
|
||||
Private ReadOnly Property DynamicRulesUpdateIntervalProvider As IFormatProvider
|
||||
<PropertyOption(ControlText:="Dynamic rules",
|
||||
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
|
||||
#End Region
|
||||
#Region "OFScraper"
|
||||
<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
|
||||
Get
|
||||
If Not DefaultInstance Is Nothing Then
|
||||
@@ -106,7 +111,7 @@ Namespace API.OnlyFans
|
||||
End Get
|
||||
End Property
|
||||
<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
|
||||
Get
|
||||
If Not DefaultInstance Is Nothing Then
|
||||
@@ -118,7 +123,7 @@ Namespace API.OnlyFans
|
||||
End Property
|
||||
Friend Const KeyModeDefault_Default As String = "cdrm"
|
||||
<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
|
||||
Get
|
||||
If Not DefaultInstance Is Nothing Then
|
||||
@@ -128,12 +133,27 @@ Namespace API.OnlyFans
|
||||
End If
|
||||
End Get
|
||||
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
|
||||
#Region "Initializer"
|
||||
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)
|
||||
|
||||
CheckOFSConfig()
|
||||
|
||||
_AllowUserAgentUpdate = False
|
||||
|
||||
With Responser
|
||||
.Accept = "application/json, text/plain, */*"
|
||||
.AutomaticDecompression = Net.DecompressionMethods.GZip
|
||||
@@ -185,6 +205,7 @@ Namespace API.OnlyFans
|
||||
End If
|
||||
OFScraperMP4decrypt_XML = New PropertyValue(String.Empty, GetType(String))
|
||||
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)
|
||||
UrlPatternUser = "https://onlyfans.com/{0}"
|
||||
@@ -197,8 +218,19 @@ Namespace API.OnlyFans
|
||||
End Function
|
||||
#End Region
|
||||
#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()
|
||||
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()
|
||||
End Sub
|
||||
#End Region
|
||||
|
||||
@@ -549,7 +549,8 @@ Namespace API.OnlyFans
|
||||
Optional ByVal Round As Integer = 0) As Boolean
|
||||
Try
|
||||
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
|
||||
Try
|
||||
j = JsonDocument.Parse(AuthFile.GetText)
|
||||
@@ -565,8 +566,16 @@ Namespace API.OnlyFans
|
||||
End Try
|
||||
If Not j Is Nothing Then
|
||||
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
|
||||
|
||||
@@ -607,10 +616,14 @@ Namespace API.OnlyFans
|
||||
Dim r$ = GetWebString(If(ACheck(Of String)(MySettings.DynamicRules.Value),
|
||||
CStr(MySettings.DynamicRules.Value),
|
||||
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
|
||||
Using j As EContainer = JsonDocument.Parse(r, EDP.ReturnValue)
|
||||
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 _
|
||||
TextSaver.SaveTextToFile(r, AuthFile, True, False, EDP.ThrowException) : MySettings.LastDateUpdated = Now
|
||||
End If
|
||||
@@ -658,12 +671,9 @@ Namespace API.OnlyFans
|
||||
currentCache.Validate()
|
||||
Dim cacheRoot As SFile = currentCache.NewPath
|
||||
cacheRoot.Exists(SFO.Path, True, EDP.ThrowException)
|
||||
Dim f As SFile = $"{SettingsFolderName}\OFScraperConfigPattern.json"
|
||||
Dim f As SFile = OFScraperConfigPatternFile
|
||||
Dim configText$
|
||||
If Not f.Exists Then
|
||||
configText = Text.Encoding.UTF8.GetString(My.Resources.OFResources.OFScraperConfigPattern)
|
||||
TextSaver.SaveTextToFile(configText, f, True)
|
||||
End If
|
||||
CheckOFSConfig()
|
||||
If f.Exists Then
|
||||
Dim replaceValue$ = String.Empty
|
||||
Dim rp As RParams = RParams.DMS(String.Empty, 1, RegexReturn.Replace, RegexOptions.IgnoreCase,
|
||||
@@ -684,6 +694,7 @@ Namespace API.OnlyFans
|
||||
End If
|
||||
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("keydb_api", CStr(MySettings.Keydb_Api.Value))
|
||||
f = currentCache
|
||||
f.Name = "config"
|
||||
f.Extension = "json"
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Imports System.Net
|
||||
Imports System.Threading
|
||||
Imports SCrawler.API.Base
|
||||
Imports SCrawler.API.Reddit.M3U8_Declarations
|
||||
Imports PersonalUtilities.Tools
|
||||
Imports PersonalUtilities.Tools.Web
|
||||
@@ -61,15 +62,18 @@ Namespace API.Reddit
|
||||
Private ReadOnly ProgressExists As Boolean
|
||||
Private ReadOnly Property ProgressPre As PreProgress
|
||||
Private ReadOnly UsePreProgress As Boolean
|
||||
Private ReadOnly Media As UserMedia
|
||||
#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
|
||||
Me.Media = Media
|
||||
BaseURL = RegexReplace(URL, BaseUrlPattern)
|
||||
Video = New List(Of String)
|
||||
Audio = New List(Of String)
|
||||
Me.OutFile = OutFile
|
||||
Me.OutFile.Name = "PlayListFile"
|
||||
Me.OutFile.Extension = "mp4"
|
||||
If Media.Post.Date.HasValue Then Me.OutFile.Name = Media.Post.Date.Value.ToString("yyyyMMdd_HHmmss")
|
||||
Me.Progress = Progress
|
||||
ProgressExists = Not Me.Progress Is Nothing
|
||||
ProgressPre = New PreProgress(Progress)
|
||||
@@ -202,9 +206,9 @@ Namespace API.Reddit
|
||||
End Function
|
||||
#End Region
|
||||
#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
|
||||
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 Region
|
||||
#Region "IDisposable Support"
|
||||
|
||||
@@ -10,6 +10,7 @@ Imports SCrawler.API.Base
|
||||
Imports SCrawler.Plugin
|
||||
Imports SCrawler.Plugin.Attributes
|
||||
Imports PersonalUtilities.Tools.Web.Clients
|
||||
Imports PersonalUtilities.Tools.Web.Clients.Base
|
||||
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||
Imports PersonalUtilities.Functions.XML
|
||||
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 &
|
||||
"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
|
||||
<PropertyOption(ControlText:="Use 'cUrl' to get a token", IsAuth:=True), PXML, PClonable, HiddenControl>
|
||||
Private ReadOnly Property BearerTokenUseCurl As PropertyValue
|
||||
#Region "TokenUpdateInterval"
|
||||
<PropertyOption(ControlText:="Token refresh interval", ControlToolTip:="Interval (in minutes) to refresh the token",
|
||||
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)
|
||||
End Get
|
||||
End Property
|
||||
|
||||
#End Region
|
||||
#Region "Other"
|
||||
<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))
|
||||
ApiClientSecret = New PropertyValue(String.Empty, GetType(String))
|
||||
BearerToken = New PropertyValue(token, GetType(String), Sub(v) Responser.Headers.Add(DeclaredNames.Header_Authorization, v))
|
||||
BearerTokenUseCurl = New PropertyValue(True)
|
||||
TokenUpdateInterval = New PropertyValue(60 * 12)
|
||||
TokenUpdateIntervalProvider = New TokenRefreshIntervalProvider
|
||||
BearerTokenDateUpdate = New PropertyValue(Now.AddYears(-1))
|
||||
@@ -269,29 +272,51 @@ Namespace API.Reddit
|
||||
result = False
|
||||
Dim r$ = String.Empty
|
||||
Dim c% = 0
|
||||
Dim _found As Boolean
|
||||
Dim useCurl As Boolean = Settings.CurlFile.Exists And CBool(BearerTokenUseCurl.Value)
|
||||
Dim curlUsed As Boolean = useCurl
|
||||
Do
|
||||
c += 1
|
||||
Using resp As New Responser With {
|
||||
.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 .PayLoadValues
|
||||
.Add("grant_type", "password")
|
||||
.Add("username", UserName)
|
||||
.Add("password", Password)
|
||||
End With
|
||||
.CredentialsUserName = ClientID
|
||||
.CredentialsPassword = ClientSecret
|
||||
.PreAuthenticate = True
|
||||
If useCurl Then
|
||||
If Settings.CurlFile.Exists Then
|
||||
curlUsed = True
|
||||
.Mode = Responser.Modes.Curl
|
||||
.CurlPath = Settings.CurlFile
|
||||
.CurlArgumentsLeft = $"-d ""grant_type=password&username={UserName}&password={Password}"" --user ""{ClientID}:{ClientSecret}"""
|
||||
Else
|
||||
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
|
||||
r = resp.GetResponse("https://www.reddit.com/api/v1/access_token",, EDP.ThrowException)
|
||||
End Using
|
||||
If Not r.IsEmptyString Then
|
||||
Using j As EContainer = JsonDocument.Parse(r)
|
||||
If j.ListExists Then
|
||||
_found = True
|
||||
Dim newToken$ = j.Value("access_token")
|
||||
If Not newToken.IsEmptyString Then
|
||||
BearerToken.Value = $"Bearer {newToken}"
|
||||
@@ -302,7 +327,7 @@ Namespace API.Reddit
|
||||
End If
|
||||
End Using
|
||||
End If
|
||||
Loop While c < 5 And Not _found
|
||||
Loop While c < 5 And Not result
|
||||
End If
|
||||
Return result
|
||||
Catch ex As Exception
|
||||
|
||||
@@ -225,6 +225,7 @@ Namespace API.Reddit
|
||||
#End Region
|
||||
#Region "Download Overrides"
|
||||
Friend Overrides Sub DownloadData(ByVal Token As CancellationToken)
|
||||
Err429Count = 0
|
||||
_CrossPosts.Clear()
|
||||
If CreatedByChannel And Settings.FromChannelDownloadTopUse And Settings.FromChannelDownloadTop > 0 Then _
|
||||
DownloadTopCount = Settings.FromChannelDownloadTop.Value
|
||||
@@ -287,6 +288,7 @@ Namespace API.Reddit
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Download Functions (User, Channel)"
|
||||
Private Err429Count As Integer = 0
|
||||
Private _TotalPostsDownloaded As Integer = 0
|
||||
Private ReadOnly _CrossPosts As List(Of String)
|
||||
Private Const SiteGfycatKey As String = "gfycat"
|
||||
@@ -375,6 +377,7 @@ Namespace API.Reddit
|
||||
Loop While Not _completed
|
||||
End Sub
|
||||
Private Sub DownloadDataChannel(ByVal POST As String, ByVal Token As CancellationToken)
|
||||
Const savedPostsSleepTimer% = 2000
|
||||
Dim eObj% = 0
|
||||
Dim round% = 0
|
||||
Dim URL$ = String.Empty
|
||||
@@ -392,12 +395,14 @@ Namespace API.Reddit
|
||||
|
||||
If IsSavedPosts Then
|
||||
URL = $"https://www.reddit.com/user/{TrueName}/saved.json?after={POST}"
|
||||
If Not POST.IsEmptyString Then Thread.Sleep(savedPostsSleepTimer)
|
||||
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"
|
||||
End If
|
||||
|
||||
ThrowAny(Token)
|
||||
Dim r$ = Responser.GetResponse(URL)
|
||||
If IsSavedPosts Then Err429Count = 0
|
||||
If Not r.IsEmptyString Then
|
||||
Using w As EContainer = JsonDocument.Parse(r).XmlIfNothing
|
||||
If w.Count > 0 Then
|
||||
@@ -458,8 +463,12 @@ Namespace API.Reddit
|
||||
End If
|
||||
_completed = True
|
||||
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
|
||||
ElseIf errValue = 429 And round = 0 Then
|
||||
Thread.Sleep(savedPostsSleepTimer)
|
||||
round += 1
|
||||
Else
|
||||
_completed = True
|
||||
End If
|
||||
@@ -905,19 +914,24 @@ Namespace API.Reddit
|
||||
Dim RedGifsHost As SettingsHost = Settings(RedGifs.RedGifsSiteKey, RedGifsAccount)
|
||||
If RedGifsHost Is Nothing Then RedGifsHost = Settings(RedGifs.RedGifsSiteKey).Default
|
||||
RedGifsResponser = RedGifsHost.Responser.Copy
|
||||
Dim respNoHeaders As Responser = Responser.Copy
|
||||
Dim m As UserMedia, m2 As UserMedia
|
||||
Dim r$
|
||||
Dim r$, url$
|
||||
Dim j As EContainer
|
||||
Dim lastCount%, li%
|
||||
Dim rv As New ErrorsDescriber(EDP.ReturnValue)
|
||||
respNoHeaders.Headers.Clear()
|
||||
ProgressPre.ChangeMax(_ContentList.Count)
|
||||
For i% = 0 To _ContentList.Count - 1
|
||||
m = _ContentList(i)
|
||||
ProgressPre.Perform()
|
||||
If m.State = UStates.Missing AndAlso Not m.Post.ID.IsEmptyString Then
|
||||
ThrowAny(Token)
|
||||
r = Responser.GetResponse($"https://www.reddit.com/comments/{m.Post.ID.Split("_").LastOrDefault}/.json",, 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
|
||||
j = JsonDocument.Parse(r, EDP.ReturnValue)
|
||||
j = JsonDocument.Parse(r, rv)
|
||||
If Not j Is Nothing Then
|
||||
If j.Count > 0 Then
|
||||
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}}
|
||||
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 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
|
||||
End Function
|
||||
Private Function TryFile(ByVal URL As String) As Boolean
|
||||
@@ -1027,7 +1041,7 @@ Namespace API.Reddit
|
||||
Return URL.Contains(SiteRedGifsKey)
|
||||
End Function
|
||||
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
|
||||
Protected Overrides Function ChangeFileNameByProvider(ByVal f As SFile, ByVal m As UserMedia) As SFile
|
||||
If Not IsChannel Or Not SaveToCache Then
|
||||
@@ -1057,8 +1071,11 @@ Namespace API.Reddit
|
||||
ElseIf .StatusCode = HttpStatusCode.InternalServerError Then '500
|
||||
If Not IsNothing(EObj) AndAlso IsNumeric(EObj) AndAlso CInt(EObj) = HttpStatusCode.InternalServerError Then Return 1
|
||||
Return HttpStatusCode.InternalServerError
|
||||
ElseIf .StatusCode = 429 And IsSavedPosts And Err429Count = 0 Then
|
||||
Err429Count += 1
|
||||
Return 429
|
||||
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
|
||||
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")
|
||||
|
||||
@@ -18,9 +18,9 @@ Namespace API.RedGifs
|
||||
<Manifest(RedGifsSiteKey)>
|
||||
Friend Class SiteSettings : Inherits SiteSettingsBase
|
||||
#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
|
||||
<PropertyOption, ControlNumber(2), PClonable>
|
||||
<PropertyOption, ControlNumber(2), PClonable, HiddenControl>
|
||||
Private ReadOnly Property UserAgent As PropertyValue
|
||||
<PXML> Friend ReadOnly Property TokenLastDateUpdated As PropertyValue
|
||||
Private Const TokenName As String = "authorization"
|
||||
@@ -107,7 +107,9 @@ Namespace API.RedGifs
|
||||
Friend Overrides Sub Update()
|
||||
If _SiteEditorFormOpened Then
|
||||
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
|
||||
MyBase.Update()
|
||||
End Sub
|
||||
|
||||
@@ -13,6 +13,7 @@ Imports PersonalUtilities.Tools.Web.Clients
|
||||
Imports PersonalUtilities.Tools.Web.Cookies
|
||||
Imports PersonalUtilities.Functions.RegularExpressions
|
||||
Imports IG = SCrawler.API.Instagram.SiteSettings
|
||||
Imports DN = SCrawler.API.Base.DeclaredNames
|
||||
Namespace API.ThreadsNet
|
||||
<Manifest("AndyProgram_ThreadsNet"), SeparatedTasks(1)>
|
||||
Friend Class SiteSettings : Inherits SiteSettingsBase
|
||||
@@ -40,10 +41,10 @@ Namespace API.ThreadsNet
|
||||
Friend ReadOnly Property HH_ASBD_ID As PropertyValue
|
||||
<PropertyOption(ControlText:="sec-ch-ua", AllowNull:=True, IsAuth:=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,
|
||||
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,
|
||||
InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua_platform_version), ControlNumber(50), PClonable, PXML(OnlyForChecked:=True)>
|
||||
Friend ReadOnly Property HH_PLATFORM_VER As PropertyValue
|
||||
@@ -75,14 +76,14 @@ Namespace API.ThreadsNet
|
||||
#Region "Other properties"
|
||||
<PropertyOption(ControlText:="Request timer (any)",
|
||||
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>
|
||||
Friend ReadOnly Property RequestsWaitTimer_Any As PropertyValue
|
||||
<Provider(NameOf(RequestsWaitTimer_Any), FieldsChecker:=True)>
|
||||
Private ReadOnly Property RequestsWaitTimer_AnyProvider As IFormatProvider
|
||||
<PropertyOption(ControlText:="Download data",
|
||||
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
|
||||
#End Region
|
||||
#End Region
|
||||
@@ -127,9 +128,10 @@ Namespace API.ThreadsNet
|
||||
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecFetchMode, "cors"))
|
||||
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.SecFetchSite, "same-origin"))
|
||||
.Add("Sec-Fetch-User", "?1")
|
||||
.Add("dht", 1)
|
||||
.Add("dnt", 1)
|
||||
.Add("drp", 1)
|
||||
.Add(Instagram.UserData.GQL_HEADER_FB_FRINDLY_NAME, "BarcelonaProfileThreadsTabRefetchableQuery")
|
||||
.Remove("dht")
|
||||
End With
|
||||
.CookiesExtractMode = Responser.CookiesExtractModes.Any
|
||||
.CookiesUpdateMode = CookieKeeper.UpdateModes.ReplaceByNameAll
|
||||
|
||||
@@ -17,6 +17,10 @@ Imports PersonalUtilities.Tools.Web.Clients.EventArguments
|
||||
Imports IGS = SCrawler.API.Instagram.SiteSettings
|
||||
Namespace API.ThreadsNet
|
||||
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"
|
||||
Private ReadOnly Property MySettings As SiteSettings
|
||||
Get
|
||||
@@ -29,9 +33,20 @@ Namespace API.ThreadsNet
|
||||
Return ValidateBaseTokens() And Not ID.IsEmptyString
|
||||
End Get
|
||||
End Property
|
||||
Private Property MaxLastDownDate As Date? = Nothing
|
||||
Private Property FirstLoadingDone As Boolean = False
|
||||
#End Region
|
||||
#Region "Loader"
|
||||
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 Region
|
||||
#Region "Exchange"
|
||||
@@ -49,6 +64,7 @@ Namespace API.ThreadsNet
|
||||
DefaultParser_PostUrlCreator = Function(post) $"https://www.threads.net/@{NameTrue}/post/{post.Code}"
|
||||
_ResponserAutoUpdateCookies = True
|
||||
_ResponserAddResponseReceivedHandler = True
|
||||
DefaultParser_Pinned = AddressOf IsPinnedPost
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Download functions"
|
||||
@@ -66,7 +82,27 @@ Namespace API.ThreadsNet
|
||||
Responser.Method = "POST"
|
||||
LoadSavePostsKV(True)
|
||||
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)
|
||||
If _TempMediaList.Count > 0 Then FirstLoadingDone = True : setMaxPostDate.Invoke(_TempMediaList)
|
||||
Catch ex As Exception
|
||||
errorFound = True
|
||||
Throw ex
|
||||
@@ -78,6 +114,21 @@ Namespace API.ThreadsNet
|
||||
End Try
|
||||
End If
|
||||
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()
|
||||
If Not Responser Is Nothing AndAlso Not Responser.Disposed Then
|
||||
RemoveHandler Responser.ResponseReceived, AddressOf Responser_ResponseReceived
|
||||
@@ -164,16 +215,27 @@ Namespace API.ThreadsNet
|
||||
.Method = "GET"
|
||||
.Referer = URL
|
||||
With .Headers
|
||||
.Remove(GQL_HEADER_FB_LSD)
|
||||
.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()
|
||||
Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException)
|
||||
If Not r.IsEmptyString Then
|
||||
ParseTokens(r, 0)
|
||||
If ID.IsEmptyString Then ID = RegexReplace(r, RParams.DMS("""props"":\{""user_id"":""(\d+)""\},", 1, EDP.ReturnValue))
|
||||
If ID.IsEmptyString Then ID = RegexReplace(r, RParams.DMS("""props"":\{""user_id"":""(\d+)""", 1, EDP.ReturnValue))
|
||||
End If
|
||||
Return Valid
|
||||
Catch ex As Exception
|
||||
|
||||
@@ -15,6 +15,7 @@ Namespace API.Twitter
|
||||
Friend Const TwitterSiteKey As String = "AndyProgram_Twitter"
|
||||
Friend ReadOnly DateProvider As ADateTime = GetDateProvider()
|
||||
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
|
||||
Dim n As DateTimeFormatInfo = CultureInfo.GetCultureInfo("en-us").DateTimeFormat.Clone
|
||||
n.FullDateTimePattern = "ddd MMM dd HH:mm:ss +ffff yyyy"
|
||||
|
||||
@@ -28,16 +28,20 @@ Namespace API.Twitter
|
||||
Friend Overridable Property MediaModelAllowNonUserTweets As Boolean = False
|
||||
<PSetting(Address:=SettingAddress.User,
|
||||
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
|
||||
<PSetting(Address:=SettingAddress.User,
|
||||
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
|
||||
<PSetting(Address:=SettingAddress.User,
|
||||
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
|
||||
<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,
|
||||
Caption:="Force apply",
|
||||
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)
|
||||
DownloadModelProfile = dm.Contains(DModels.Profile)
|
||||
DownloadModelSearch = dm.Contains(DModels.Search)
|
||||
DownloadModelLikes = dm.Contains(DModels.Likes)
|
||||
End If
|
||||
End If
|
||||
MySettings = u.HOST.Source
|
||||
|
||||
@@ -16,32 +16,37 @@ Namespace API.Twitter
|
||||
<Manifest(TwitterSiteKey), SavedPosts, SeparatedTasks, SpecialForm(False)>
|
||||
Friend Class SiteSettings : Inherits SiteSettingsBase
|
||||
#Region "Declarations"
|
||||
#Region "Categories"
|
||||
Private Const CAT_DOWN As String = "Downloading"
|
||||
#End Region
|
||||
#Region "Other properties"
|
||||
<PropertyOption(ControlText:="Use the appropriate model",
|
||||
ControlToolTip:="Use the appropriate model for new users." & vbCr &
|
||||
"If disabled, all download models will be used for the first download. " &
|
||||
"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
|
||||
#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
|
||||
<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
|
||||
#End Region
|
||||
#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
|
||||
<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
|
||||
#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
|
||||
<PropertyOption(ControlText:=DN.GifsDownloadCaption), PXML, PClonable>
|
||||
<PropertyOption(ControlText:=DN.GifsDownloadCaption, Category:=DN.CAT_UserDefs), PXML, PClonable>
|
||||
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
|
||||
<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
|
||||
<Provider(NameOf(GifsSpecialFolder), Interaction:=True), Provider(NameOf(GifsPrefix), Interaction:=True)>
|
||||
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]")
|
||||
End Function
|
||||
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
|
||||
<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
|
||||
<Provider(NameOf(ConcurrentDownloads), FieldsChecker:=True)>
|
||||
Private ReadOnly Property MyConcurrentDownloadsProvider As IFormatProvider
|
||||
#End Region
|
||||
#End Region
|
||||
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)
|
||||
|
||||
@@ -96,8 +101,8 @@ Namespace API.Twitter
|
||||
ConcurrentDownloads = New PropertyValue(1)
|
||||
MyConcurrentDownloadsProvider = New ConcurrentDownloadsProvider
|
||||
|
||||
UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "/(twitter|x).com/"), 2)
|
||||
UrlPatternUser = "https://twitter.com/{0}"
|
||||
UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, $"/(twitter|x).com({CommunitiesUser}|)/"), 3)
|
||||
UrlPatternUser = "https://x.com/{0}"
|
||||
ImageVideoContains = "twitter"
|
||||
CheckNetscapeCookiesOnEndInit = True
|
||||
UseNetscapeCookies = True
|
||||
@@ -105,8 +110,9 @@ Namespace API.Twitter
|
||||
Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider
|
||||
Return New UserData
|
||||
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
|
||||
Return $"https://twitter.com/{User.Name}/status/{Media.Post.ID}"
|
||||
Return String.Format(SinglePostPattern, Media.Post.ID)
|
||||
End Function
|
||||
Friend Overrides Function BaseAuthExists() As Boolean
|
||||
Return Responser.CookiesExists
|
||||
@@ -146,5 +152,18 @@ Namespace API.Twitter
|
||||
End If
|
||||
MyBase.Update()
|
||||
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 Namespace
|
||||
@@ -26,13 +26,30 @@ Namespace API.Twitter
|
||||
Private Const Name_GifsDownload As String = "GifsDownload"
|
||||
Private Const Name_GifsSpecialFolder As String = "GifsSpecialFolder"
|
||||
Private Const Name_GifsPrefix As String = "GifsPrefix"
|
||||
Private Const Name_IsCommunity As String = "IsCommunity"
|
||||
#End Region
|
||||
#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
|
||||
Undefined = 0
|
||||
Media = 1
|
||||
Profile = 2
|
||||
Search = 5
|
||||
Likes = 10
|
||||
End Enum
|
||||
Private FirstDownloadComplete As Boolean = False
|
||||
Friend Property DownloadModelForceApply As Boolean = False
|
||||
@@ -41,6 +58,8 @@ Namespace API.Twitter
|
||||
Friend Property GifsDownload As Boolean = True
|
||||
Friend Property GifsSpecialFolder 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 Property MySettings As SiteSettings
|
||||
Get
|
||||
@@ -55,6 +74,9 @@ Namespace API.Twitter
|
||||
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)
|
||||
End Function
|
||||
Friend Function GetUserUrl() As String
|
||||
Return $"https://x.com{IIf(IsCommunity, SiteSettings.CommunitiesUser, String.Empty)}/{NameTrue}"
|
||||
End Function
|
||||
#End Region
|
||||
#Region "Exchange options"
|
||||
Friend Overrides Function ExchangeOptionsGet() As Object
|
||||
@@ -74,6 +96,7 @@ Namespace API.Twitter
|
||||
If .DownloadModelMedia Then DownloadModel += DownloadModels.Media
|
||||
If .DownloadModelProfile Then DownloadModel += DownloadModels.Profile
|
||||
If .DownloadModelSearch Then DownloadModel += DownloadModels.Search
|
||||
If .DownloadModelLikes Then DownloadModel += DownloadModels.Likes
|
||||
End With
|
||||
End If
|
||||
End Sub
|
||||
@@ -81,6 +104,7 @@ Namespace API.Twitter
|
||||
#Region "Initializer, loader"
|
||||
Friend Sub New()
|
||||
_DataNames = New List(Of String)
|
||||
LikesPosts = New List(Of String)
|
||||
End Sub
|
||||
Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean)
|
||||
With Container
|
||||
@@ -117,7 +141,20 @@ Namespace API.Twitter
|
||||
RemoveExistingDuplicates = .Value(Name_RemoveExistingDuplicates).FromXML(Of Boolean)(False)
|
||||
StartMD5Checked = .Value(Name_StartMD5Checked).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
|
||||
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_DownloadModelForceApply, DownloadModelForceApply.BoolToInteger)
|
||||
.Add(Name_DownloadModel, CInt(DownloadModel))
|
||||
@@ -128,6 +165,8 @@ Namespace API.Twitter
|
||||
.Add(Name_RemoveExistingDuplicates, RemoveExistingDuplicates.BoolToInteger)
|
||||
.Add(Name_StartMD5Checked, StartMD5Checked.BoolToInteger)
|
||||
.Add(Name_MediaModelAllowNonUserTweets, MediaModelAllowNonUserTweets.BoolToInteger)
|
||||
.Add(Name_IsCommunity, IsCommunity.BoolToInteger)
|
||||
.Add(Name_TrueName, _NameTrue)
|
||||
End If
|
||||
End With
|
||||
End Sub
|
||||
@@ -142,21 +181,32 @@ Namespace API.Twitter
|
||||
}
|
||||
End Function
|
||||
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
||||
If MySettings.LIMIT_ABORT Then
|
||||
Throw New TwitterLimitException(Me)
|
||||
Else
|
||||
If IsSavedPosts Then
|
||||
If _ContentList.Count > 0 Then _DataNames.ListAddList(_ContentList.Select(Function(c) c.Post.ID), LAP.ClearBeforeAdd, LAP.NotContainsOnly)
|
||||
DownloadData_SavedPosts(Token)
|
||||
Try
|
||||
If MySettings.LIMIT_ABORT Then
|
||||
Throw New TwitterLimitException(Me)
|
||||
Else
|
||||
If _ContentList.Count > 0 Then _DataNames.ListAddList(_ContentList.Select(Function(c) c.File.File), LAP.ClearBeforeAdd, LAP.NotContainsOnly)
|
||||
DownloadData_Timeline(Token)
|
||||
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
|
||||
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
|
||||
Finally
|
||||
_ReparseLikes = False
|
||||
End Try
|
||||
End Sub
|
||||
Private Sub DownloadData_Timeline(ByVal Token As CancellationToken)
|
||||
Dim URL$ = String.Empty
|
||||
Dim tCache As CacheKeeper = Nothing
|
||||
Dim likesDetected As Boolean = False
|
||||
Try
|
||||
Const entry$ = "entry"
|
||||
Dim PostID$ = String.Empty
|
||||
@@ -173,14 +223,15 @@ Namespace API.Twitter
|
||||
Dim newTwitterNodes() As Object = {0, "content", "items"}
|
||||
Dim p As Predicate(Of EContainer)
|
||||
Dim pIndx%
|
||||
Dim indxChanged 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 __parseContainer As Func(Of EContainer, Boolean) =
|
||||
Function(ByVal ee As EContainer) As Boolean
|
||||
nn = Nothing
|
||||
If dirIndx > 1 Then nn = ee
|
||||
If Not nn.ListExists Then
|
||||
If dirIndx > 1 Or IsCommunity Then nn = ee
|
||||
If Not nn.ListExists Or IsCommunity Then
|
||||
For Each node In nodes
|
||||
nn = ee(node)
|
||||
If nn.ListExists Then Exit For
|
||||
@@ -199,6 +250,7 @@ Namespace API.Twitter
|
||||
|
||||
If Not _TempPostsList.Contains(PostID) Then
|
||||
_TempPostsList.Add(PostID)
|
||||
ElseIf dirIndx = 3 Then
|
||||
ElseIf isPins Then
|
||||
Return False
|
||||
Else
|
||||
@@ -211,9 +263,22 @@ Namespace API.Twitter
|
||||
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("/")
|
||||
|
||||
If Not ParseUserMediaOnly OrElse
|
||||
If (Not ParseUserMediaOnly Or dirIndx = 3) 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
|
||||
Return True
|
||||
End Function
|
||||
@@ -225,6 +290,8 @@ Namespace API.Twitter
|
||||
For Each dir As SFile In dirs
|
||||
dirIndx += 1
|
||||
|
||||
If dirIndx = 3 Then likesDetected = True
|
||||
|
||||
ExistsDetected = False
|
||||
|
||||
If Not dir.IsEmptyString Then
|
||||
@@ -238,10 +305,22 @@ Namespace API.Twitter
|
||||
For i = 0 To timelineFiles.Count - 1
|
||||
j = JsonDocument.Parse(timelineFiles(i).GetText)
|
||||
If Not j Is Nothing Then
|
||||
If i = 0 Then
|
||||
If i = 0 And Not indxChanged Then
|
||||
If Not userInfoParsed Then
|
||||
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
|
||||
UserExists = False
|
||||
j.Dispose()
|
||||
@@ -250,6 +329,29 @@ Namespace API.Twitter
|
||||
UserSuspended = True
|
||||
j.Dispose()
|
||||
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
|
||||
With j({"data", "user", "result"})
|
||||
If .ListExists Then
|
||||
@@ -259,21 +361,11 @@ Namespace API.Twitter
|
||||
End If
|
||||
With .Item({"legacy"})
|
||||
If .ListExists Then
|
||||
If .Value("screen_name").StringToLower = Name.ToLower Then
|
||||
If .Value("screen_name").StringToLower = NameTrue.ToLower Then
|
||||
UserSiteNameUpdate(.Value("name"))
|
||||
UserDescriptionUpdate(.Value("description"))
|
||||
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
|
||||
Dim icon$ = .Value("profile_image_url_https")
|
||||
|
||||
icon = .Value("profile_image_url_https")
|
||||
If Not icon.IsEmptyString Then icon = icon.Replace("_normal", String.Empty)
|
||||
If DownloadIconBanner Then
|
||||
__getImage.Invoke(.Value("profile_banner_url"))
|
||||
@@ -285,29 +377,55 @@ Namespace API.Twitter
|
||||
End If
|
||||
End With
|
||||
End If
|
||||
ElseIf IsCommunity Then
|
||||
i = -1
|
||||
indxChanged = True
|
||||
End If
|
||||
Else
|
||||
For pIndx = 0 To IIf(dirIndx < 2, 1, 0)
|
||||
For pIndx = 0 To IIf(dirIndx < 2 Or dirIndx = 3, 1, 0)
|
||||
optionalNode = Nothing
|
||||
Select Case dirIndx
|
||||
Case 0, 1
|
||||
rootNode = j({"data", "user", "result", "timeline_v2", "timeline", "instructions"})
|
||||
If rootNode.ListExists Then
|
||||
p = If(pIndx = 0, pinNode, timelineNode)
|
||||
isPins = pIndx = 0
|
||||
rootNode = Nothing
|
||||
If IsCommunity Then
|
||||
With j({"data", "communityResults", "result", "community_media_timeline", "timeline", "instructions"})
|
||||
If .ListExists Then
|
||||
If i = 0 Then
|
||||
rootNode = .Find(entriesNode, True)
|
||||
Else
|
||||
rootNode = .Find(moduleItemsPredicate, True)
|
||||
End If
|
||||
optionalNode = rootNode
|
||||
rootNode = rootNode.Find(p, False)
|
||||
If rootNode.ListExists Then rootNode = rootNode.Find(entriesNode, False)
|
||||
End If
|
||||
Case Else
|
||||
isPins = False
|
||||
rootNode = j({"globalObjects", "tweets"})
|
||||
optionalNode = rootNode
|
||||
End Select
|
||||
End With
|
||||
Else
|
||||
Select Case dirIndx
|
||||
Case 0, 1, 3
|
||||
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
|
||||
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))
|
||||
If isOneNode Then
|
||||
ProgressPre.Perform()
|
||||
@@ -369,12 +487,12 @@ Namespace API.Twitter
|
||||
ProcessException(ex, Token, $"data downloading error [{URL}]")
|
||||
Finally
|
||||
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 Sub
|
||||
Private Sub DownloadData_SavedPosts(ByVal Token As CancellationToken)
|
||||
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")
|
||||
If files.ListExists Then
|
||||
ResetFileNameProvider(Math.Max(files.Count.ToString.Length, 3))
|
||||
@@ -417,21 +535,24 @@ Namespace API.Twitter
|
||||
#End Region
|
||||
#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,
|
||||
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"})
|
||||
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
|
||||
Dim mUrl$
|
||||
Dim media As UserMedia
|
||||
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"))
|
||||
If Not mUrl.IsEmptyString Then
|
||||
Dim dName$ = UrlFile(mUrl)
|
||||
If Not dName.IsEmptyString AndAlso Not _DataNames.Contains(dName) Then
|
||||
_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
|
||||
@@ -439,15 +560,17 @@ Namespace API.Twitter
|
||||
End If
|
||||
End Sub
|
||||
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
|
||||
If CheckForGif(w, PostID, PostDate, State) Then Return True
|
||||
If CheckForGif(w, PostID, PostDate, State, SpecialFolder) Then Return True
|
||||
Dim URL$ = GetVideoNodeURL(w)
|
||||
If Not URL.IsEmptyString Then
|
||||
Dim f$ = UrlFile(URL)
|
||||
If Not f.IsEmptyString AndAlso Not _DataNames.Contains(f) Then
|
||||
_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
|
||||
Return True
|
||||
End If
|
||||
@@ -458,7 +581,7 @@ Namespace API.Twitter
|
||||
End Try
|
||||
End Function
|
||||
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
|
||||
Dim gifUrl As Predicate(Of EContainer) = Function(e) Not e.Value("content_type").IsEmptyString AndAlso
|
||||
e.Value("content_type").Contains("mp4") AndAlso
|
||||
@@ -477,9 +600,13 @@ Namespace API.Twitter
|
||||
If Not ff.IsEmptyString Then
|
||||
If GifsDownload And Not _DataNames.Contains(ff) Then
|
||||
m = MediaFromData(url, PostID, PostDate,, State, UTypes.Video)
|
||||
If Not SpecialFolder.IsEmptyString Then m.SpecialFolder = SpecialFolder
|
||||
f = m.File
|
||||
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)
|
||||
End If
|
||||
Return True
|
||||
@@ -615,6 +742,7 @@ Namespace API.Twitter
|
||||
Dim dir As SFile
|
||||
Dim dm As List(Of DownloadModels) = EnumExtract(Of DownloadModels)(DownloadModel).ListIfNothing
|
||||
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 {
|
||||
.TempPostsList = _TempPostsList,
|
||||
@@ -625,7 +753,7 @@ Namespace API.Twitter
|
||||
}
|
||||
tgdl.FileExchanger.DeleteCacheOnDispose = 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.Exists(SFO.Path, True, EDP.ThrowException)
|
||||
outList.Add(dir)
|
||||
@@ -633,9 +761,10 @@ Namespace API.Twitter
|
||||
command = $"""{Settings.GalleryDLFile}"" --verbose --no-download --no-skip --config ""{conf}"" --write-pages "
|
||||
command &= GdlGetIdFilterString()
|
||||
Select Case i
|
||||
Case 0 : command &= $"https://twitter.com/{Name}/media" : process = dm.Contains(DownloadModels.Media)
|
||||
Case 1 : command &= $"https://twitter.com/{Name}" : 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 0 : command &= $"{urlPrePattern}{NameTrue}/media" : process = dm.Contains(DownloadModels.Media) Or IsCommunity
|
||||
Case 1 : command &= $"{urlPrePattern}{NameTrue}" : process = dm.Contains(DownloadModels.Profile)
|
||||
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
|
||||
End Select
|
||||
'#If DEBUG Then
|
||||
@@ -687,13 +816,13 @@ Namespace API.Twitter
|
||||
End Function
|
||||
#End Region
|
||||
#Region "ReparseMissing"
|
||||
Private _ReparseLikes As Boolean = False
|
||||
Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken)
|
||||
Const SinglePostPattern$ = "https://twitter.com/{0}/status/{1}"
|
||||
Dim rList As New List(Of Integer)
|
||||
Dim URL$ = String.Empty
|
||||
Dim cache As CacheKeeper = Nothing
|
||||
Try
|
||||
If ContentMissingExists Then
|
||||
If ContentMissingExists Or (_ReparseLikes And LikesPosts.Count > 0) Then
|
||||
Dim m As UserMedia
|
||||
Dim PostDate$
|
||||
Dim nodes As List(Of String()) = GetContainerSubnodes()
|
||||
@@ -702,24 +831,24 @@ Namespace API.Twitter
|
||||
Dim f As SFile
|
||||
Dim i%, ii%
|
||||
Dim files As List(Of SFile)
|
||||
Dim lim%
|
||||
Dim specFolder$ = IIf(_ReparseLikes, "Likes", String.Empty)
|
||||
ResetFileNameProvider()
|
||||
If IsSingleObjectDownload Then
|
||||
cache = Settings.Cache
|
||||
Else
|
||||
cache = New CacheKeeper(DownloadContentDefault_GetRootDir.CSFilePS)
|
||||
cache.CacheDeleteError = CacheDeletionError(cache)
|
||||
End If
|
||||
ProgressPre.ChangeMax(_ContentList.Count)
|
||||
For i = 0 To _ContentList.Count - 1
|
||||
cache = If(IsSingleObjectDownload, Settings.Cache, CreateCache())
|
||||
If _ReparseLikes Then lim = LikesPosts.Count Else lim = _ContentList.Count
|
||||
ProgressPre.ChangeMax(lim)
|
||||
For i = 0 To lim - 1
|
||||
ProgressPre.Perform()
|
||||
If _ContentList(i).State = UStates.Missing Then
|
||||
m = _ContentList(i)
|
||||
If Not m.Post.ID.IsEmptyString Or (IsSingleObjectDownload And Not m.URL_BASE.IsEmptyString) Then
|
||||
If _ReparseLikes OrElse _ContentList(i).State = UStates.Missing Then
|
||||
m = If(_ReparseLikes, Nothing, _ContentList(i))
|
||||
If Not m.Post.ID.IsEmptyString Or (IsSingleObjectDownload And Not m.URL_BASE.IsEmptyString) Or _ReparseLikes Then
|
||||
ThrowAny(Token)
|
||||
If IsSingleObjectDownload Then
|
||||
URL = m.URL_BASE
|
||||
ElseIf _ReparseLikes Then
|
||||
URL = LikesPosts(i)
|
||||
Else
|
||||
URL = String.Format(SinglePostPattern, Name, m.Post.ID)
|
||||
URL = String.Format(SiteSettings.SinglePostPattern, m.Post.ID)
|
||||
End If
|
||||
f = GetDataFromGalleryDL(URL, cache, False, Token)
|
||||
If Not f.IsEmptyString Then
|
||||
@@ -737,7 +866,7 @@ Namespace API.Twitter
|
||||
If .ListExists Then
|
||||
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)
|
||||
End If
|
||||
End With
|
||||
@@ -759,7 +888,7 @@ Namespace API.Twitter
|
||||
ProcessException(ex, Token, $"ReparseMissing error [{URL}]")
|
||||
Finally
|
||||
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
|
||||
rList.Clear()
|
||||
End If
|
||||
@@ -856,7 +985,7 @@ Namespace API.Twitter
|
||||
#End Region
|
||||
#Region "IDisposable support"
|
||||
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)
|
||||
End Sub
|
||||
#End Region
|
||||
|
||||
@@ -558,7 +558,7 @@ Namespace API
|
||||
End Sub
|
||||
#End Region
|
||||
#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")
|
||||
End Function
|
||||
Friend Overloads Sub MergeData(ByVal Merging As Boolean)
|
||||
@@ -601,7 +601,19 @@ Namespace API
|
||||
"Operation canceled", MsgBoxStyle.Critical)
|
||||
Return False
|
||||
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)
|
||||
AddRemoveBttDeleteHandler(_Item, False)
|
||||
RaiseEvent OnUserRemoved(_Item)
|
||||
@@ -618,7 +630,7 @@ Namespace API
|
||||
End If
|
||||
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,
|
||||
{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 {
|
||||
.ToolTip = "Users will be removed from the collection and will be displayed in the program as separate users." & vbCr &
|
||||
"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)
|
||||
Return 0
|
||||
Else
|
||||
Collections.ForEach(Sub(ByVal c As IUserData)
|
||||
If c.MoveFiles(String.Empty, Nothing) Then
|
||||
UserListLoader.UpdateUser(Settings.GetUser(c), True)
|
||||
MainFrameObj.ImageHandler(c)
|
||||
End If
|
||||
End Sub)
|
||||
Dim uu As New List(Of SplitCollectionUserInfo)(Collections.Select(Function(uuu As UserDataBase) uuu.SplitCollectionGetNewUserInfo))
|
||||
If uu.All(Function(uuu) uuu.SameDrive) Then
|
||||
uu.Clear()
|
||||
Else
|
||||
Using colPaths As New SplitCollectionUserInfoChangePathsForm(uu)
|
||||
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
|
||||
Settings.Users.Remove(Me)
|
||||
Collections.Clear()
|
||||
|
||||
@@ -59,10 +59,10 @@ Namespace API.YouTube
|
||||
.Cookies.Clear()
|
||||
.Cookies.AddRange(Responser.Cookies)
|
||||
.CookiesUpdated = True
|
||||
.PerformUpdate()
|
||||
End With
|
||||
End If
|
||||
End With
|
||||
DirectCast(MyYouTubeSettings, YTSettings_Internal).PerformUpdate()
|
||||
End If
|
||||
MyBase.Update()
|
||||
End Sub
|
||||
|
||||
@@ -58,7 +58,6 @@ Namespace DownloadObjects
|
||||
End If
|
||||
Catch ex As Exception
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "Change 'ActiveDownloadingProgress' size")
|
||||
MainFrameObj.UpdateLogButton()
|
||||
End Try
|
||||
End Sub
|
||||
Private Sub Downloader_Reconfigured()
|
||||
|
||||
@@ -16,11 +16,13 @@ Imports PersonalUtilities.Tools.Notifications
|
||||
Namespace DownloadObjects
|
||||
Friend Class AutoDownloader : Inherits GroupParameters : Implements IIndexable, IEContainerProvider, IComparable(Of AutoDownloader)
|
||||
Friend Event PauseChanged(ByVal Value As PauseModes)
|
||||
Friend Event PlanChanged As Scheduler.PlanChangedEventHandler
|
||||
Friend Enum Modes As Integer
|
||||
None = 0
|
||||
Specified = 3
|
||||
Groups = 4
|
||||
End Enum
|
||||
Friend Const NoPauseMode As Integer = -100
|
||||
Friend Enum PauseModes As Integer
|
||||
Disabled = -2
|
||||
Enabled = -1
|
||||
@@ -198,6 +200,52 @@ Namespace DownloadObjects
|
||||
Private Const Name_ShowSimpleNotification As String = "ShowSimpleNotification"
|
||||
#End Region
|
||||
#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
|
||||
Private _Mode As Modes = Modes.None
|
||||
Friend Property Mode As Modes
|
||||
@@ -266,11 +314,15 @@ Namespace DownloadObjects
|
||||
End Property
|
||||
Private Function GetWorkingState() As String
|
||||
Dim OutStr$
|
||||
If Working Then
|
||||
If StartupDelay > 0 And _StartTime.AddMinutes(StartupDelay) > Now Then
|
||||
OutStr = $"delayed until {_StartTime.AddMinutes(StartupDelay).ToStringDate(ADateTime.Formats.BaseDateTime)}"
|
||||
If Working And Not IsManual Then
|
||||
If _Downloading Then
|
||||
OutStr = "downloading"
|
||||
ElseIf _ForceStartRequested Then
|
||||
OutStr = "force start pending"
|
||||
ElseIf _StopRequested Then
|
||||
OutStr = "stopping"
|
||||
ElseIf StartupDelay > 0 And _StartTime.AddMinutes(StartupDelay) > Now Then
|
||||
OutStr = $"delayed ({StartupDelay}) until {_StartTime.AddMinutes(StartupDelay).ToStringDate(ADateTime.Formats.BaseDateTime)}"
|
||||
Else
|
||||
OutStr = "working"
|
||||
End If
|
||||
@@ -281,14 +333,26 @@ Namespace DownloadObjects
|
||||
Case Else : OutStr &= $", paused ([{Pause}] until {AConvert(Of String)(_PauseValue, ADateTime.Formats.BaseDateTime, "?")})"
|
||||
End Select
|
||||
End If
|
||||
ElseIf IsManual Then
|
||||
If _Downloading Then
|
||||
OutStr = "downloading"
|
||||
ElseIf _ForceStartRequested Then
|
||||
OutStr = "force start pending"
|
||||
Else
|
||||
OutStr = String.Empty
|
||||
End If
|
||||
Else
|
||||
OutStr = "stopped"
|
||||
End If
|
||||
Return OutStr
|
||||
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
|
||||
If IsManual Then
|
||||
Return $"{Name} (manual): last download date: {GetLastDateString()}"
|
||||
Return $"{Name} (manual{GetWorkingState_Manual()}): last download date: {GetLastDateString()}"
|
||||
Else
|
||||
Return $"{Name} ({GetWorkingState()}): last download date: {GetLastDateString()}; next run: {GetNextDateString()}"
|
||||
End If
|
||||
@@ -315,6 +379,7 @@ Namespace DownloadObjects
|
||||
Friend Sub New(ByVal x As EContainer)
|
||||
Me.New
|
||||
Initialization = True
|
||||
'URGENT: replace this line
|
||||
Dim m% = x.Value(Name_Mode).FromXML(Of Integer)(Modes.None)
|
||||
If m = 1 Or m = 2 Then m = Modes.Specified
|
||||
Mode = m
|
||||
@@ -394,10 +459,10 @@ Namespace DownloadObjects
|
||||
End Function
|
||||
#End Region
|
||||
#Region "Execution"
|
||||
Private AThread As Thread
|
||||
Private _Working As Boolean = False
|
||||
Friend ReadOnly Property Working As Boolean
|
||||
Get
|
||||
Return If(AThread?.IsAlive, False)
|
||||
Return _Working
|
||||
End Get
|
||||
End Property
|
||||
Private _StartTime As Date = Now
|
||||
@@ -405,11 +470,8 @@ Namespace DownloadObjects
|
||||
If Not IsManual Or Force Then
|
||||
If Init Then _StartTime = Now
|
||||
_IsNewPlan = False
|
||||
If Not Working And Not Mode = Modes.None Then
|
||||
AThread = New Thread(New ThreadStart(AddressOf Checker))
|
||||
AThread.SetApartmentState(ApartmentState.MTA)
|
||||
AThread.Start()
|
||||
End If
|
||||
If Not Working And Not Mode = Modes.None Then _Working = True
|
||||
RaiseEvent PlanChanged(Me)
|
||||
End If
|
||||
End Sub
|
||||
Private _StopRequested As Boolean = False
|
||||
@@ -433,6 +495,7 @@ Namespace DownloadObjects
|
||||
Case Else : _PauseValue = Nothing
|
||||
End Select
|
||||
RaiseEvent PauseChanged(p)
|
||||
RaiseEvent PlanChanged(Me)
|
||||
End Set
|
||||
End Property
|
||||
Private ReadOnly Property IsPaused As Boolean
|
||||
@@ -456,7 +519,10 @@ Namespace DownloadObjects
|
||||
End Get
|
||||
End Property
|
||||
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
|
||||
Friend Overloads Sub Skip()
|
||||
If LastDownloadDate.AddMinutes(Timer) <= Now Then
|
||||
@@ -464,65 +530,59 @@ Namespace DownloadObjects
|
||||
Else
|
||||
_LastDownloadDateSkip = LastDownloadDate.AddMinutes(Timer)
|
||||
End If
|
||||
RaiseEvent PlanChanged(Me)
|
||||
End Sub
|
||||
Friend Overloads Sub Skip(ByVal Minutes As Integer)
|
||||
_LastDownloadDateSkip = If(_LastDownloadDateSkip, Now).AddMinutes(Minutes)
|
||||
RaiseEvent PlanChanged(Me)
|
||||
End Sub
|
||||
Friend Overloads Sub Skip(ByVal ToDate As Date)
|
||||
_LastDownloadDateSkip = ToDate
|
||||
RaiseEvent PlanChanged(Me)
|
||||
End Sub
|
||||
Friend Sub SkipReset()
|
||||
_LastDownloadDateSkip = Nothing
|
||||
RaiseEvent PlanChanged(Me)
|
||||
End Sub
|
||||
Friend Sub ForceStart()
|
||||
_ForceStartRequested = True
|
||||
If IsManual Then Start(False, True)
|
||||
RaiseEvent PlanChanged(Me)
|
||||
End Sub
|
||||
Private _ForceStartRequested As Boolean = False
|
||||
Private _SpecialDelayUse As Boolean = False
|
||||
Private _SpecialDelayTime As Date? = Nothing
|
||||
Private Sub Checker()
|
||||
Try
|
||||
Dim _StartDownload As Boolean
|
||||
While (Not _StopRequested Or Downloader.Working) And Not Mode = Modes.None
|
||||
If ((IsManual And _ForceStartRequested) Or (NextExecutionDate < Now And Not IsPaused) Or _ForceStartRequested) And
|
||||
Not _StopRequested And Not Mode = Modes.None Then
|
||||
If Downloader.Working Then
|
||||
_SpecialDelayUse = True
|
||||
Else
|
||||
If _SpecialDelayUse And Not _SpecialDelayTime.HasValue Then _SpecialDelayTime = Now.AddSeconds(10)
|
||||
If Not _SpecialDelayUse OrElse (_SpecialDelayTime.HasValue AndAlso _SpecialDelayTime.Value < Now) Then
|
||||
_SpecialDelayUse = False
|
||||
_SpecialDelayTime = Nothing
|
||||
_StartDownload = False
|
||||
If Settings.Automation.Count = 1 Or _ForceStartRequested Or Index = -1 Then
|
||||
_StartDownload = True
|
||||
Else
|
||||
_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
|
||||
Friend ReadOnly Property ForceStartRequested As Boolean
|
||||
Get
|
||||
Return _ForceStartRequested
|
||||
End Get
|
||||
End Property
|
||||
Friend ReadOnly Property DownloadReady(Optional ByVal IgnorePause As Boolean = False, Optional ByVal IgnoreDownloaderWorking As Boolean = False) As Boolean
|
||||
Get
|
||||
If _StopRequested Then _Working = False
|
||||
Return (Working Or IsManual) And ((IsManual And _ForceStartRequested) Or (Not IsManual And NextExecutionDate < Now And (Not IsPaused Or IgnorePause)) Or _ForceStartRequested) And
|
||||
Not _StopRequested And Not Mode = Modes.None And (Not Downloader.Working Or IgnoreDownloaderWorking)
|
||||
End Get
|
||||
End Property
|
||||
Friend ReadOnly Property NextDate As Date?
|
||||
Get
|
||||
If Not _StopRequested And Not Mode = Modes.None Then
|
||||
If IsManual Or _ForceStartRequested Then
|
||||
Return Now.AddYears(-10)
|
||||
ElseIf Not IsPaused And Not IsManual And Working Then
|
||||
Return NextExecutionDate
|
||||
End If
|
||||
Thread.Sleep(500)
|
||||
End While
|
||||
Catch ex As Exception
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[AutoDownloader.Checker]")
|
||||
Finally
|
||||
_StopRequested = False
|
||||
End Try
|
||||
End Sub
|
||||
End If
|
||||
Return Nothing
|
||||
End Get
|
||||
End Property
|
||||
Private _Downloading As Boolean = False
|
||||
Friend ReadOnly Property Downloading As Boolean
|
||||
Get
|
||||
Return _Downloading
|
||||
End Get
|
||||
End Property
|
||||
Private Sub Download()
|
||||
Friend Sub Download()
|
||||
_Downloading = True
|
||||
RaiseEvent PlanChanged(Me)
|
||||
Dim Keys As New List(Of String)
|
||||
Try
|
||||
Dim users As New List(Of IUserData)
|
||||
@@ -572,11 +632,23 @@ Namespace DownloadObjects
|
||||
With Downloader
|
||||
.AutoDownloaderWorking = True
|
||||
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
|
||||
.AutoDownloaderWorking = False
|
||||
notify.Invoke
|
||||
If simple And DownloadedUsersCount + DownloadedSubscriptionsCount > 0 Then
|
||||
If simple And (DownloadedUsersCount + DownloadedSubscriptionsCount) > 0 Then
|
||||
Dim msg$ = String.Empty
|
||||
If DownloadedUsersCount > 0 Then msg = $"{DownloadedUsersCount} user(s) "
|
||||
If DownloadedSubscriptionsCount > 0 Then msg &= $"{IIf(DownloadedUsersCount > 0, "and ", String.Empty)}{DownloadedSubscriptionsCount} subscription(s) "
|
||||
@@ -586,7 +658,7 @@ Namespace DownloadObjects
|
||||
End With
|
||||
End If
|
||||
Catch ex As Exception
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[AutoDownloader.Download]")
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, $"[AutoDownloader.Download({Name})]")
|
||||
Finally
|
||||
Keys.Clear()
|
||||
LastDownloadDate = Now
|
||||
@@ -594,6 +666,8 @@ Namespace DownloadObjects
|
||||
_Downloading = False
|
||||
_ForceStartRequested = False
|
||||
_LastDownloadDateSkip = Nothing
|
||||
If _StopRequested Then _Working = False
|
||||
RaiseEvent PlanChanged(Me)
|
||||
End Try
|
||||
End Sub
|
||||
Private Sub ShowNotification(ByVal u As IUserData)
|
||||
|
||||
@@ -28,9 +28,10 @@ Namespace DownloadObjects
|
||||
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 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 TP_NOTIFY As System.Windows.Forms.TableLayoutPanel
|
||||
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
|
||||
Me.DEF_GROUP = New SCrawler.DownloadObjects.Groups.GroupDefaults()
|
||||
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.Name = "Edit"
|
||||
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(ActionButton2)
|
||||
Me.TXT_GROUPS.Buttons.Add(ActionButton3)
|
||||
Me.TXT_GROUPS.CaptionText = "Groups"
|
||||
Me.TXT_GROUPS.CaptionWidth = 50.0R
|
||||
Me.TXT_GROUPS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
@@ -260,9 +266,9 @@ Namespace DownloadObjects
|
||||
'
|
||||
'TXT_TIMER
|
||||
'
|
||||
ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image)
|
||||
ActionButton3.Name = "Refresh"
|
||||
Me.TXT_TIMER.Buttons.Add(ActionButton3)
|
||||
ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image)
|
||||
ActionButton4.Name = "Refresh"
|
||||
Me.TXT_TIMER.Buttons.Add(ActionButton4)
|
||||
Me.TXT_TIMER.CaptionText = "Timer"
|
||||
Me.TXT_TIMER.CaptionToolTipEnabled = True
|
||||
Me.TXT_TIMER.CaptionToolTipText = "Timer (in minutes)"
|
||||
@@ -275,9 +281,9 @@ Namespace DownloadObjects
|
||||
'
|
||||
'NUM_DELAY
|
||||
'
|
||||
ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image)
|
||||
ActionButton4.Name = "Refresh"
|
||||
Me.NUM_DELAY.Buttons.Add(ActionButton4)
|
||||
ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image)
|
||||
ActionButton5.Name = "Refresh"
|
||||
Me.NUM_DELAY.Buttons.Add(ActionButton5)
|
||||
Me.NUM_DELAY.CaptionText = "Delay"
|
||||
Me.NUM_DELAY.CaptionToolTipEnabled = True
|
||||
Me.NUM_DELAY.CaptionToolTipText = "Startup delay"
|
||||
|
||||
@@ -189,6 +189,18 @@
|
||||
</value>
|
||||
</data>
|
||||
<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>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
||||
@@ -203,22 +215,6 @@
|
||||
<value>Show a simple notification instead of a user notification.
|
||||
This means that if any user data has been downloaded with the plan, a simple notification will be shown with the number of users downloaded.
|
||||
The 'Image' and 'User icon' parameters will be ignored.</value>
|
||||
</data>
|
||||
<data name="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 name="ActionButton4.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
@@ -234,6 +230,22 @@ The 'Image' and 'User icon' parameters will be ignored.</value>
|
||||
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
|
||||
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
|
||||
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>
|
||||
</data>
|
||||
</root>
|
||||
@@ -134,11 +134,26 @@ Namespace DownloadObjects
|
||||
Private Sub TXT_GROUPS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles TXT_GROUPS.ActionOnButtonClick
|
||||
Select Case Sender.DefaultButton
|
||||
Case ActionButton.DefaultButtons.Edit
|
||||
Using f As New LabelsForm(MyGroups, (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()
|
||||
If f.DialogResult = DialogResult.OK Then MyGroups.ListAddList(f.LabelsList, LAP.ClearBeforeAdd) : TXT_GROUPS.Text = MyGroups.ListToString
|
||||
End Using
|
||||
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 Sub
|
||||
Private Sub ChangeEnabled() Handles OPT_DISABLED.CheckedChanged,
|
||||
|
||||
@@ -14,15 +14,19 @@ Imports PauseModes = SCrawler.DownloadObjects.AutoDownloader.PauseModes
|
||||
Namespace DownloadObjects
|
||||
Friend Class Scheduler : Implements IEnumerable(Of AutoDownloader), IMyEnumerator(Of AutoDownloader), IDisposable
|
||||
Friend Const Name_Plan As String = "Plan"
|
||||
Friend Delegate Sub PlanChangedEventHandler(ByVal Plan As AutoDownloader)
|
||||
Friend Event PauseChanged As AutoDownloader.PauseChangedEventHandler
|
||||
Private Sub OnPauseChanged(ByVal Value As PauseModes)
|
||||
RaiseEvent PauseChanged(Pause)
|
||||
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)
|
||||
Friend Const FileNameDefault As String = "AutoDownload"
|
||||
Friend ReadOnly FileDefault As SFile = $"{SettingsFolderName}\{FileNameDefault}.xml"
|
||||
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 PlansWaiter As Action(Of Predicate(Of AutoDownloader)) = Sub(ByVal Predicate As Predicate(Of AutoDownloader))
|
||||
While Plans.Exists(Predicate) : Thread.Sleep(200) : End While
|
||||
@@ -69,6 +73,7 @@ Namespace DownloadObjects
|
||||
Friend Sub Add(ByVal Plan As AutoDownloader)
|
||||
Plan.Source = Me
|
||||
AddHandler Plan.PauseChanged, AddressOf OnPauseChanged
|
||||
AddHandler Plan.PlanChanged, AddressOf OnPlanChanged
|
||||
Plans.Add(Plan)
|
||||
Plans.ListReindex
|
||||
Update()
|
||||
@@ -77,9 +82,9 @@ Namespace DownloadObjects
|
||||
If Index.ValueBetween(0, Count - 1) Then
|
||||
With Plans(Index)
|
||||
.Stop()
|
||||
If .Working Then
|
||||
If .Downloading Then
|
||||
Await Task.Run(Sub()
|
||||
While .Working : Thread.Sleep(510) : End While
|
||||
While .Downloading : Thread.Sleep(510) : End While
|
||||
End Sub)
|
||||
End If
|
||||
.Dispose()
|
||||
@@ -103,10 +108,10 @@ Namespace DownloadObjects
|
||||
End Try
|
||||
End Sub
|
||||
Friend Function Reset(ByVal f As SFile, ByVal IsInit As Boolean) As Boolean
|
||||
If Plans.Count > 0 Then
|
||||
If Not Plans.Exists(PlanWorking) Then
|
||||
If Count > 0 Then
|
||||
If Not Plans.Exists(PlanDownloading) Then
|
||||
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.",
|
||||
"Change scheduler"}, vbCritical)
|
||||
Pause = PauseModes.Unlimited
|
||||
@@ -114,6 +119,7 @@ Namespace DownloadObjects
|
||||
End If
|
||||
End If
|
||||
[Stop]()
|
||||
While Working : Thread.Sleep(200) : End While
|
||||
If _UpdateRequired Then Update()
|
||||
Plans.ListClearDispose(,, EDP.LogMessageValue)
|
||||
End If
|
||||
@@ -127,11 +133,12 @@ Namespace DownloadObjects
|
||||
Plans.Add(New AutoDownloader(x))
|
||||
End If
|
||||
End Using
|
||||
If Plans.Count > 0 Then Plans.ForEach(Sub(ByVal p As AutoDownloader)
|
||||
p.Source = Me
|
||||
If Not IsInit Then p.Pause = PauseModes.Unlimited
|
||||
AddHandler p.PauseChanged, AddressOf OnPauseChanged
|
||||
End Sub) : Plans.ListReindex
|
||||
If Count > 0 Then Plans.ForEach(Sub(ByVal p As AutoDownloader)
|
||||
p.Source = Me
|
||||
If Not IsInit Then p.Pause = PauseModes.Unlimited
|
||||
AddHandler p.PauseChanged, AddressOf OnPauseChanged
|
||||
AddHandler p.PlanChanged, AddressOf OnPlanChanged
|
||||
End Sub) : Plans.ListReindex
|
||||
End If
|
||||
Return True
|
||||
End Function
|
||||
@@ -163,38 +170,94 @@ Namespace DownloadObjects
|
||||
End Sub
|
||||
#End Region
|
||||
#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
|
||||
Try
|
||||
_StopRequested = False
|
||||
Await Task.Run(Sub()
|
||||
Dim r% = 0
|
||||
Do
|
||||
r += 1
|
||||
Try
|
||||
If Count > 0 Then
|
||||
If Plans.Exists(PlanDownloading) Then PlansWaiter(PlanDownloading)
|
||||
For Each Plan In Plans
|
||||
Plan.Start(Init)
|
||||
PlansWaiter(PlanDownloading)
|
||||
Thread.Sleep(1000)
|
||||
Next
|
||||
End If
|
||||
If Count > 0 Then PlansWaiter(PlanDownloading) : Plans.ForEach(Sub(p) p.Start(Init))
|
||||
Exit Do
|
||||
Catch io_ex As InvalidOperationException 'Collection was modified; enumeration operation may not execute
|
||||
End Try
|
||||
Loop While r < 10
|
||||
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
|
||||
If Init Then
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "Start automation")
|
||||
MainFrameObj.UpdateLogButton()
|
||||
Else
|
||||
Throw ex
|
||||
End If
|
||||
End Try
|
||||
End Function
|
||||
Friend Sub [Stop]()
|
||||
If Working Then _StopRequested = True
|
||||
If Count > 0 Then Plans.ForEach(Sub(p) p.Stop())
|
||||
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
|
||||
Get
|
||||
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 disposing Then
|
||||
[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()
|
||||
Plans.ListClearDispose
|
||||
End If
|
||||
|
||||
@@ -23,7 +23,8 @@ Namespace DownloadObjects
|
||||
<System.Diagnostics.DebuggerStepThrough()>
|
||||
Private Sub InitializeComponent()
|
||||
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.ContentPanel.SuspendLayout()
|
||||
CONTAINER_MAIN.SuspendLayout()
|
||||
@@ -47,12 +48,25 @@ Namespace DownloadObjects
|
||||
'
|
||||
'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.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.MultiSelect = False
|
||||
Me.LIST_PLANS.Name = "LIST_PLANS"
|
||||
Me.LIST_PLANS.ShowGroups = False
|
||||
Me.LIST_PLANS.Size = New System.Drawing.Size(414, 316)
|
||||
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
|
||||
'
|
||||
@@ -63,7 +77,6 @@ Namespace DownloadObjects
|
||||
Me.KeyPreview = True
|
||||
Me.MinimumSize = New System.Drawing.Size(430, 380)
|
||||
Me.Name = "SchedulerEditorForm"
|
||||
Me.ShowIcon = True
|
||||
Me.ShowInTaskbar = False
|
||||
Me.Text = "Scheduler"
|
||||
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
|
||||
@@ -72,6 +85,7 @@ Namespace DownloadObjects
|
||||
Me.ResumeLayout(False)
|
||||
|
||||
End Sub
|
||||
Private WithEvents LIST_PLANS As ListBox
|
||||
Private WithEvents LIST_PLANS As ListView
|
||||
Private WithEvents COL_MAIN As ColumnHeader
|
||||
End Class
|
||||
End Namespace
|
||||
@@ -6,8 +6,12 @@
|
||||
'
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Imports System.Threading
|
||||
Imports System.ComponentModel
|
||||
Imports PersonalUtilities.Forms
|
||||
Imports PersonalUtilities.Forms.Toolbars
|
||||
Imports PersonalUtilities.Forms.Controls.Base
|
||||
Imports PersonalUtilities.Functions.XML
|
||||
Imports PersonalUtilities.Tools
|
||||
Imports ECI = PersonalUtilities.Forms.Toolbars.EditToolbar.ControlItem
|
||||
Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons
|
||||
@@ -129,6 +133,16 @@ Namespace DownloadObjects
|
||||
SetTitle()
|
||||
.EndLoaderOperations(False)
|
||||
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
|
||||
Private Sub SchedulerEditorForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
|
||||
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
|
||||
PauseArr.Dispose()
|
||||
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
|
||||
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 Sub Refill() Handles MyDefs.ButtonUpdateClick
|
||||
Try
|
||||
If Not _RefillInProgress Then
|
||||
_RefillInProgress = True
|
||||
LIST_PLANS.Items.Clear()
|
||||
If Settings.Automation.Count > 0 Then
|
||||
LIST_PLANS.Items.AddRange(Settings.Automation.Select(Function(a) a.ToString()).Cast(Of Object).ToArray)
|
||||
If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then LIST_PLANS.SelectedIndex = _LatestSelected
|
||||
Else
|
||||
_LatestSelected = -1
|
||||
ControlInvokeFast(LIST_PLANS,
|
||||
Sub()
|
||||
If Not _RefillInProgress Then
|
||||
_RefillInProgress = True
|
||||
With LIST_PLANS.Items
|
||||
.Clear()
|
||||
If Settings.Automation.Count > 0 Then
|
||||
.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
|
||||
_RefillInProgress = False
|
||||
End If
|
||||
End Sub)
|
||||
Catch ex As Exception
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[DownloadObjects.SchedulerEditorForm.Refill]")
|
||||
End Try
|
||||
@@ -194,7 +235,7 @@ Namespace DownloadObjects
|
||||
Private Sub Edit() Handles MyDefs.ButtonEditClick
|
||||
If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then
|
||||
Using f As New AutoDownloaderEditorForm(Settings.Automation(_LatestSelected)) : f.ShowDialog() : End Using
|
||||
Refill()
|
||||
LIST_PLANS_Refresh(_LatestSelected)
|
||||
Else
|
||||
MsgBoxE("You have not selected a plan to edit.", vbExclamation)
|
||||
End If
|
||||
@@ -222,19 +263,83 @@ Namespace DownloadObjects
|
||||
#End Region
|
||||
#Region "List handlers"
|
||||
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
|
||||
_LatestSelected = LIST_PLANS.SelectedIndex
|
||||
PauseArr.PlanIndex = _LatestSelected
|
||||
PauseArr.UpdatePauseButtons(False)
|
||||
If _LatestSelectedChangeEnabled Then
|
||||
_LatestSelected = ListSelectedIndex
|
||||
PauseArr.PlanIndex = _LatestSelected
|
||||
PauseArr.UpdatePauseButtons(False)
|
||||
End If
|
||||
End Sub
|
||||
Private Sub LIST_PLANS_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles LIST_PLANS.MouseDoubleClick
|
||||
Edit()
|
||||
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
|
||||
#Region "Settings, Start, Skip, Pause"
|
||||
Private Function GetSchedulerFiles() As List(Of SFile)
|
||||
Return SFile.GetFiles(SettingsFolderName.CSFileP, $"{Scheduler.FileNameDefault}*.xml",, EDP.ReturnValue)
|
||||
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
|
||||
Const msgTitle$ = "Change scheduler"
|
||||
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)))
|
||||
End With
|
||||
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",
|
||||
.Icon = ImageRenderer.GetIcon(My.Resources.ScriptPic_32, EDP.ReturnValue),
|
||||
.FormText = "Schedulers",
|
||||
@@ -256,17 +361,56 @@ Namespace DownloadObjects
|
||||
Dim f As SFile
|
||||
Dim selectedName$
|
||||
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()
|
||||
.Buttons = {ADB.Add, ADB.Delete}
|
||||
.Buttons = {ADB.Add, ADB.SaveAs, ADB.Delete}
|
||||
AddHandler .AddClick, Sub(ByVal obj As Object, ByVal args As SimpleListFormEventArgs)
|
||||
If addedObj.IsEmptyString Then
|
||||
addedObj = InputBoxE("Enter a new scheduler name:", msgTitle)
|
||||
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
|
||||
MsgBoxE({"You can only create one scheduler at a time", "Create a new scheduler"}, vbCritical)
|
||||
End If
|
||||
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
|
||||
.DataSelectedIndexes.Add(0)
|
||||
Else
|
||||
@@ -279,7 +423,7 @@ Namespace DownloadObjects
|
||||
If selectedName = defName Then
|
||||
f = Settings.Automation.FileDefault
|
||||
Else
|
||||
f = $"{SettingsFolderName}\{Scheduler.FileNameDefault}_{selectedName.StringRemoveWinForbiddenSymbols}.xml"
|
||||
f = createSchedulerPath.Invoke(selectedName)
|
||||
End If
|
||||
If Not Settings.Automation.File = f AndAlso Settings.Automation.Reset(f, False) Then
|
||||
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
|
||||
If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then
|
||||
With Settings.Automation(_LatestSelected) : .Start(.IsNewPlan) : End With
|
||||
Refill()
|
||||
LIST_PLANS_Refresh(_LatestSelected)
|
||||
End If
|
||||
End Sub
|
||||
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
|
||||
With Settings.Automation(_LatestSelected)
|
||||
If .Working Or .IsManual Then .ForceStart() : Refill()
|
||||
If .Working Or .IsManual Then .ForceStart() : LIST_PLANS_Refresh(_LatestSelected)
|
||||
End With
|
||||
End If
|
||||
End Sub
|
||||
@@ -328,10 +472,10 @@ Namespace DownloadObjects
|
||||
Select Case mode
|
||||
Case String.Empty
|
||||
Settings.Automation(_LatestSelected).Skip()
|
||||
Refill()
|
||||
LIST_PLANS_Refresh(_LatestSelected)
|
||||
Case "m"
|
||||
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"
|
||||
Dim d As Date? = Nothing
|
||||
Using f As New DateTimeSelectionForm(DateTimeSelectionForm.Modes.Date +
|
||||
@@ -342,16 +486,13 @@ Namespace DownloadObjects
|
||||
f.ShowDialog()
|
||||
If f.DialogResult = DialogResult.OK Then d = f.MyDateStart
|
||||
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"
|
||||
Settings.Automation(_LatestSelected).SkipReset()
|
||||
Refill()
|
||||
LIST_PLANS_Refresh(_LatestSelected)
|
||||
End Select
|
||||
End If
|
||||
End Sub
|
||||
Private Sub PauseArr_Updating() Handles PauseArr.Updating
|
||||
Refill()
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Move"
|
||||
Private Sub BTT_MOVE_UP_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_MOVE_UP.Click, BTT_MOVE_DOWN.Click
|
||||
|
||||
83
SCrawler/Download/Feed/DownloadFeedForm.Designer.vb
generated
@@ -35,6 +35,7 @@ Namespace DownloadObjects
|
||||
Dim MENU_LOAD_SEP_7 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_9 As System.Windows.Forms.ToolStripSeparator
|
||||
Me.OPT_DEFAULT = New System.Windows.Forms.ToolStripMenuItem()
|
||||
Me.OPT_SUBSCRIPTIONS = New System.Windows.Forms.ToolStripMenuItem()
|
||||
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_DAILY_LIST = 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_CLEAR_DAILY = 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_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.MENU_DOWN = New System.Windows.Forms.ToolStripDropDownButton()
|
||||
Me.BTT_DOWN_ALL = New System.Windows.Forms.ToolStripMenuItem()
|
||||
Me.BTT_DOWN_SELECTED = New System.Windows.Forms.ToolStripMenuItem()
|
||||
Me.BTT_REFRESH = New System.Windows.Forms.ToolStripButton()
|
||||
Me.TP_DATA = New System.Windows.Forms.TableLayoutPanel()
|
||||
Me.BTT_VIEW_SAVE = New System.Windows.Forms.ToolStripMenuItem()
|
||||
Me.BTT_VIEW_LOAD = New System.Windows.Forms.ToolStripMenuItem()
|
||||
Me.BTT_COPY_SPEC_TO = 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_2 = New System.Windows.Forms.ToolStripSeparator()
|
||||
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_0 = 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.SuspendLayout()
|
||||
'
|
||||
@@ -157,6 +163,11 @@ Namespace DownloadObjects
|
||||
MENU_LOAD_SEP_0.Name = "MENU_LOAD_SEP_0"
|
||||
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
|
||||
'
|
||||
Me.ToolbarTOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden
|
||||
@@ -170,7 +181,7 @@ Namespace DownloadObjects
|
||||
'
|
||||
Me.MENU_LOAD_SESSION.AutoToolTip = False
|
||||
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.ImageTransparentColor = System.Drawing.Color.Magenta
|
||||
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.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
|
||||
'
|
||||
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.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
|
||||
'
|
||||
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.TabIndex = 1
|
||||
'
|
||||
'MENU_LOAD_SEP_8
|
||||
'MENU_LOAD_SEP_9
|
||||
'
|
||||
MENU_LOAD_SEP_8.Name = "MENU_LOAD_SEP_8"
|
||||
MENU_LOAD_SEP_8.Size = New System.Drawing.Size(349, 6)
|
||||
MENU_LOAD_SEP_9.Name = "MENU_LOAD_SEP_9"
|
||||
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_VIEW_SAVE.Size = New System.Drawing.Size(352, 22)
|
||||
Me.BTT_VIEW_SAVE.Text = "Save current view"
|
||||
Me.BTT_COPY_SPEC_TO.AutoToolTip = True
|
||||
Me.BTT_COPY_SPEC_TO.Image = Global.SCrawler.My.Resources.Resources.PastePic_32
|
||||
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_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"
|
||||
Me.BTT_MOVE_SPEC_TO.AutoToolTip = True
|
||||
Me.BTT_MOVE_SPEC_TO.Image = Global.SCrawler.My.Resources.Resources.CutPic_48
|
||||
Me.BTT_MOVE_SPEC_TO.Name = "BTT_MOVE_SPEC_TO"
|
||||
Me.BTT_MOVE_SPEC_TO.Size = New System.Drawing.Size(352, 22)
|
||||
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
|
||||
'
|
||||
@@ -483,5 +530,9 @@ Namespace DownloadObjects
|
||||
Private WithEvents BTT_MOVE_TO As ToolStripMenuItem
|
||||
Private WithEvents BTT_VIEW_SAVE 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 Namespace
|
||||
@@ -159,10 +159,13 @@
|
||||
<metadata name="MENU_LOAD_SEP_0.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
<metadata name="ToolbarTOP.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="MENU_LOAD_SEP_8.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
<metadata name="ToolbarTOP.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="MENU_LOAD_SEP_9.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
</root>
|
||||
@@ -276,7 +276,6 @@ Namespace DownloadObjects
|
||||
End With
|
||||
Catch ex As Exception
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "Feed removed")
|
||||
MainFrameObj.UpdateLogButton()
|
||||
End Try
|
||||
End Sub
|
||||
Private Sub Feed_SPEC_LOAD(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs)
|
||||
@@ -440,7 +439,9 @@ Namespace DownloadObjects
|
||||
End Sub
|
||||
Private Sub SessionChooser(ByVal GetLast As Boolean, Optional ByVal GetFilesOnly As Boolean = False,
|
||||
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
|
||||
LoadedSessionName = String.Empty
|
||||
Downloader.ClearSessions()
|
||||
@@ -475,6 +476,12 @@ Namespace DownloadObjects
|
||||
If fList.ListExists Then
|
||||
If GetFilesOnly Then
|
||||
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
|
||||
DataList.Clear()
|
||||
If SelectedMode >= 0 Then
|
||||
@@ -533,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
|
||||
MoveCopyFiles(True, sender, Nothing, Nothing)
|
||||
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"
|
||||
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 ff As SFile = Nothing, df As SFile
|
||||
Dim data As IEnumerable(Of UserMediaD) = Nothing
|
||||
Dim dd As UserMediaD
|
||||
Dim __user As UserInfo
|
||||
Dim data_files As IEnumerable(Of SFile) = Nothing
|
||||
Dim new_files As New List(Of SFile)
|
||||
Dim mm As UserMediaD
|
||||
@@ -559,7 +571,12 @@ Namespace DownloadObjects
|
||||
Dim result As Boolean = False
|
||||
|
||||
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
|
||||
If .ListExists Then data_files = .Select(Function(m) m.Data.File)
|
||||
End With
|
||||
@@ -580,7 +597,6 @@ Namespace DownloadObjects
|
||||
With moveOptions
|
||||
If Not .Destination.IsEmptyString And .ReplaceUserProfile And .ReplaceUserProfile_CreateIfNull And .ReplaceUserProfile_Profile Is Nothing Then
|
||||
Dim existingPathInstances As IEnumerable(Of String) = Nothing
|
||||
Dim __user As UserInfo
|
||||
Dim __host As Plugin.Hosts.SettingsHost = Settings(API.PathPlugin.PluginKey).Default
|
||||
Dim __userName$ = .Destination.Segments.LastOrDefault
|
||||
If Settings.UsersList.Count > 0 Then _
|
||||
@@ -652,9 +668,11 @@ Namespace DownloadObjects
|
||||
indx = Downloader.Files.FindIndex(finder)
|
||||
If indx >= 0 Then
|
||||
mm = Downloader.Files(indx)
|
||||
__user = mm.UserInfo
|
||||
mm_data = mm.Data
|
||||
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
|
||||
downloaderFilesUpdated = True
|
||||
End If
|
||||
@@ -680,9 +698,11 @@ Namespace DownloadObjects
|
||||
indx = sessionData.FindIndex(finder)
|
||||
If indx >= 0 Then
|
||||
mm = sessionData(indx)
|
||||
__user = mm.UserInfo
|
||||
mm_data = mm.Data
|
||||
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
|
||||
sesFilesReplaced = True
|
||||
If DataList.Count > 0 Then
|
||||
@@ -861,7 +881,6 @@ Namespace DownloadObjects
|
||||
End If
|
||||
Catch ex As Exception
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "Delete daily sessions (by list)")
|
||||
MainFrameObj.UpdateLogButton()
|
||||
End Try
|
||||
End Sub
|
||||
Private Sub BTT_FEED_DELETE_DAILY_DATE_Click(sender As Object, e As EventArgs) Handles BTT_FEED_DELETE_DAILY_DATE.Click
|
||||
@@ -899,20 +918,23 @@ Namespace DownloadObjects
|
||||
End Using
|
||||
Catch ex As Exception
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "Delete daily sessions (by date)")
|
||||
MainFrameObj.UpdateLogButton()
|
||||
End Try
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Clear session"
|
||||
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
|
||||
#Region "Sessions set, merge, clear"
|
||||
Private Sub BTT_CURR_SESSION_SET_Click(sender As Object, e As EventArgs) Handles BTT_CURR_SESSION_SET.Click
|
||||
Try
|
||||
Dim f As SFile = Nothing
|
||||
SessionChooser(False,,,, True, f)
|
||||
If Not f.IsEmptyString AndAlso f.Exists Then
|
||||
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 Region
|
||||
#Region "Merge feeds"
|
||||
Private Sub BTT_MERGE_SESSIONS_Click(sender As Object, e As EventArgs) Handles BTT_MERGE_SESSIONS.Click
|
||||
Try
|
||||
Const msgTitle$ = "Merge feeds"
|
||||
@@ -973,6 +995,23 @@ Namespace DownloadObjects
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[DownloadFeedForm.MergeSessions]")
|
||||
End Try
|
||||
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
|
||||
Try
|
||||
Const msgTitle$ = "Merge feeds"
|
||||
|
||||
@@ -221,8 +221,8 @@ Namespace DownloadObjects
|
||||
Information = $"Type: {Media.Data.Type}"
|
||||
Information.StringAppendLine($"File: {File.File}")
|
||||
Information.StringAppendLine($"Address: {File}")
|
||||
Information.StringAppendLine($"Downloaded: {Media.Date.ToStringDate(ADateTime.Formats.BaseDateTime)}")
|
||||
If Media.Data.Post.Date.HasValue Then Information.StringAppendLine($"Posted: {Media.Data.Post.Date.Value.ToStringDate(ADateTime.Formats.BaseDateTime)}")
|
||||
Information.StringAppendLine($"Downloaded: {Media.Date.ToStringDateDef}")
|
||||
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 h%
|
||||
Dim s As Size
|
||||
@@ -267,23 +267,27 @@ Namespace DownloadObjects
|
||||
BTT_CONTEXT_OPEN_MEDIA.Text &= " video"
|
||||
BTT_CONTEXT_DELETE.Text &= " video"
|
||||
h = VideoHeight
|
||||
AddHandler MyVideo.DoubleClick, AddressOf MyPicture_DoubleClick
|
||||
Case Else : Throw New ArgumentNullException With {.HelpLink = 1}
|
||||
End Select
|
||||
|
||||
Dim info$ = $"[{infoType}] - "
|
||||
Dim info$ = If(Settings.FeedAddTypeToCaption.Value And Not IsSubscription, $"[{infoType}] - ", String.Empty)
|
||||
|
||||
If Not Media.User Is Nothing Then
|
||||
With Media.User
|
||||
Dim otherName$ = If(Media.IsSavedPosts, "Saved", Media.UserInfo.Name)
|
||||
Dim site$ = If(Settings.FeedAddSiteToCaption.Value, $"{ .Site} - ", String.Empty)
|
||||
|
||||
UserKey = .Key
|
||||
Information &= vbNewLine.StringDup(2)
|
||||
If .IncludedInCollection Then Information.StringAppendLine($"User collection: { .CollectionName}")
|
||||
Information.StringAppendLine($"User site: { .Site}")
|
||||
Information.StringAppendLine($"User name: {IIf(Not .FriendlyName.IsEmptyString And Not .IncludedInCollection, .FriendlyName, .Name)}")
|
||||
Information.StringAppendLine($"User name: {CStr(IIf(Not .FriendlyName.IsEmptyString And Not .IncludedInCollection, .FriendlyName, .Name)).IfNullOrEmpty(otherName)}")
|
||||
If .IncludedInCollection Then info &= $"[{ .CollectionName}]: "
|
||||
If Settings.FeedShowFriendlyNames Or Not DirectCast(.Self, UserDataBase).FeedIsUser Then
|
||||
info &= $"{ .Site} - { .FriendlyName.IfNullOrEmpty(.Name)}"
|
||||
info &= $"{site}{ .FriendlyName.IfNullOrEmpty(.Name).IfNullOrEmpty(otherName)}"
|
||||
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 With
|
||||
End If
|
||||
|
||||
@@ -139,7 +139,6 @@ Namespace DownloadObjects
|
||||
End If
|
||||
Catch ex As Exception
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[FeedSpecial.UpdateUsers]")
|
||||
MainFrameObj.UpdateLogButton()
|
||||
End Try
|
||||
End Sub
|
||||
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 path$ = InitialUser.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.Data.File.PathWithSeparator.Contains(path) Then
|
||||
data = Item.Data
|
||||
@@ -158,7 +158,7 @@ Namespace DownloadObjects
|
||||
user = Item.User
|
||||
End If
|
||||
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
|
||||
Return Item
|
||||
End If
|
||||
@@ -175,8 +175,10 @@ Namespace DownloadObjects
|
||||
If indx >= 0 Then
|
||||
Dim m As UserMediaD = Items(indx)
|
||||
Dim mm As UserMedia = m.Data
|
||||
Dim user As UserInfo = m.UserInfo
|
||||
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
|
||||
_FilesUpdated = True
|
||||
End If
|
||||
|
||||
@@ -111,7 +111,6 @@ Namespace DownloadObjects
|
||||
End If
|
||||
Catch ex As Exception
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[FeedSpecialCollection.Load]")
|
||||
MainFrameObj.UpdateLogButton()
|
||||
End Try
|
||||
End Sub
|
||||
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)
|
||||
Try
|
||||
Load()
|
||||
If Count > 0 Then
|
||||
If Count > 0 AndAlso Not UserInfo.ExactEquals(InitialUser, NewUser) Then
|
||||
Feeds.ForEach(Sub(f) f.UpdateUsers(InitialUser, NewUser))
|
||||
If Downloader.Files.Count > 0 Then
|
||||
PendingUsersToUpdate.Add(New KeyValuePair(Of UserInfo, UserInfo)(InitialUser, NewUser))
|
||||
@@ -245,7 +244,6 @@ Namespace DownloadObjects
|
||||
End If
|
||||
Catch ex As Exception
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[FeedSpecialCollection.UpdateUsers]")
|
||||
MainFrameObj.UpdateLogButton()
|
||||
End Try
|
||||
End Sub
|
||||
#End Region
|
||||
|
||||
@@ -176,5 +176,9 @@ Namespace DownloadObjects
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, $"An error occurred while performing action [{ActionName}] on file [{MediaFile}]")
|
||||
End Try
|
||||
End Function
|
||||
Private Sub MyVideo_DoubleClick(sender As Object, e As EventArgs) Handles MyVideo.DoubleClick
|
||||
[Stop]()
|
||||
OnDoubleClick(e)
|
||||
End Sub
|
||||
End Class
|
||||
End Namespace
|
||||
@@ -20,6 +20,7 @@ Namespace DownloadObjects.Groups
|
||||
Private Const Name_FilterViewMode As String = "FilterViewMode"
|
||||
Private Const Name_FilterGroupUsers As String = "FilterGroupUsers"
|
||||
Private Const Name_FilterShowGroupsInsteadLabels As String = "FilterShowGroupsInsteadLabels"
|
||||
Private Const Name_FilterShowAllUsers As String = "FilterShowAllUsers"
|
||||
#End Region
|
||||
#Region "Declarations"
|
||||
#Region "Controls"
|
||||
@@ -36,6 +37,7 @@ Namespace DownloadObjects.Groups
|
||||
Friend Property FilterViewMode As ViewModes = ViewModes.IconLarge
|
||||
Friend Property FilterGroupUsers As Boolean = True
|
||||
Friend Property FilterShowGroupsInsteadLabels As Boolean = True
|
||||
Friend Property FilterShowAllUsers As Boolean = False
|
||||
#End Region
|
||||
Private File As SFile = Nothing
|
||||
Friend Overrides Property Name As String
|
||||
@@ -144,13 +146,15 @@ Namespace DownloadObjects.Groups
|
||||
FilterViewMode = e.Value(Name_FilterViewMode).FromXML(Of Integer)(ViewModes.IconLarge)
|
||||
FilterGroupUsers = e.Value(Name_FilterGroupUsers).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 Sub
|
||||
Protected Overrides Function Export(ByVal e As EContainer) As EContainer
|
||||
MyBase.Export(e)
|
||||
e.AddRange({New EContainer(Name_FilterViewMode, CInt(FilterViewMode)),
|
||||
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
|
||||
End Function
|
||||
#End Region
|
||||
@@ -166,6 +170,7 @@ Namespace DownloadObjects.Groups
|
||||
FilterViewMode = .FilterViewMode
|
||||
FilterGroupUsers = .FilterGroupUsers
|
||||
FilterShowGroupsInsteadLabels = .FilterShowGroupsInsteadLabels
|
||||
FilterShowAllUsers = .FilterShowAllUsers
|
||||
End If
|
||||
End With
|
||||
End If
|
||||
|
||||
@@ -117,6 +117,8 @@ Namespace DownloadObjects.Groups
|
||||
RefillList()
|
||||
If Not IsViewFilter Then Settings.Groups.BeginUpdate()
|
||||
|
||||
If IsViewFilter And LIST_GROUPS.Items.Count > 0 Then .MyOkCancel.EnableOK = True : _LatestSelected = 0
|
||||
|
||||
.DelegateClosingChecker = False
|
||||
|
||||
.EndLoaderOperations()
|
||||
|
||||
@@ -93,7 +93,6 @@ Namespace DownloadObjects.STDownloader
|
||||
End With
|
||||
Catch ex As Exception
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[STDownloader.DownloaderUrlForm.TXT_URL_ActionOnTextChanged]")
|
||||
MainFrameObj.UpdateLogButton()
|
||||
End Try
|
||||
End Sub
|
||||
Private Sub TXT_PATH_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_PATH.ActionOnButtonClick
|
||||
|
||||
@@ -108,7 +108,6 @@ Namespace DownloadObjects.STDownloader
|
||||
Catch ex As Exception
|
||||
_UseAccountName = True
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[STDownloader.DownloaderUrlsArrForm.TXT_URLS_TextChanged]")
|
||||
MainFrameObj.UpdateLogButton()
|
||||
End Try
|
||||
End Sub
|
||||
End Class
|
||||
|
||||
@@ -226,9 +226,5 @@ Namespace DownloadObjects.STDownloader
|
||||
RemoveControls(ControlNonYT, False)
|
||||
End If
|
||||
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 Namespace
|
||||
@@ -39,7 +39,7 @@ Namespace DownloadObjects
|
||||
#End Region
|
||||
Friend ReadOnly User As IUserData
|
||||
Friend ReadOnly Data As UserMedia
|
||||
Friend ReadOnly UserInfo As UserInfo
|
||||
Friend UserInfo As UserInfo
|
||||
Friend ReadOnly [Date] As Date
|
||||
Friend Session As Integer
|
||||
Friend IsSavedPosts As Boolean
|
||||
@@ -149,29 +149,35 @@ Namespace DownloadObjects
|
||||
End Try
|
||||
End Function
|
||||
Private _FilesSessionChecked_Impl As Boolean = False
|
||||
Friend Sub FilesLoadLastSession()
|
||||
Friend Sub FilesLoadLastSession(Optional ByVal SelectedSessionFile As SFile = Nothing)
|
||||
Try
|
||||
If Not _FilesSessionChecked And Not _FilesSessionChecked_Impl And _FilesSessionActual.IsEmptyString Then
|
||||
If Not SelectedSessionFile.IsEmptyString Or (Not _FilesSessionChecked And Not _FilesSessionChecked_Impl And _FilesSessionActual.IsEmptyString) Then
|
||||
_FilesSessionChecked = True
|
||||
_FilesSessionChecked_Impl = True
|
||||
Dim settingValue% = Settings.FeedCurrentTryLoadLastSession
|
||||
If settingValue >= 0 Then
|
||||
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) = 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))
|
||||
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 lastDate.Date = startTime.Date Then
|
||||
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
|
||||
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)
|
||||
@@ -191,9 +197,9 @@ Namespace DownloadObjects
|
||||
End Sub
|
||||
Private _FilesUpdating As Boolean = False
|
||||
Friend Sub FilesUpdatePendingUsers()
|
||||
_FilesUpdating = True
|
||||
Try
|
||||
If Files.Count > 0 Then
|
||||
_FilesUpdating = True
|
||||
With Settings.Feeds
|
||||
Dim pUsers As List(Of KeyValuePair(Of UserInfo, UserInfo))
|
||||
Dim pendingUser As KeyValuePair(Of UserInfo, UserInfo)
|
||||
@@ -214,19 +220,20 @@ Namespace DownloadObjects
|
||||
Next
|
||||
End If
|
||||
End With
|
||||
If changed Then FilesSave()
|
||||
If changed Then _FilesUpdating = False : FilesSave()
|
||||
Next
|
||||
pUsers.Clear()
|
||||
End While
|
||||
End With
|
||||
_FilesUpdating = False
|
||||
End If
|
||||
Catch aex As ArgumentOutOfRangeException
|
||||
Catch iex As IndexOutOfRangeException
|
||||
Catch ex As Exception
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[TDownloader.FilesUpdatePendingUsers]")
|
||||
MainFrameObj.UpdateLogButton()
|
||||
Finally
|
||||
_FilesUpdating = False
|
||||
Catch iex As IndexOutOfRangeException
|
||||
_FilesUpdating = False
|
||||
Catch ex As Exception
|
||||
_FilesUpdating = False
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[TDownloader.FilesUpdatePendingUsers]")
|
||||
End Try
|
||||
End Sub
|
||||
Friend Sub ClearSessions()
|
||||
@@ -250,6 +257,13 @@ Namespace DownloadObjects
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[DownloadObjects.TDownloader.ClearSessions]")
|
||||
End Try
|
||||
End Sub
|
||||
Friend Sub ResetSession()
|
||||
Files.Clear()
|
||||
_FilesSessionActual = Nothing
|
||||
_FilesSessionChecked = True
|
||||
_Session = 0
|
||||
_SessionSavedPosts = -1
|
||||
End Sub
|
||||
#End Region
|
||||
Friend ReadOnly Property Downloaded As List(Of IUserData)
|
||||
Private ReadOnly NProv As IFormatProvider
|
||||
@@ -534,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)
|
||||
ExecuteCommand(Settings.DownloadsCompleteCommand)
|
||||
UpdateJobsLabel()
|
||||
If MissingPostsDetected And Settings.AddMissingToLog Then
|
||||
MyMainLOG = "Some posts didn't download. You can see them in the 'Missing posts' form."
|
||||
MainFrameObj.UpdateLogButton()
|
||||
End If
|
||||
If MissingPostsDetected And Settings.AddMissingToLog Then _
|
||||
MyMainLOG = "Some posts didn't download. You can see them in the 'Missing posts' form."
|
||||
Files.Sort()
|
||||
FilesChanged = Not fBefore = Files.Count
|
||||
RaiseEvent Downloading(False)
|
||||
@@ -610,6 +622,7 @@ Namespace DownloadObjects
|
||||
Dim limitIndex%
|
||||
Dim limits As New List(Of HostLimit)
|
||||
Dim Keys As New List(Of String)
|
||||
Dim KeysSkipped As New List(Of String)
|
||||
Dim h As Boolean = False
|
||||
Dim host As SettingsHost = Nothing
|
||||
Dim hostAvailable As Boolean
|
||||
@@ -636,6 +649,8 @@ Namespace DownloadObjects
|
||||
limit = limit.Next
|
||||
limits(limitIndex) = limit
|
||||
If limit.Value >= limit.Limit Then Exit For
|
||||
Else
|
||||
KeysSkipped.Add(_Item.Key)
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
@@ -653,24 +668,27 @@ Namespace DownloadObjects
|
||||
For Each k$ In Keys
|
||||
i = _Job.Items.FindIndex(Function(ii) ii.Key = k)
|
||||
If i >= 0 Then
|
||||
With _Job.Items(i)
|
||||
If DirectCast(.Self, UserDataBase).ContentMissingExists Then MissingPostsDetected = True
|
||||
RaiseEvent UserDownloadStateChanged(.Self, False)
|
||||
host = _Job.UserHost(.Self)
|
||||
host.AfterDownload(.Self, Download.Main)
|
||||
If Not .Disposed AndAlso Not .IsCollection AndAlso .DownloadedTotal(False) > 0 Then
|
||||
If Not Downloaded.Contains(.Self) Then Downloaded.Add(Settings.GetUser(.Self))
|
||||
With DirectCast(.Self, UserDataBase)
|
||||
If .LatestData.Count > 0 And .IncludeInTheFeed Then Files.ListAddList(.LatestData.Select(Function(d) New UserMediaD(d, .Self, Session)), FilesLP)
|
||||
End With
|
||||
dcc = True
|
||||
End If
|
||||
End With
|
||||
If KeysSkipped.Count = 0 OrElse Not KeysSkipped.Contains(k) Then
|
||||
With _Job.Items(i)
|
||||
If DirectCast(.Self, UserDataBase).ContentMissingExists Then MissingPostsDetected = True
|
||||
RaiseEvent UserDownloadStateChanged(.Self, False)
|
||||
host = _Job.UserHost(.Self)
|
||||
host.AfterDownload(.Self, Download.Main)
|
||||
If Not .Disposed AndAlso Not .IsCollection AndAlso .DownloadedTotal(False) > 0 Then
|
||||
If Not Downloaded.Contains(.Self) Then Downloaded.Add(Settings.GetUser(.Self))
|
||||
With DirectCast(.Self, UserDataBase)
|
||||
If .LatestData.Count > 0 And .IncludeInTheFeed Then Files.ListAddList(.LatestData.Select(Function(d) New UserMediaD(d, .Self, Session)), FilesLP)
|
||||
End With
|
||||
dcc = True
|
||||
End If
|
||||
End With
|
||||
End If
|
||||
_Job.Items.RemoveAt(i)
|
||||
End If
|
||||
Next
|
||||
End If
|
||||
Keys.Clear()
|
||||
KeysSkipped.Clear()
|
||||
_Job.Items.RemoveAll(Function(ii) ii.Disposed)
|
||||
If dcc Then Downloaded.RemoveAll(Function(u) u Is Nothing)
|
||||
If dcc And Downloaded.Count > 0 Then RaiseEvent DownloadCountChange()
|
||||
|
||||
103
SCrawler/Editors/GlobalSettingsForm.Designer.vb
generated
@@ -167,6 +167,7 @@ Namespace Editors
|
||||
Me.TXT_DOWN_COMPLETE_SCRIPT = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||
Me.CH_UNAME_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_COLUMNS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||
Me.CH_FEED_ENDLESS = New System.Windows.Forms.CheckBox()
|
||||
@@ -178,6 +179,7 @@ Namespace Editors
|
||||
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_FFMPEG = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||
Me.TXT_CURL = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||
@@ -203,6 +205,7 @@ Namespace Editors
|
||||
Me.TAB_MAIN = New System.Windows.Forms.TabControl()
|
||||
Me.TAB_ENVIR = New System.Windows.Forms.TabPage()
|
||||
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_IMAGES = New System.Windows.Forms.TableLayoutPanel()
|
||||
TP_FILE_NAME = New System.Windows.Forms.TableLayoutPanel()
|
||||
@@ -269,6 +272,7 @@ Namespace Editors
|
||||
CType(Me.TXT_SCRIPT, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||
CType(Me.TXT_DOWN_COMPLETE_SCRIPT, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||
TP_MISSING_DATA.SuspendLayout()
|
||||
CType(Me.TXT_AUTO_BRUSH_MIN, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||
TAB_FEED.SuspendLayout()
|
||||
TP_FEED.SuspendLayout()
|
||||
TP_FEED_IMG_COUNT.SuspendLayout()
|
||||
@@ -947,10 +951,10 @@ Namespace Editors
|
||||
'
|
||||
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.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.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)"
|
||||
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
|
||||
@@ -1060,10 +1064,10 @@ Namespace Editors
|
||||
'
|
||||
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.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.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"
|
||||
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
|
||||
@@ -1488,10 +1492,11 @@ Namespace Editors
|
||||
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_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.Location = New System.Drawing.Point(0, 0)
|
||||
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!))
|
||||
@@ -1502,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, 28.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.TabIndex = 1
|
||||
@@ -1584,12 +1590,30 @@ Namespace Editors
|
||||
Me.CH_UICON_UP.Text = "Update user icon and banner every time (where supported)"
|
||||
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.Controls.Add(TP_FEED)
|
||||
TAB_FEED.Location = New System.Drawing.Point(4, 22)
|
||||
TAB_FEED.Name = "TAB_FEED"
|
||||
TAB_FEED.Size = New System.Drawing.Size(621, 399)
|
||||
TAB_FEED.Size = New System.Drawing.Size(621, 374)
|
||||
TAB_FEED.TabIndex = 7
|
||||
TAB_FEED.Text = "Feed"
|
||||
'
|
||||
@@ -1601,32 +1625,35 @@ Namespace Editors
|
||||
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_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.TXT_FEED_CENTER_IMAGE, 0, 1)
|
||||
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_SHOW_FRIENDLY, 0, 8)
|
||||
TP_FEED.Controls.Add(Me.CH_FEED_SHOW_SPEC_MEDIAITEM, 0, 9)
|
||||
TP_FEED.Controls.Add(Me.CH_FEED_UP_FILE_LOC_MOVE, 0, 10)
|
||||
TP_FEED.Controls.Add(TP_FEED_SES, 0, 6)
|
||||
TP_FEED.Controls.Add(Me.CH_FEED_OPEN_LAST_MODE, 0, 9)
|
||||
TP_FEED.Controls.Add(Me.CH_FEED_SHOW_FRIENDLY, 0, 10)
|
||||
TP_FEED.Controls.Add(Me.CH_FEED_SHOW_SPEC_MEDIAITEM, 0, 11)
|
||||
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.Location = New System.Drawing.Point(0, 0)
|
||||
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, 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, 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.Absolute, 20.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_IMG_COUNT
|
||||
@@ -1704,10 +1731,10 @@ Namespace Editors
|
||||
'
|
||||
Me.CH_FEED_ADD_DATE.AutoSize = True
|
||||
Me.CH_FEED_ADD_DATE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||
Me.CH_FEED_ADD_DATE.Location = New System.Drawing.Point(4, 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.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.UseVisualStyleBackColor = True
|
||||
'
|
||||
@@ -1747,10 +1774,10 @@ Namespace Editors
|
||||
'
|
||||
Me.CH_FEED_SHOW_FRIENDLY.AutoSize = True
|
||||
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.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.UseVisualStyleBackColor = True
|
||||
'
|
||||
@@ -1758,10 +1785,10 @@ Namespace Editors
|
||||
'
|
||||
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.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.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.UseVisualStyleBackColor = True
|
||||
'
|
||||
@@ -1773,14 +1800,14 @@ Namespace Editors
|
||||
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, 163)
|
||||
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 = 6
|
||||
TP_FEED_SES.TabIndex = 8
|
||||
'
|
||||
'NUM_FEED_STORE_SESSION_DATA
|
||||
'
|
||||
@@ -1829,6 +1856,17 @@ Namespace Editors
|
||||
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.Controls.Add(TP_NOTIFY_MAIN)
|
||||
@@ -2397,7 +2435,7 @@ Namespace Editors
|
||||
Me.TAB_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||
Me.TAB_MAIN.Name = "TAB_MAIN"
|
||||
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
|
||||
'
|
||||
'TAB_ENVIR
|
||||
@@ -2415,7 +2453,7 @@ Namespace Editors
|
||||
'CONTAINER_MAIN.ContentPanel
|
||||
'
|
||||
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.LeftToolStripPanelVisible = False
|
||||
Me.CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||
@@ -2425,6 +2463,17 @@ Namespace Editors
|
||||
Me.CONTAINER_MAIN.TabIndex = 0
|
||||
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
|
||||
'
|
||||
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
||||
@@ -2486,6 +2535,7 @@ Namespace Editors
|
||||
CType(Me.TXT_DOWN_COMPLETE_SCRIPT, System.ComponentModel.ISupportInitialize).EndInit()
|
||||
TP_MISSING_DATA.ResumeLayout(False)
|
||||
TP_MISSING_DATA.PerformLayout()
|
||||
CType(Me.TXT_AUTO_BRUSH_MIN, System.ComponentModel.ISupportInitialize).EndInit()
|
||||
TAB_FEED.ResumeLayout(False)
|
||||
TP_FEED.ResumeLayout(False)
|
||||
TP_FEED.PerformLayout()
|
||||
@@ -2636,5 +2686,8 @@ Namespace Editors
|
||||
Private WithEvents CH_DOWN_ALL_NOTIFY 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 Namespace
|
||||
@@ -19,6 +19,7 @@ Namespace Editors
|
||||
Friend Property HeadersChanged As Boolean = False
|
||||
Friend Property PictureChanged As Boolean = False
|
||||
Friend Property EnvironmentProgramsChanged As Boolean = False
|
||||
Friend Property UserAgentChanged As Boolean = False
|
||||
Friend Sub New()
|
||||
InitializeComponent()
|
||||
MyDefs = New DefaultFormOptions(Me, Settings.Design)
|
||||
@@ -122,6 +123,7 @@ Namespace Editors
|
||||
CH_ADD_MISSING_ERROS_TO_LOG.Checked = .AddMissingErrorsToLog
|
||||
CH_DOWN_REPARSE_MISSING.Checked = .ReparseMissingInTheRoutine
|
||||
CH_USE_DEF_ACC.Checked = .UseDefaultAccountIfMissing
|
||||
TXT_AUTO_BRUSH_MIN.Value = .AutomationBrushUndownloadedPlansMinutes.Value
|
||||
'Downloading: file names
|
||||
CH_FILE_NAME_CHANGE.Checked = Not .FileReplaceNameByDate.Value = FileNameReplaceMode.None
|
||||
OPT_FILE_NAME_REPLACE.Checked = .FileReplaceNameByDate.Value = FileNameReplaceMode.Replace
|
||||
@@ -149,6 +151,8 @@ Namespace Editors
|
||||
COLORS_FEED.ColorsSet(.FeedBackColor, .FeedForeColor, SystemColors.Window, SystemColors.WindowText)
|
||||
CH_FEED_ENDLESS.Checked = .FeedEndless
|
||||
CH_FEED_ADD_SESSION.Checked = .FeedAddSessionToCaption
|
||||
CH_FEED_ADD_SITE.Checked = .FeedAddSiteToCaption
|
||||
CH_FEED_ADD_TYPE.Checked = .FeedAddTypeToCaption
|
||||
CH_FEED_ADD_DATE.Checked = .FeedAddDateToCaption
|
||||
NUM_FEED_STORE_SESSION_DATA.Checked = .FeedStoreSessionsData
|
||||
NUM_FEED_STORE_SESSION_DATA.Value = .FeedStoredSessionsNumber.Value
|
||||
@@ -183,6 +187,7 @@ Namespace Editors
|
||||
"Do you really want to continue?",
|
||||
"Increasing download tasks"},
|
||||
vbExclamation,,, {"Confirm", $"Set to default ({SettingsCLS.DefaultMaxDownloadingTasks})", "Cancel"})
|
||||
|
||||
If CInt(TXT_MAX_JOBS_USERS.Value) > SettingsCLS.DefaultMaxDownloadingTasks Then
|
||||
Select Case a.Invoke("users", TXT_MAX_JOBS_USERS.Value)
|
||||
Case 1 : TXT_MAX_JOBS_USERS.Value = SettingsCLS.DefaultMaxDownloadingTasks
|
||||
@@ -213,6 +218,25 @@ Namespace Editors
|
||||
"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
|
||||
|
||||
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
|
||||
.BeginUpdate()
|
||||
|
||||
@@ -225,7 +249,7 @@ Namespace Editors
|
||||
.ChannelsMaxJobsCount.Value = TXT_MAX_JOBS_CHANNELS.Value
|
||||
.CheckUpdatesAtStart.Value = CH_CHECK_VER_START.Checked
|
||||
.UserAgent.Value = TXT_USER_AGENT.Text
|
||||
DefaultUserAgent = TXT_USER_AGENT.Text
|
||||
UserAgentChanged = .UserAgent.ChangesDetected
|
||||
.ImgurClientID.Value = TXT_IMGUR_CLIENT_ID.Text
|
||||
'Design
|
||||
.ProgramText.Value = TXT_PRG_TITLE.Text
|
||||
@@ -310,6 +334,7 @@ Namespace Editors
|
||||
.AddMissingErrorsToLog.Value = CH_ADD_MISSING_ERROS_TO_LOG.Checked
|
||||
.ReparseMissingInTheRoutine.Value = CH_DOWN_REPARSE_MISSING.Checked
|
||||
.UseDefaultAccountIfMissing.Value = CH_USE_DEF_ACC.Checked
|
||||
.AutomationBrushUndownloadedPlansMinutes.Value = TXT_AUTO_BRUSH_MIN.Value
|
||||
'Downloading: file names
|
||||
If CH_FILE_NAME_CHANGE.Checked Then
|
||||
.FileReplaceNameByDate.Value = If(OPT_FILE_NAME_REPLACE.Checked, FileNameReplaceMode.Replace, FileNameReplaceMode.Add)
|
||||
@@ -338,6 +363,8 @@ Namespace Editors
|
||||
COLORS_FEED.ColorsGet(.FeedBackColor, .FeedForeColor)
|
||||
.FeedEndless.Value = CH_FEED_ENDLESS.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
|
||||
.FeedStoreSessionsData.Value = NUM_FEED_STORE_SESSION_DATA.Checked
|
||||
.FeedStoredSessionsNumber.Value = NUM_FEED_STORE_SESSION_DATA.Value
|
||||
|
||||
@@ -27,6 +27,7 @@ Friend Class LabelsForm
|
||||
End Property
|
||||
Friend Property WithDeleteButton 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)
|
||||
InitializeComponent()
|
||||
Me.AddNoParsed = AddNoParsed
|
||||
@@ -65,7 +66,15 @@ Friend Class LabelsForm
|
||||
End Try
|
||||
End Sub
|
||||
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
|
||||
Private Sub LabelsForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
|
||||
LabelsList.Clear()
|
||||
@@ -101,4 +110,20 @@ Friend Class LabelsForm
|
||||
End If
|
||||
End If
|
||||
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
|
||||
@@ -7,6 +7,7 @@
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Imports SCrawler.Plugin
|
||||
Imports SCrawler.Plugin.Attributes
|
||||
Imports SCrawler.Plugin.Hosts
|
||||
Imports PersonalUtilities.Forms
|
||||
Imports PersonalUtilities.Forms.Controls
|
||||
@@ -15,13 +16,13 @@ Imports PersonalUtilities.Tools.Web.Cookies
|
||||
Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons
|
||||
Namespace Editors
|
||||
Friend Class SiteEditorForm
|
||||
Private ReadOnly LBL_AUTH As Label
|
||||
Private ReadOnly LBL_OTHER As Label
|
||||
Private WithEvents MyDefs As DefaultFormOptions
|
||||
Private WithEvents SpecialButton As Button
|
||||
Private Property Cookies As CookieKeeper
|
||||
Private ReadOnly CookiesControlsInteraction As List(Of PropertyValueHost)
|
||||
Private CookiesChanged As Boolean = False
|
||||
Private Const OtherOptionsText As String = "Other Parameters"
|
||||
Private ReadOnly LabelControls As List(Of Label)
|
||||
#Region "Providers"
|
||||
Private Class SavedPostsChecker : Inherits AccountsNameChecker
|
||||
Friend ReadOnly PathControl As TextBoxExtended
|
||||
@@ -138,6 +139,108 @@ Namespace Editors
|
||||
Return Nothing
|
||||
End Function
|
||||
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
|
||||
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
|
||||
@@ -148,8 +251,7 @@ Namespace Editors
|
||||
Host = h
|
||||
CookiesControlsInteraction = New List(Of PropertyValueHost)
|
||||
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}
|
||||
LBL_OTHER = New Label With {.Text = "Other Parameters", .TextAlign = ContentAlignment.MiddleCenter, .Dock = DockStyle.Fill}
|
||||
LabelControls = New List(Of Label)
|
||||
Host.BeginEdit()
|
||||
End Sub
|
||||
Private Sub SiteEditorForm_Load(sender As Object, e As EventArgs) Handles Me.Load
|
||||
@@ -191,13 +293,6 @@ Namespace Editors
|
||||
|
||||
Dim offset% = PropertyValueHost.LeftOffsetDefault
|
||||
Dim h% = 0, c% = 0
|
||||
Dim AddTpControl As Action(Of Control, Integer) = Sub(ByVal cnt As Control, ByVal _height As Integer)
|
||||
TP_SITE_PROPS.RowStyles.Add(New RowStyle(SizeType.Absolute, _height))
|
||||
TP_SITE_PROPS.RowCount += 1
|
||||
TP_SITE_PROPS.Controls.Add(cnt, 0, TP_SITE_PROPS.RowStyles.Count - 1)
|
||||
h += _height
|
||||
c += 1
|
||||
End Sub
|
||||
|
||||
If Host.Responser Is Nothing Then
|
||||
h -= 28
|
||||
@@ -214,41 +309,17 @@ Namespace Editors
|
||||
|
||||
Dim laAdded 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()
|
||||
For Each pAuth As Boolean In pArr
|
||||
Using pc As New CatReorder
|
||||
For Each prop As PropertyValueHost In .PropList
|
||||
If PropertyValid.Invoke(prop) Then
|
||||
With prop
|
||||
If .Options.IsAuth = pAuth Then
|
||||
|
||||
If .CookieValueExtractorExists Then CookiesControlsInteraction.Add(prop)
|
||||
|
||||
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
|
||||
If PropertyValid.Invoke(prop) Then pc.Add(prop)
|
||||
Next
|
||||
Next
|
||||
If pc.Count > 0 Then pc.AddToTable(Me, h, c, offset)
|
||||
End Using
|
||||
End If
|
||||
|
||||
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)
|
||||
offset += PaddingE.GetOf({TP_SITE_PROPS}).Left
|
||||
TXT_PATH.CaptionWidth = offset
|
||||
@@ -290,8 +361,7 @@ Namespace Editors
|
||||
If Host.PropList.Count > 0 Then Host.PropList.ForEach(Sub(p) p.DisposeControl())
|
||||
If Not SpecialButton Is Nothing Then SpecialButton.Dispose()
|
||||
CookiesControlsInteraction.Clear()
|
||||
LBL_AUTH.Dispose()
|
||||
LBL_OTHER.Dispose()
|
||||
LabelControls.ListClearDispose
|
||||
Host.EndEdit()
|
||||
If Not Cookies Is Nothing Then Cookies.Dispose()
|
||||
End Sub
|
||||
@@ -317,6 +387,13 @@ Namespace Editors
|
||||
Next
|
||||
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)
|
||||
If TXT_PATH.IsEmptyString Then .Path = Nothing Else .Path = TXT_PATH.Text
|
||||
.SavedPostsPath = TXT_PATH_SAVED_POSTS.Text
|
||||
|
||||
@@ -313,7 +313,6 @@ Namespace Editors
|
||||
BTT_START.Enabled = Not Working
|
||||
BTT_CANCEL.Enabled = Working
|
||||
End Sub, EDP.None)
|
||||
If Not Working Then MainFrameObj.UpdateLogButton()
|
||||
Catch
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
@@ -131,7 +131,6 @@ Public Class MainFrame
|
||||
Await .Automation.Start(True)
|
||||
End With
|
||||
UpdatePauseButtonsVisibility()
|
||||
MainFrameObj.UpdateLogButton()
|
||||
End Sub
|
||||
Private _CloseInvoked As Boolean = False
|
||||
Private _IgnoreTrayOptions As Boolean = False
|
||||
@@ -325,9 +324,10 @@ CloseResume:
|
||||
TrayIcon.Visible = .CloseToTray
|
||||
If f.EnvironmentProgramsChanged Then Settings.UpdateEnvironmentPrograms()
|
||||
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.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()
|
||||
End If
|
||||
UpdateSilentButtons()
|
||||
@@ -624,7 +624,6 @@ CloseResume:
|
||||
End Using
|
||||
Catch ex As Exception
|
||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[MainFrame.ShowGroups]")
|
||||
MainFrameObj.UpdateLogButton()
|
||||
End Try
|
||||
End Sub
|
||||
#End Region
|
||||
@@ -651,7 +650,6 @@ CloseResume:
|
||||
MainFrameObj.PauseButtons.UpdatePauseButtons()
|
||||
Catch ex As Exception
|
||||
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Start automation")
|
||||
MainFrameObj.UpdateLogButton()
|
||||
End Try
|
||||
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
|
||||
@@ -781,6 +779,7 @@ CloseResume:
|
||||
f.FilterViewMode = Settings.ViewMode
|
||||
f.FilterGroupUsers = Settings.GroupUsers
|
||||
f.FilterShowGroupsInsteadLabels = Settings.ShowGroupsInsteadLabels
|
||||
f.FilterShowAllUsers = Settings.ShowAllUsers
|
||||
f.Name = fName
|
||||
Settings.Groups.Add(f, isFilter, True)
|
||||
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.GroupUsers.Value = .FilterGroupUsers
|
||||
Settings.ShowGroupsInsteadLabels.Value = .FilterShowGroupsInsteadLabels
|
||||
Settings.ShowAllUsers.Value = .FilterShowAllUsers
|
||||
End With
|
||||
ApplyViewPattern(Settings.ViewMode.Value, True)
|
||||
Else
|
||||
Settings.ShowAllUsers.Value = False
|
||||
End If
|
||||
Settings.AdvancedFilter.Copy(filter)
|
||||
Settings.AdvancedFilter.UpdateFile()
|
||||
@@ -2017,7 +2019,6 @@ ResumeDownloadingOperation:
|
||||
End Sub
|
||||
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}]"))
|
||||
MainFrameObj.UpdateLogButton()
|
||||
End Sub
|
||||
Private Sub Downloader_Downloading(ByVal Value As Boolean)
|
||||
Dim __isDownloading As Boolean = Value Or Downloader.Working(False)
|
||||
|
||||
@@ -66,17 +66,17 @@ Friend Class MainFrameObjects : Implements INotificator
|
||||
ControlInvokeFast(MF.TRAY_CONTEXT, Sub() MF.BTT_TRAY_CLOSE_NO_SCRIPT.Visible =
|
||||
Settings.ClosingCommand.Attribute And Not Settings.ClosingCommand.IsEmptyString)
|
||||
End Sub
|
||||
Friend Sub UpdateLogButton()
|
||||
MyMainLOG_UpdateLogButton(MF.BTT_LOG, MF.Toolbar_TOP)
|
||||
Private Sub UpdateLogButton()
|
||||
Try : MyMainLOG_UpdateLogButton(MF.BTT_LOG, MF.Toolbar_TOP) : Catch : End Try
|
||||
End Sub
|
||||
Friend Function GetUserListProvider(ByVal WithCollections As Boolean) As IFormatProvider
|
||||
Return MF.GetUserListProvider(WithCollections)
|
||||
End Function
|
||||
Friend Sub ShowLog()
|
||||
MyMainLOG_ShowForm(Settings.Design,,,, Sub()
|
||||
UpdateLogButton()
|
||||
LogFormClosed()
|
||||
End Sub)
|
||||
Try : MyMainLOG_ShowForm(Settings.Design,,,, Sub()
|
||||
UpdateLogButton()
|
||||
LogFormClosed()
|
||||
End Sub) : Catch : End Try
|
||||
End Sub
|
||||
#End Region
|
||||
#Region "Notifications"
|
||||
|
||||
@@ -77,10 +77,15 @@ Friend Module MainMod
|
||||
''' <summary>Alt+F1</summary>
|
||||
Friend ReadOnly ShowUsersButtonKey As New PersonalUtilities.Forms.ButtonKey(Keys.F1,, True)
|
||||
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 FeedVideoLengthProvider As New ADateTime("hh\:mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan}
|
||||
Friend ReadOnly LogConnector As New LogHost
|
||||
Friend DefaultUserAgent As String = String.Empty
|
||||
Friend SiteSettingsShowHiddenControls As Boolean = False
|
||||
#Region "NonExistingUsersLog"
|
||||
Friend ReadOnly NonExistingUsersLog As New TextSaver($"LOGs\NonExistingUsers.txt") With {.LogMode = True, .AutoSave = True}
|
||||
|
||||
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
|
||||
' by using the '*' as shown below:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("2024.4.26.0")>
|
||||
<Assembly: AssemblyFileVersion("2024.4.26.0")>
|
||||
<Assembly: AssemblyVersion("2024.6.10.0")>
|
||||
<Assembly: AssemblyFileVersion("2024.6.10.0")>
|
||||
<Assembly: NeutralResourcesLanguage("en")>
|
||||
|
||||
@@ -54,6 +54,7 @@ Namespace Plugin.Hosts
|
||||
#Region "Control"
|
||||
Friend Property Control As Control
|
||||
Friend Property ControlNumber As Integer = -1
|
||||
Friend Property Category As String = String.Empty
|
||||
Friend ReadOnly Property ControlHeight As Integer
|
||||
Get
|
||||
If Not Control Is Nothing Then
|
||||
@@ -333,6 +334,8 @@ Namespace Plugin.Hosts
|
||||
If DirectCast(Member, PropertyInfo).PropertyType Is GetType(PropertyValue) Then
|
||||
UpdateMember()
|
||||
Options = Member.GetCustomAttribute(Of PropertyOption)()
|
||||
Category = If(Options?.Category, String.Empty)
|
||||
If Category.IsEmptyString Then Category = If(Member.GetCustomAttribute(Of ComponentModel.CategoryAttribute)?.Category, String.Empty)
|
||||
IsTaskCounter = Not Member.GetCustomAttribute(Of TaskCounter)() Is Nothing
|
||||
IsHidden = If(Member.GetCustomAttribute(Of HiddenControlAttribute)?.IsHidden, False)
|
||||
With Member.GetCustomAttribute(Of PXML)
|
||||
|
||||
@@ -219,10 +219,10 @@ Namespace Plugin.Hosts
|
||||
Friend ReadOnly Property DownloadImages As XMLValue(Of Boolean)
|
||||
Friend ReadOnly Property DownloadVideos As XMLValue(Of Boolean)
|
||||
Private ReadOnly _Path As XMLValue(Of SFile)
|
||||
Friend Property Path(Optional ByVal SetProp As Boolean = True) As SFile
|
||||
Friend Property Path(Optional ByVal SetProp As Boolean = True, Optional ByVal GetActualValue As Boolean = False) As SFile
|
||||
Get
|
||||
If _Path.IsEmptyString Then
|
||||
Dim tmpPath As SFile = SFile.GetPath($"{Settings.GlobalPath.Value.PathWithSeparator}{Source.Site}")
|
||||
If Not GetActualValue And _Path.IsEmptyString Then
|
||||
Dim tmpPath As SFile = PathGenerate()
|
||||
If SetProp Then _Path.Value = tmpPath Else Return tmpPath
|
||||
End If
|
||||
Return _Path.Value
|
||||
@@ -231,6 +231,9 @@ Namespace Plugin.Hosts
|
||||
_Path.Value = NewPath
|
||||
End Set
|
||||
End Property
|
||||
Friend Function PathGenerate() As SFile
|
||||
Return SFile.GetPath($"{Settings.GlobalPath.Value.PathWithSeparator}{Source.Site}")
|
||||
End Function
|
||||
Friend Const SavedPostsFolderName As String = "!Saved"
|
||||
Private ReadOnly _SavedPostsPath As XMLValue(Of SFile)
|
||||
Friend Property SavedPostsPath(Optional ByVal GetAny As Boolean = True) As SFile
|
||||
|
||||
@@ -25,6 +25,7 @@ Namespace Plugin.Hosts
|
||||
Private ReadOnly Hosts As List(Of SettingsHost)
|
||||
Private ReadOnly HostsUnavailableIndexes As List(Of Integer)
|
||||
Private ReadOnly HostsXml As List(Of XmlFile)
|
||||
Private Const NoPauseMode As Integer = DownloadObjects.AutoDownloader.NoPauseMode
|
||||
#Region "Controls"
|
||||
Private WithEvents BTT_SETTINGS As ToolStripMenuItem
|
||||
Private BTT_SETTINGS_SEP_1 As ToolStripSeparator
|
||||
@@ -201,7 +202,6 @@ Namespace Plugin.Hosts
|
||||
Select Case Hosts_Deleted_MoveAcc(Obj)
|
||||
Case -1 : ShowOperationCanceledMsg(ChngUACC_MsgTitle) : Exit Sub
|
||||
Case 1
|
||||
MainFrameObj.UpdateLogButton()
|
||||
MsgBoxE({$"An error occurred while changing user accounts (see log for details).{vbCr}Operation canceled.", ChngUACC_MsgTitle}, vbCritical)
|
||||
Exit Sub
|
||||
End Select
|
||||
@@ -226,8 +226,7 @@ Namespace Plugin.Hosts
|
||||
''' 1 - error
|
||||
''' </summary>
|
||||
Private Function Hosts_Deleted_MoveAcc(ByVal Obj As SettingsHost) As Integer
|
||||
Const np% = -100
|
||||
Dim p As PauseModes = np
|
||||
Dim p As PauseModes = NoPauseMode
|
||||
Dim changedUsers As New List(Of String)
|
||||
Try
|
||||
With Settings
|
||||
@@ -294,10 +293,10 @@ Namespace Plugin.Hosts
|
||||
.UpdateUsersList()
|
||||
End If
|
||||
Else
|
||||
p = np
|
||||
p = NoPauseMode
|
||||
End If
|
||||
Else
|
||||
p = np
|
||||
p = NoPauseMode
|
||||
End If
|
||||
End With
|
||||
Return 0
|
||||
@@ -309,11 +308,13 @@ Namespace Plugin.Hosts
|
||||
End If
|
||||
Return ErrorsDescriber.Execute(EDP.SendToLog, ex, msg, 1)
|
||||
Finally
|
||||
If p <> np Then Settings.Automation.Pause = p
|
||||
If p <> NoPauseMode Then Settings.Automation.Pause = p
|
||||
End Try
|
||||
End Function
|
||||
Friend Shared Sub UpdateUserAccount(ByRef ChangingUser As UserInfo, ByVal HostOld As SettingsHost, ByVal HostNew As SettingsHost,
|
||||
ByVal UpdateUserInTheList As Boolean, Optional ByRef UserIndex As Integer = -1)
|
||||
Friend Shared Function UpdateUserAccount(ByRef ChangingUser As UserInfo, ByVal HostOld As SettingsHost, ByVal HostNew As SettingsHost,
|
||||
ByVal UpdateUserInTheList As Boolean, Optional ByRef UserIndex As Integer = -1,
|
||||
Optional ByVal ForceCollections As Boolean = False) As Boolean
|
||||
Dim result As Boolean = False
|
||||
With Settings
|
||||
UserIndex = .UsersList.IndexOf(ChangingUser)
|
||||
If UserIndex = -1 Then
|
||||
@@ -322,16 +323,17 @@ Namespace Plugin.Hosts
|
||||
Dim processUserPath As Boolean
|
||||
Dim samePath As Boolean = HostOld.Path(False) = HostNew.Path(False)
|
||||
With ChangingUser
|
||||
If Not samePath AndAlso .SpecialPath.IsEmptyString AndAlso .SpecialCollectionPath.IsEmptyString Then
|
||||
If (Not samePath Or ForceCollections) AndAlso .SpecialPath.IsEmptyString AndAlso .SpecialCollectionPath.IsEmptyString Then
|
||||
processUserPath = False
|
||||
If .IncludedInCollection Then
|
||||
If Not .IsVirtual Then
|
||||
.SpecialCollectionPath = .GetCollectionRootPath
|
||||
result = True
|
||||
Else
|
||||
processUserPath = True
|
||||
If Not samePath Then processUserPath = True
|
||||
End If
|
||||
End If
|
||||
If Not .IncludedInCollection Or processUserPath Then .SpecialPath = .File.CutPath.PathWithSeparator
|
||||
If Not .IncludedInCollection Or processUserPath Then .SpecialPath = .File.CutPath.PathWithSeparator : result = True
|
||||
End If
|
||||
End With
|
||||
ChangingUser.AccountName = HostNew.AccountName
|
||||
@@ -339,7 +341,108 @@ Namespace Plugin.Hosts
|
||||
If UpdateUserInTheList Then .UsersList(UserIndex) = ChangingUser
|
||||
End If
|
||||
End With
|
||||
End Sub
|
||||
Return result
|
||||
End Function
|
||||
Friend Shared Function UpdateHostPath_CheckDownloader() As Boolean
|
||||
If Downloader.Working Then
|
||||
MsgBoxE({"You cannot change global paths while the downloader is working!", "Changing paths"}, vbCritical)
|
||||
Return False
|
||||
Else
|
||||
Return True
|
||||
End If
|
||||
End Function
|
||||
Friend Overloads Shared Function UpdateHostPath(ByVal PathOld As SFile, ByVal PathNew As SFile,
|
||||
ByVal ColNameOld As String, ByVal ColNameNew As String) As Boolean
|
||||
Dim p As PauseModes = NoPauseMode
|
||||
Try
|
||||
If UpdateHostPath_CheckDownloader() Then Return False
|
||||
If Not AEquals(Of String)(PathOld.PathWithSeparator, PathNew.PathWithSeparator) Or Not AEquals(Of String)(ColNameOld, ColNameNew) Then
|
||||
p = Settings.Automation.Pause
|
||||
Settings.Automation.Pause = PauseModes.Unlimited
|
||||
With Settings.Plugins
|
||||
If .Count > 0 Then
|
||||
Dim h As SettingsHost
|
||||
For Each plugin As PluginHost In .Self
|
||||
If plugin.Settings.Count > 0 Then
|
||||
For Each h In plugin.Settings
|
||||
If Not UpdateHostPath(h, PathOld, PathNew, False, False, Not ColNameOld = ColNameNew) Then Return False
|
||||
Next
|
||||
End If
|
||||
Next
|
||||
End If
|
||||
End With
|
||||
End If
|
||||
Return True
|
||||
Catch ex As Exception
|
||||
Return ErrorsDescriber.Execute(EDP.SendToLog, ex, "[SettingsHostCollection.UpdateHostPath]", False)
|
||||
Finally
|
||||
If p <> NoPauseMode Then Settings.Automation.Pause = p
|
||||
End Try
|
||||
End Function
|
||||
Friend Overloads Shared Function UpdateHostPath(ByVal Host As SettingsHost, ByVal PathOld As SFile, ByVal PathNew As SFile,
|
||||
Optional ByVal Abs As Boolean = True,
|
||||
Optional ByVal PauseDownloader As Boolean = True,
|
||||
Optional ByVal ForceCollections As Boolean = False) As Boolean
|
||||
Dim p As PauseModes = NoPauseMode
|
||||
Try
|
||||
If UpdateHostPath_CheckDownloader() Then Return False
|
||||
If Not PathNew.IsEmptyString And Settings.UsersList.Count > 0 Then
|
||||
Dim hp As SFile = Host.Path(False, True)
|
||||
Dim diffPaths As Boolean = (Abs And hp.PathWithSeparator = PathOld.PathWithSeparator) Or
|
||||
(Not Abs And hp.PathWithSeparator.StartsWith(PathOld.PathWithSeparator))
|
||||
If Not hp.IsEmptyString AndAlso (diffPaths Or ForceCollections) Then
|
||||
If PauseDownloader Then
|
||||
p = Settings.Automation.Pause
|
||||
Settings.Automation.Pause = PauseModes.Unlimited
|
||||
End If
|
||||
Dim checkAccName As Func(Of UserInfo, Boolean) = Function(u) _
|
||||
(
|
||||
(Host.AccountName.IsEmptyString Or Host.AccountName = SettingsHost.NameAccountNameDefault) And
|
||||
(u.AccountName.IsEmptyString Or u.AccountName = SettingsHost.NameAccountNameDefault)
|
||||
) Or
|
||||
(Host.AccountName = u.AccountName)
|
||||
Dim tUser As UserInfo, tUserNew As UserInfo
|
||||
Dim tUserBase As UserDataBase
|
||||
Dim i%
|
||||
Dim newHost As SettingsHost = Nothing
|
||||
Dim userListUpdated As Boolean = False
|
||||
For i = 0 To Settings.UsersList.Count - 1
|
||||
tUser = Settings.UsersList(i)
|
||||
tUserNew = tUser
|
||||
If tUser.Plugin = Host.Key And checkAccName.Invoke(tUser) Then
|
||||
If newHost Is Nothing Then
|
||||
newHost = Host.Clone
|
||||
newHost.AccountName = Host.AccountName
|
||||
If Abs Then
|
||||
newHost.Path = PathNew
|
||||
Else
|
||||
newHost.Path = $"{PathNew.PathWithSeparator}{Host.Source.Site}".CSFileP
|
||||
End If
|
||||
End If
|
||||
If UpdateUserAccount(tUserNew, Host, newHost, False,, ForceCollections) Then
|
||||
tUserBase = Settings.GetUser(tUser)
|
||||
If Not tUserBase Is Nothing Then tUserBase.User = tUserNew : tUserBase.UpdateUserInformation(True)
|
||||
Settings.UsersList(i) = tUserNew
|
||||
userListUpdated = True
|
||||
End If
|
||||
End If
|
||||
Next
|
||||
newHost.DisposeIfReady(False)
|
||||
If userListUpdated Then Settings.UpdateUsersList()
|
||||
If Abs Then
|
||||
Host.Path = PathNew
|
||||
Else
|
||||
Host.Path = $"{PathNew.PathWithSeparator}{Host.Source.Site}".CSFileP
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
Return True
|
||||
Catch ex As Exception
|
||||
Return ErrorsDescriber.Execute(EDP.SendToLog, ex, "[SettingsHostCollection.UpdateHostPath(HOST)]", False)
|
||||
Finally
|
||||
If p <> NoPauseMode Then Settings.Automation.Pause = p
|
||||
End Try
|
||||
End Function
|
||||
#End Region
|
||||
#Region "Count, Item"
|
||||
Friend ReadOnly Property Count As Integer Implements IMyEnumerator(Of SettingsHost).MyEnumeratorCount
|
||||
|
||||
@@ -173,6 +173,19 @@
|
||||
<Compile Include="API\Base\M3U8Base.vb" />
|
||||
<Compile Include="API\Base\ProfileSaved.vb" />
|
||||
<Compile Include="API\Base\SiteSettingsBase.vb" />
|
||||
<Compile Include="API\BaseObjects\SplitCollectionUserInfo.vb" />
|
||||
<Compile Include="API\BaseObjects\SplitCollectionUserInfoChangePathsForm.Designer.vb">
|
||||
<DependentUpon>SplitCollectionUserInfoChangePathsForm.vb</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="API\BaseObjects\SplitCollectionUserInfoChangePathsForm.vb">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="API\BaseObjects\SplitCollectionUserInfoPathForm.Designer.vb">
|
||||
<DependentUpon>SplitCollectionUserInfoPathForm.vb</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="API\BaseObjects\SplitCollectionUserInfoPathForm.vb">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="API\Base\Structures.vb" />
|
||||
<Compile Include="API\Base\TokenBatch.vb" />
|
||||
<Compile Include="API\Base\YTDLP.vb" />
|
||||
@@ -518,6 +531,12 @@
|
||||
<EmbeddedResource Include="API\BaseObjects\InternalSettingsForm.resx">
|
||||
<DependentUpon>InternalSettingsForm.vb</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="API\BaseObjects\SplitCollectionUserInfoChangePathsForm.resx">
|
||||
<DependentUpon>SplitCollectionUserInfoChangePathsForm.vb</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="API\BaseObjects\SplitCollectionUserInfoPathForm.resx">
|
||||
<DependentUpon>SplitCollectionUserInfoPathForm.vb</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="API\OnlyFans\OFResources.resx">
|
||||
<CustomToolNamespace>My.Resources</CustomToolNamespace>
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
|
||||
@@ -54,6 +54,14 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
||||
a.Invoke(CurlFile)
|
||||
Plugins.ForEach(Sub(p) p.Settings.UpdateEnvironmentPrograms(EnvironmentProgramsList, CMDEncoding.Value))
|
||||
End Sub
|
||||
Friend Sub UpdatePluginsUserAgent(Optional ByVal InvokeUpdate As Boolean = True)
|
||||
If Not UserAgent.IsEmptyString Then
|
||||
If InvokeUpdate Then BeginUpdate()
|
||||
Dim __userAgent$ = UserAgent
|
||||
Plugins.ForEach(Sub(p) p.Settings.ListForEach(Sub(ps, psi) ps.Source.UserAgentDefault = __userAgent))
|
||||
If InvokeUpdate Then EndUpdate()
|
||||
End If
|
||||
End Sub
|
||||
Friend Class ProgramFile
|
||||
Friend Const File_FFMPEG As String = "ffmpeg.exe"
|
||||
Friend Const File_YTDLP As String = "yt-dlp.exe"
|
||||
@@ -244,7 +252,6 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
||||
MaxUsersJobsCount = New XMLValue(Of Integer)("MaxJobsCount", DefaultMaxDownloadingTasks, MyXML, n)
|
||||
UserAgent = New XMLValue(Of String)("UserAgent",, MyXML, n)
|
||||
If Not SettingsReoranized Then UserAgent.Value = New XMLValue(Of String)("UserAgent",, MyXML).Value 'URGENT: remove this line
|
||||
If Not UserAgent.IsEmptyString Then DefaultUserAgent = UserAgent
|
||||
ImgurClientID = New XMLValue(Of String)("ImgurClientID", String.Empty, MyXML, {Name_Node_Sites})
|
||||
|
||||
'Basis: new version
|
||||
@@ -349,6 +356,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
||||
DownloadsCompleteCommand = New XMLValueAttribute(Of String, Boolean)("DownloadsCompleteCommand", "Use",,, MyXML, n)
|
||||
ReparseMissingInTheRoutine = New XMLValue(Of Boolean)("ReparseMissingInTheRoutine", False, MyXML, n)
|
||||
UseDefaultAccountIfMissing = New XMLValue(Of Boolean)("UseDefaultAccountIfMissing", True, MyXML, n)
|
||||
AutomationBrushUndownloadedPlansMinutes = New XMLValue(Of Integer)("AutomationBrushUndownloadedPlansMinutes", 10080, MyXML, n)
|
||||
|
||||
'Downloading: file naming
|
||||
n_old = {"Users", "FileName"}
|
||||
@@ -394,6 +402,8 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
||||
FeedForeColor.SetExtended("FeedColorFore",, MyXML, n)
|
||||
FeedEndless = New XMLValue(Of Boolean)("Endless", True, MyXML, n)
|
||||
FeedAddSessionToCaption = New XMLValue(Of Boolean)("AddSessionToCaption", False, MyXML, n)
|
||||
FeedAddSiteToCaption = New XMLValue(Of Boolean)("AddSiteToCaption", True, MyXML, n)
|
||||
FeedAddTypeToCaption = New XMLValue(Of Boolean)("AddTypeToCaption", False, MyXML, n)
|
||||
FeedAddDateToCaption = New XMLValue(Of Boolean)("AddDateToCaption", True, MyXML, n)
|
||||
FeedStoreSessionsData = New XMLValue(Of Boolean)("StoreSessionsData", True, MyXML, n)
|
||||
FeedStoredSessionsNumber = New XMLValue(Of Integer)("StoredSessionsNumber", 20, MyXML, n)
|
||||
@@ -462,6 +472,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
||||
Plugins.AddRange(tmpPluginList)
|
||||
End If
|
||||
UpdateEnvironmentPrograms()
|
||||
UpdatePluginsUserAgent(False)
|
||||
#End Region
|
||||
|
||||
Labels = New LabelsKeeper(MyXML)
|
||||
@@ -993,6 +1004,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
||||
End Get
|
||||
End Property
|
||||
#End Region
|
||||
#Region "Properties"
|
||||
#Region "Basis"
|
||||
Friend ReadOnly Property GlobalPath As XMLValue(Of SFile)
|
||||
Friend ReadOnly Property MaxLargeImageHeight As XMLValue(Of Integer)
|
||||
@@ -1001,7 +1013,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
||||
Friend ReadOnly Property CollectionsPathF As SFile
|
||||
Get
|
||||
If GlobalPath.IsEmptyString Then
|
||||
Throw New ArgumentNullException("GlobalPath", "GlobalPath not set")
|
||||
Throw New ArgumentNullException("GlobalPath", "Global path not set")
|
||||
Else
|
||||
Return SFile.GetPath($"{GlobalPath.Value.PathWithSeparator}{CollectionsPath.Value}")
|
||||
End If
|
||||
@@ -1196,6 +1208,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
||||
Friend ReadOnly Property DownloadsCompleteCommand As XMLValueAttribute(Of String, Boolean)
|
||||
Friend ReadOnly Property ReparseMissingInTheRoutine As XMLValue(Of Boolean)
|
||||
Friend ReadOnly Property UseDefaultAccountIfMissing As XMLValue(Of Boolean)
|
||||
Friend ReadOnly Property AutomationBrushUndownloadedPlansMinutes As XMLValue(Of Integer)
|
||||
#End Region
|
||||
#Region "Downloading: file naming"
|
||||
Friend ReadOnly Property FileAddDateToFileName As XMLValue(Of Boolean)
|
||||
@@ -1249,6 +1262,8 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
||||
Friend ReadOnly Property FeedForeColor As XMLValue(Of Color)
|
||||
Friend ReadOnly Property FeedEndless As XMLValue(Of Boolean)
|
||||
Friend ReadOnly Property FeedAddSessionToCaption As XMLValue(Of Boolean)
|
||||
Friend ReadOnly Property FeedAddSiteToCaption As XMLValue(Of Boolean)
|
||||
Friend ReadOnly Property FeedAddTypeToCaption As XMLValue(Of Boolean)
|
||||
Friend ReadOnly Property FeedAddDateToCaption As XMLValue(Of Boolean)
|
||||
Friend ReadOnly Property FeedStoreSessionsData As XMLValue(Of Boolean)
|
||||
Friend ReadOnly Property FeedStoredSessionsNumber As XMLValue(Of Integer)
|
||||
@@ -1301,6 +1316,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
||||
Friend ReadOnly Property LatestSavingPath As XMLValue(Of SFile)
|
||||
Friend ReadOnly Property LatestSelectedChannel As XMLValue(Of String)
|
||||
#End Region
|
||||
#End Region
|
||||
#Region "IDisposable Support"
|
||||
Private disposedValue As Boolean = False
|
||||
Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
|
||||
|
||||
@@ -31,6 +31,7 @@ Friend Class UserSearchForm
|
||||
Else
|
||||
If User.IncludedInCollection Then Text &= $"[{User.CollectionName}] "
|
||||
Text &= $"[{User.Site}] [{User.Name}]"
|
||||
If Not User.FriendlyName.IsEmptyString Then Text &= $" ({User.FriendlyName})"
|
||||
End If
|
||||
End Sub
|
||||
Private Function CompareTo(ByVal Other As SearchResult) As Integer Implements IComparable(Of SearchResult).CompareTo
|
||||
|
||||
24
Tools/DeleteGDLTempFiles.bat
Normal file
@@ -0,0 +1,24 @@
|
||||
REM https://superuser.com/a/577640/1410018
|
||||
|
||||
@echo off
|
||||
|
||||
set dirname=_MEI
|
||||
set usewildcard=true
|
||||
set found=false
|
||||
if %usewildcard% == true (
|
||||
set dirname=*%dirname%*
|
||||
)
|
||||
set directorytosearch=%UserProfile%\AppData\Local\Temp
|
||||
echo Searching for %dirname% in %directorytosearch%
|
||||
|
||||
for /d %%i in (%directorytosearch%\%dirname%) do (
|
||||
IF EXIST %%i (
|
||||
set found=true
|
||||
echo Deleting the folder %%i
|
||||
rmdir /s /q "%%i"
|
||||
)
|
||||
)
|
||||
|
||||
if NOT "%found%" == "true" (
|
||||
echo No directories were found with the name of %dirname%
|
||||
)
|
||||