Compare commits

...

3 Commits

Author SHA1 Message Date
Andy
52a43b9207 2024.1.26.0
YT
YouTubeSettings: add property DefaultVideoFPS
VideoOptionsForm, YouTubeMediaContainerBase: add FPS reduction

SCrawler
API.Instagram: change back aspect ratio determining
API.TikTok: add the ability to use a regex to clean the title
API.YouTube: add the ability to ignore community errors
2024-01-26 04:13:42 +03:00
Andy
5bc559c448 2024.1.20.0
API.Instagram: add reels support (separate)
API.LPSG: handle 404 error
2024-01-20 00:00:23 +03:00
Andy
b37f641582 2024.1.18.0
YT: url array form doesn't show scrollbars
API.Instagram: change aspect ratio determining
API.xHamster: some user videos were not downloaded
API.UserDataBind: incorrect collection sorting
DownloadFeedForm: change separator in result dialog when merging feeds
2024-01-18 01:23:55 +03:00
24 changed files with 633 additions and 199 deletions

View File

@@ -1,3 +1,33 @@
# 2024.1.26.0
*2024-01-26*
- Added
- YouTube (standalone app): **the ability to reduce video FPS**
- TikTok: the ability to use a regex to clean the title
- YouTube (SCrawler): the ability to ignore community errors
- Fixed
- Instagram: stories (user) downloading with the wrong aspect ratio for some users
- Minor bugs
# 2024.1.20.0
*2024-01-20*
- Added
- Instagram: **the ability to download reels**
- LPSG: handle 404 error
# 2024.1.18.0
*2024-01-18*
- Fixed
- Main window: incorrect collection sorting
- xHamster: some user videos were not downloaded
- YouTube (standalone app): URL array form doesn't show scrollbars
- Minor bugs
# 2024.1.12.1 # 2024.1.12.1
*2024-01-12* *2024-01-12*

View File

@@ -15,6 +15,7 @@ Imports PersonalUtilities.Forms
Imports PersonalUtilities.Functions.XML Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.XML.Base Imports PersonalUtilities.Functions.XML.Base
Imports PersonalUtilities.Functions.XML.Objects Imports PersonalUtilities.Functions.XML.Objects
Imports PersonalUtilities.Functions.XML.Attributes
Imports PersonalUtilities.Functions.XML.Attributes.Specialized Imports PersonalUtilities.Functions.XML.Attributes.Specialized
Imports PersonalUtilities.Tools Imports PersonalUtilities.Tools
Imports PersonalUtilities.Tools.Grid.Base Imports PersonalUtilities.Tools.Grid.Base
@@ -275,6 +276,71 @@ Namespace API.YouTube.Base
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}), Category("Defaults Video"), DisplayName("Include zero size formats"), <Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}), Category("Defaults Video"), DisplayName("Include zero size formats"),
Description("Include formats with zero size (or undefined size).")> Description("Include formats with zero size (or undefined size).")>
Public ReadOnly Property DefaultVideoIncludeNullSize As XMLValue(Of Boolean) Public ReadOnly Property DefaultVideoIncludeNullSize As XMLValue(Of Boolean)
<Browsable(False), XMLV("DefaultVideoFPS", {"DefaultsVideo"}, -1)>
Private ReadOnly Property DefaultVideoFPS_XML As XMLValue(Of Double)
<Browsable(True), GridVisible, Category("Defaults Video"), DisplayName("Defaults Video FPS"),
Description("Set default video FPS (only to reduce video FPS). Default: -1 (disabled)."),
TypeConverter(GetType(FieldsTypeConverter)), GridFormatProvider(GetType(FpsFormatProvider))>
Public Property DefaultVideoFPS As Double
Get
Return DefaultVideoFPS_XML
End Get
Set(ByVal fps As Double)
DefaultVideoFPS_XML.Value = fps
End Set
End Property
Private Function ShouldSerializeDefaultVideoFPS() As Boolean
Return DefaultVideoFPS <> DefaultVideoFPS_XML.Value
End Function
Private Sub ResetDefaultVideoFPS()
DefaultVideoFPS = -1
End Sub
Friend Class FpsFormatProvider : Implements IGridConversionProvider
Private Property Converter As TypeConverter Implements IGridConversionProvider.Converter
Private Property Context As ITypeDescriptorContext Implements IGridConversionProvider.Context
Private Property DataType As Type Implements IGridConversionProvider.DataType
Private Property Instance As Object Implements IGridConversionProvider.Instance
Friend Shared ReadOnly Property MyProviderDefault As ANumbers
Get
Return New ANumbers(ANumbers.Cultures.Primitive) With {.DecimalDigits = 5, .TrimDecimalDigits = True}
End Get
End Property
Friend Const ErrorMessageDefault As String = "The fps value must be a number"
Private ReadOnly MyProvider As ANumbers = MyProviderDefault
Friend Function ToObject(ByVal Context As ITypeDescriptorContext, ByVal Culture As CultureInfo, ByVal Value As Object) As Object Implements IGridConversionProvider.ToObject
Return AConvert(Of Double)(Value, MyProvider, -1)
End Function
Friend Overloads Function ToString(ByVal Context As ITypeDescriptorContext, ByVal Culture As CultureInfo, ByVal Value As Object,
ByVal DestinationType As Type) As Object Implements IGridConversionProvider.ToString
If ACheck(Of Double)(Value, AModes.Var, MyProvider) Then
Return Value.ToString
Else
Return -1
End If
End Function
Friend Function CreateInstance(ByVal Context As ITypeDescriptorContext, ByVal NewValue As Object, ByRef RefreshGrid As Boolean) As Object Implements IGridConversionProvider.CreateInstance
If ACheck(Of Double)(NewValue, AModes.Var, MyProvider) Then
Return NewValue
Else
RefreshGrid = True
Return -1
End If
End Function
Friend Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider,
Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert
Return AConvert(Value, AModes.Var, DestinationType,, True, -1, MyProvider, EDP.ReturnValue)
End Function
Friend Function IsValid(ByVal Context As ITypeDescriptorContext, ByVal Value As Object, ByVal DestinationType As Type) As Boolean Implements IGridValidator.IsValid
If ACheck(Of Double)(Value, AModes.Var, MyProvider) Then
Return True
Else
Throw New FormatException(ErrorMessageDefault)
End If
End Function
Private Function GetFormat(ByVal FormatType As Type) As Object Implements IFormatProvider.GetFormat
Throw New NotImplementedException("'GetFormat' is not available in 'FpsFormatProvider'")
End Function
End Class
#End Region #End Region
#Region "Defaults Audio" #Region "Defaults Audio"
<Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, "AAC"), Category("Defaults Audio"), DisplayName("Default codec"), <Browsable(True), GridVisible, XMLVN({"DefaultsAudio"}, "AAC"), Category("Defaults Audio"), DisplayName("Default codec"),

View File

@@ -100,6 +100,7 @@ Namespace API.YouTube.Controls
Me.TXT_URLS.MaxLength = 2147483647 Me.TXT_URLS.MaxLength = 2147483647
Me.TXT_URLS.Multiline = True Me.TXT_URLS.Multiline = True
Me.TXT_URLS.Name = "TXT_URLS" Me.TXT_URLS.Name = "TXT_URLS"
Me.TXT_URLS.ScrollBars = System.Windows.Forms.ScrollBars.Both
Me.TXT_URLS.Size = New System.Drawing.Size(372, 261) Me.TXT_URLS.Size = New System.Drawing.Size(372, 261)
Me.TXT_URLS.TabIndex = 0 Me.TXT_URLS.TabIndex = 0
' '

View File

@@ -50,6 +50,7 @@ Namespace API.YouTube.Controls
Dim ActionButton8 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton8 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton9 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton9 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton10 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton10 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton11 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Me.ICON_VIDEO = New System.Windows.Forms.PictureBox() Me.ICON_VIDEO = New System.Windows.Forms.PictureBox()
Me.LBL_TITLE = New System.Windows.Forms.Label() Me.LBL_TITLE = New System.Windows.Forms.Label()
Me.TP_HEADER_INFO_2 = New System.Windows.Forms.TableLayoutPanel() Me.TP_HEADER_INFO_2 = New System.Windows.Forms.TableLayoutPanel()
@@ -71,6 +72,7 @@ Namespace API.YouTube.Controls
Me.CMB_FORMAT = New System.Windows.Forms.ComboBox() Me.CMB_FORMAT = New System.Windows.Forms.ComboBox()
Me.CMB_AUDIO_CODEC = New System.Windows.Forms.ComboBox() Me.CMB_AUDIO_CODEC = New System.Windows.Forms.ComboBox()
Me.NUM_RES = New System.Windows.Forms.NumericUpDown() Me.NUM_RES = New System.Windows.Forms.NumericUpDown()
Me.TXT_FPS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TP_CONTROLS = New System.Windows.Forms.TableLayoutPanel() Me.TP_CONTROLS = New System.Windows.Forms.TableLayoutPanel()
Me.TXT_SUBS_ADDIT = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_SUBS_ADDIT = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_EXTRA_AUDIO_FORMATS = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_EXTRA_AUDIO_FORMATS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
@@ -105,6 +107,7 @@ Namespace API.YouTube.Controls
Me.TP_MAIN.SuspendLayout() Me.TP_MAIN.SuspendLayout()
Me.TP_OPTIONS.SuspendLayout() Me.TP_OPTIONS.SuspendLayout()
CType(Me.NUM_RES, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.NUM_RES, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_FPS, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_SUBS_ADDIT, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_SUBS_ADDIT, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_EXTRA_AUDIO_FORMATS, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_EXTRA_AUDIO_FORMATS, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout() Me.SuspendLayout()
@@ -123,7 +126,7 @@ Namespace API.YouTube.Controls
TP_HEADER.Name = "TP_HEADER" TP_HEADER.Name = "TP_HEADER"
TP_HEADER.RowCount = 1 TP_HEADER.RowCount = 1
TP_HEADER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) TP_HEADER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_HEADER.Size = New System.Drawing.Size(599, 63) TP_HEADER.Size = New System.Drawing.Size(719, 63)
TP_HEADER.TabIndex = 0 TP_HEADER.TabIndex = 0
' '
'ICON_VIDEO 'ICON_VIDEO
@@ -152,7 +155,7 @@ Namespace API.YouTube.Controls
TP_HEADER_INFO.RowCount = 2 TP_HEADER_INFO.RowCount = 2
TP_HEADER_INFO.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) TP_HEADER_INFO.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_HEADER_INFO.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) TP_HEADER_INFO.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_HEADER_INFO.Size = New System.Drawing.Size(469, 63) TP_HEADER_INFO.Size = New System.Drawing.Size(589, 63)
TP_HEADER_INFO.TabIndex = 0 TP_HEADER_INFO.TabIndex = 0
' '
'LBL_TITLE 'LBL_TITLE
@@ -161,7 +164,7 @@ Namespace API.YouTube.Controls
Me.LBL_TITLE.Font = New System.Drawing.Font("Arial", 9.0!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(204, Byte)) Me.LBL_TITLE.Font = New System.Drawing.Font("Arial", 9.0!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(204, Byte))
Me.LBL_TITLE.Location = New System.Drawing.Point(3, 0) Me.LBL_TITLE.Location = New System.Drawing.Point(3, 0)
Me.LBL_TITLE.Name = "LBL_TITLE" Me.LBL_TITLE.Name = "LBL_TITLE"
Me.LBL_TITLE.Size = New System.Drawing.Size(463, 31) Me.LBL_TITLE.Size = New System.Drawing.Size(583, 31)
Me.LBL_TITLE.TabIndex = 0 Me.LBL_TITLE.TabIndex = 0
Me.LBL_TITLE.Text = "Video title" Me.LBL_TITLE.Text = "Video title"
Me.LBL_TITLE.TextAlign = System.Drawing.ContentAlignment.MiddleLeft Me.LBL_TITLE.TextAlign = System.Drawing.ContentAlignment.MiddleLeft
@@ -183,7 +186,7 @@ Namespace API.YouTube.Controls
Me.TP_HEADER_INFO_2.Name = "TP_HEADER_INFO_2" Me.TP_HEADER_INFO_2.Name = "TP_HEADER_INFO_2"
Me.TP_HEADER_INFO_2.RowCount = 1 Me.TP_HEADER_INFO_2.RowCount = 1
Me.TP_HEADER_INFO_2.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) Me.TP_HEADER_INFO_2.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_HEADER_INFO_2.Size = New System.Drawing.Size(469, 32) Me.TP_HEADER_INFO_2.Size = New System.Drawing.Size(589, 32)
Me.TP_HEADER_INFO_2.TabIndex = 1 Me.TP_HEADER_INFO_2.TabIndex = 1
' '
'ICON_CLOCK 'ICON_CLOCK
@@ -230,7 +233,7 @@ Namespace API.YouTube.Controls
Me.LBL_URL.LinkColor = System.Drawing.Color.FromArgb(CType(CType(0, Byte), Integer), CType(CType(0, Byte), Integer), CType(CType(192, Byte), Integer)) Me.LBL_URL.LinkColor = System.Drawing.Color.FromArgb(CType(CType(0, Byte), Integer), CType(CType(0, Byte), Integer), CType(CType(192, Byte), Integer))
Me.LBL_URL.Location = New System.Drawing.Point(115, 0) Me.LBL_URL.Location = New System.Drawing.Point(115, 0)
Me.LBL_URL.Name = "LBL_URL" Me.LBL_URL.Name = "LBL_URL"
Me.LBL_URL.Size = New System.Drawing.Size(351, 32) Me.LBL_URL.Size = New System.Drawing.Size(471, 32)
Me.LBL_URL.TabIndex = 1 Me.LBL_URL.TabIndex = 1
Me.LBL_URL.TabStop = True Me.LBL_URL.TabStop = True
Me.LBL_URL.Text = "https://www.youtube.com/watch?v=abcdefghijk" Me.LBL_URL.Text = "https://www.youtube.com/watch?v=abcdefghijk"
@@ -250,7 +253,7 @@ Namespace API.YouTube.Controls
TP_FOOTER.RowCount = 2 TP_FOOTER.RowCount = 2
TP_FOOTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) TP_FOOTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_FOOTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) TP_FOOTER.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
TP_FOOTER.Size = New System.Drawing.Size(589, 52) TP_FOOTER.Size = New System.Drawing.Size(709, 52)
TP_FOOTER.TabIndex = 5 TP_FOOTER.TabIndex = 5
' '
'TP_DESTINATION 'TP_DESTINATION
@@ -266,7 +269,7 @@ Namespace API.YouTube.Controls
TP_DESTINATION.Name = "TP_DESTINATION" TP_DESTINATION.Name = "TP_DESTINATION"
TP_DESTINATION.RowCount = 1 TP_DESTINATION.RowCount = 1
TP_DESTINATION.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) TP_DESTINATION.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_DESTINATION.Size = New System.Drawing.Size(589, 26) TP_DESTINATION.Size = New System.Drawing.Size(709, 26)
TP_DESTINATION.TabIndex = 0 TP_DESTINATION.TabIndex = 0
' '
'TXT_FILE 'TXT_FILE
@@ -290,14 +293,14 @@ Namespace API.YouTube.Controls
Me.TXT_FILE.Location = New System.Drawing.Point(1, 1) Me.TXT_FILE.Location = New System.Drawing.Point(1, 1)
Me.TXT_FILE.Margin = New System.Windows.Forms.Padding(1) Me.TXT_FILE.Margin = New System.Windows.Forms.Padding(1)
Me.TXT_FILE.Name = "TXT_FILE" Me.TXT_FILE.Name = "TXT_FILE"
Me.TXT_FILE.Size = New System.Drawing.Size(507, 22) Me.TXT_FILE.Size = New System.Drawing.Size(627, 22)
Me.TXT_FILE.TabIndex = 0 Me.TXT_FILE.TabIndex = 0
Me.TXT_FILE.TextBoxBorderStyle = System.Windows.Forms.BorderStyle.FixedSingle Me.TXT_FILE.TextBoxBorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
' '
'BTT_BROWSE 'BTT_BROWSE
' '
Me.BTT_BROWSE.Dock = System.Windows.Forms.DockStyle.Fill Me.BTT_BROWSE.Dock = System.Windows.Forms.DockStyle.Fill
Me.BTT_BROWSE.Location = New System.Drawing.Point(512, 2) Me.BTT_BROWSE.Location = New System.Drawing.Point(632, 2)
Me.BTT_BROWSE.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2) Me.BTT_BROWSE.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2)
Me.BTT_BROWSE.Name = "BTT_BROWSE" Me.BTT_BROWSE.Name = "BTT_BROWSE"
Me.BTT_BROWSE.Size = New System.Drawing.Size(74, 22) Me.BTT_BROWSE.Size = New System.Drawing.Size(74, 22)
@@ -321,13 +324,13 @@ Namespace API.YouTube.Controls
TP_OK_CANCEL.RowCount = 1 TP_OK_CANCEL.RowCount = 1
TP_OK_CANCEL.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) TP_OK_CANCEL.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_OK_CANCEL.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26.0!)) TP_OK_CANCEL.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26.0!))
TP_OK_CANCEL.Size = New System.Drawing.Size(589, 26) TP_OK_CANCEL.Size = New System.Drawing.Size(709, 26)
TP_OK_CANCEL.TabIndex = 1 TP_OK_CANCEL.TabIndex = 1
' '
'BTT_DOWN 'BTT_DOWN
' '
Me.BTT_DOWN.Dock = System.Windows.Forms.DockStyle.Fill Me.BTT_DOWN.Dock = System.Windows.Forms.DockStyle.Fill
Me.BTT_DOWN.Location = New System.Drawing.Point(432, 2) Me.BTT_DOWN.Location = New System.Drawing.Point(552, 2)
Me.BTT_DOWN.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2) Me.BTT_DOWN.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2)
Me.BTT_DOWN.Name = "BTT_DOWN" Me.BTT_DOWN.Name = "BTT_DOWN"
Me.BTT_DOWN.Size = New System.Drawing.Size(74, 22) Me.BTT_DOWN.Size = New System.Drawing.Size(74, 22)
@@ -339,7 +342,7 @@ Namespace API.YouTube.Controls
' '
Me.BTT_CANCEL.DialogResult = System.Windows.Forms.DialogResult.Cancel Me.BTT_CANCEL.DialogResult = System.Windows.Forms.DialogResult.Cancel
Me.BTT_CANCEL.Dock = System.Windows.Forms.DockStyle.Fill Me.BTT_CANCEL.Dock = System.Windows.Forms.DockStyle.Fill
Me.BTT_CANCEL.Location = New System.Drawing.Point(512, 2) Me.BTT_CANCEL.Location = New System.Drawing.Point(632, 2)
Me.BTT_CANCEL.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2) Me.BTT_CANCEL.Margin = New System.Windows.Forms.Padding(3, 2, 3, 2)
Me.BTT_CANCEL.Name = "BTT_CANCEL" Me.BTT_CANCEL.Name = "BTT_CANCEL"
Me.BTT_CANCEL.Size = New System.Drawing.Size(74, 22) Me.BTT_CANCEL.Size = New System.Drawing.Size(74, 22)
@@ -354,7 +357,7 @@ Namespace API.YouTube.Controls
LB_SEP_1.Location = New System.Drawing.Point(6, 179) LB_SEP_1.Location = New System.Drawing.Point(6, 179)
LB_SEP_1.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0) LB_SEP_1.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0)
LB_SEP_1.Name = "LB_SEP_1" LB_SEP_1.Name = "LB_SEP_1"
LB_SEP_1.Size = New System.Drawing.Size(589, 1) LB_SEP_1.Size = New System.Drawing.Size(709, 1)
LB_SEP_1.TabIndex = 3 LB_SEP_1.TabIndex = 3
' '
'LB_SEP_2 'LB_SEP_2
@@ -364,7 +367,7 @@ Namespace API.YouTube.Controls
LB_SEP_2.Location = New System.Drawing.Point(6, 209) LB_SEP_2.Location = New System.Drawing.Point(6, 209)
LB_SEP_2.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0) LB_SEP_2.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0)
LB_SEP_2.Name = "LB_SEP_2" LB_SEP_2.Name = "LB_SEP_2"
LB_SEP_2.Size = New System.Drawing.Size(589, 1) LB_SEP_2.Size = New System.Drawing.Size(709, 1)
LB_SEP_2.TabIndex = 5 LB_SEP_2.TabIndex = 5
' '
'TP_WHAT 'TP_WHAT
@@ -436,7 +439,7 @@ Namespace API.YouTube.Controls
' '
LBL_SUBS_FORMAT.AutoSize = True LBL_SUBS_FORMAT.AutoSize = True
LBL_SUBS_FORMAT.Dock = System.Windows.Forms.DockStyle.Fill LBL_SUBS_FORMAT.Dock = System.Windows.Forms.DockStyle.Fill
LBL_SUBS_FORMAT.Location = New System.Drawing.Point(432, 0) LBL_SUBS_FORMAT.Location = New System.Drawing.Point(552, 0)
LBL_SUBS_FORMAT.Name = "LBL_SUBS_FORMAT" LBL_SUBS_FORMAT.Name = "LBL_SUBS_FORMAT"
LBL_SUBS_FORMAT.Size = New System.Drawing.Size(74, 28) LBL_SUBS_FORMAT.Size = New System.Drawing.Size(74, 28)
LBL_SUBS_FORMAT.TabIndex = 2 LBL_SUBS_FORMAT.TabIndex = 2
@@ -448,7 +451,7 @@ Namespace API.YouTube.Controls
' '
Me.LBL_AUDIO_CODEC.AutoSize = True Me.LBL_AUDIO_CODEC.AutoSize = True
Me.LBL_AUDIO_CODEC.Dock = System.Windows.Forms.DockStyle.Fill Me.LBL_AUDIO_CODEC.Dock = System.Windows.Forms.DockStyle.Fill
Me.LBL_AUDIO_CODEC.Location = New System.Drawing.Point(432, 0) Me.LBL_AUDIO_CODEC.Location = New System.Drawing.Point(552, 0)
Me.LBL_AUDIO_CODEC.Name = "LBL_AUDIO_CODEC" Me.LBL_AUDIO_CODEC.Name = "LBL_AUDIO_CODEC"
Me.LBL_AUDIO_CODEC.Size = New System.Drawing.Size(74, 28) Me.LBL_AUDIO_CODEC.Size = New System.Drawing.Size(74, 28)
Me.LBL_AUDIO_CODEC.TabIndex = 5 Me.LBL_AUDIO_CODEC.TabIndex = 5
@@ -470,7 +473,7 @@ Namespace API.YouTube.Controls
Me.TP_HEADER_BASE.RowCount = 1 Me.TP_HEADER_BASE.RowCount = 1
Me.TP_HEADER_BASE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) Me.TP_HEADER_BASE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_HEADER_BASE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 64.0!)) Me.TP_HEADER_BASE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 64.0!))
Me.TP_HEADER_BASE.Size = New System.Drawing.Size(601, 65) Me.TP_HEADER_BASE.Size = New System.Drawing.Size(721, 65)
Me.TP_HEADER_BASE.TabIndex = 6 Me.TP_HEADER_BASE.TabIndex = 6
' '
'TP_SUBS 'TP_SUBS
@@ -488,7 +491,7 @@ Namespace API.YouTube.Controls
Me.TP_SUBS.Name = "TP_SUBS" Me.TP_SUBS.Name = "TP_SUBS"
Me.TP_SUBS.RowCount = 1 Me.TP_SUBS.RowCount = 1
Me.TP_SUBS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) Me.TP_SUBS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_SUBS.Size = New System.Drawing.Size(589, 28) Me.TP_SUBS.Size = New System.Drawing.Size(709, 28)
Me.TP_SUBS.TabIndex = 2 Me.TP_SUBS.TabIndex = 2
' '
'TXT_SUBS 'TXT_SUBS
@@ -516,7 +519,7 @@ Namespace API.YouTube.Controls
Me.TXT_SUBS.Dock = System.Windows.Forms.DockStyle.Fill Me.TXT_SUBS.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_SUBS.Location = New System.Drawing.Point(3, 3) Me.TXT_SUBS.Location = New System.Drawing.Point(3, 3)
Me.TXT_SUBS.Name = "TXT_SUBS" Me.TXT_SUBS.Name = "TXT_SUBS"
Me.TXT_SUBS.Size = New System.Drawing.Size(423, 22) Me.TXT_SUBS.Size = New System.Drawing.Size(543, 22)
Me.TXT_SUBS.TabIndex = 0 Me.TXT_SUBS.TabIndex = 0
Me.TXT_SUBS.TextBoxReadOnly = True Me.TXT_SUBS.TextBoxReadOnly = True
' '
@@ -525,7 +528,7 @@ Namespace API.YouTube.Controls
Me.CMB_SUBS_FORMAT.Dock = System.Windows.Forms.DockStyle.Fill Me.CMB_SUBS_FORMAT.Dock = System.Windows.Forms.DockStyle.Fill
Me.CMB_SUBS_FORMAT.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList Me.CMB_SUBS_FORMAT.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
Me.CMB_SUBS_FORMAT.FormattingEnabled = True Me.CMB_SUBS_FORMAT.FormattingEnabled = True
Me.CMB_SUBS_FORMAT.Location = New System.Drawing.Point(512, 3) Me.CMB_SUBS_FORMAT.Location = New System.Drawing.Point(632, 3)
Me.CMB_SUBS_FORMAT.Name = "CMB_SUBS_FORMAT" Me.CMB_SUBS_FORMAT.Name = "CMB_SUBS_FORMAT"
Me.CMB_SUBS_FORMAT.Size = New System.Drawing.Size(74, 21) Me.CMB_SUBS_FORMAT.Size = New System.Drawing.Size(74, 21)
Me.CMB_SUBS_FORMAT.TabIndex = 1 Me.CMB_SUBS_FORMAT.TabIndex = 1
@@ -557,31 +560,33 @@ Namespace API.YouTube.Controls
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 5.0!)) Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 5.0!))
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 58.0!)) Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 58.0!))
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle()) Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle())
Me.TP_MAIN.Size = New System.Drawing.Size(601, 271) Me.TP_MAIN.Size = New System.Drawing.Size(721, 271)
Me.TP_MAIN.TabIndex = 0 Me.TP_MAIN.TabIndex = 0
' '
'TP_OPTIONS 'TP_OPTIONS
' '
Me.TP_OPTIONS.ColumnCount = 6 Me.TP_OPTIONS.ColumnCount = 7
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!)) Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!))
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!)) Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!))
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!)) Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!))
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 120.0!))
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!)) Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!))
Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!)) Me.TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80.0!))
Me.TP_OPTIONS.Controls.Add(LBL_FORMAT, 1, 0) Me.TP_OPTIONS.Controls.Add(LBL_FORMAT, 1, 0)
Me.TP_OPTIONS.Controls.Add(TP_WHAT, 0, 0) Me.TP_OPTIONS.Controls.Add(TP_WHAT, 0, 0)
Me.TP_OPTIONS.Controls.Add(Me.CMB_FORMAT, 2, 0) Me.TP_OPTIONS.Controls.Add(Me.CMB_FORMAT, 2, 0)
Me.TP_OPTIONS.Controls.Add(Me.LBL_AUDIO_CODEC, 4, 0) Me.TP_OPTIONS.Controls.Add(Me.LBL_AUDIO_CODEC, 5, 0)
Me.TP_OPTIONS.Controls.Add(Me.CMB_AUDIO_CODEC, 5, 0) Me.TP_OPTIONS.Controls.Add(Me.CMB_AUDIO_CODEC, 6, 0)
Me.TP_OPTIONS.Controls.Add(Me.NUM_RES, 3, 0) Me.TP_OPTIONS.Controls.Add(Me.NUM_RES, 3, 0)
Me.TP_OPTIONS.Controls.Add(Me.TXT_FPS, 4, 0)
Me.TP_OPTIONS.Dock = System.Windows.Forms.DockStyle.Fill Me.TP_OPTIONS.Dock = System.Windows.Forms.DockStyle.Fill
Me.TP_OPTIONS.Location = New System.Drawing.Point(6, 65) Me.TP_OPTIONS.Location = New System.Drawing.Point(6, 65)
Me.TP_OPTIONS.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0) Me.TP_OPTIONS.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0)
Me.TP_OPTIONS.Name = "TP_OPTIONS" Me.TP_OPTIONS.Name = "TP_OPTIONS"
Me.TP_OPTIONS.RowCount = 1 Me.TP_OPTIONS.RowCount = 1
Me.TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) Me.TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_OPTIONS.Size = New System.Drawing.Size(589, 28) Me.TP_OPTIONS.Size = New System.Drawing.Size(709, 28)
Me.TP_OPTIONS.TabIndex = 1 Me.TP_OPTIONS.TabIndex = 1
' '
'CMB_FORMAT 'CMB_FORMAT
@@ -599,7 +604,7 @@ Namespace API.YouTube.Controls
Me.CMB_AUDIO_CODEC.Dock = System.Windows.Forms.DockStyle.Fill Me.CMB_AUDIO_CODEC.Dock = System.Windows.Forms.DockStyle.Fill
Me.CMB_AUDIO_CODEC.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList Me.CMB_AUDIO_CODEC.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
Me.CMB_AUDIO_CODEC.FormattingEnabled = True Me.CMB_AUDIO_CODEC.FormattingEnabled = True
Me.CMB_AUDIO_CODEC.Location = New System.Drawing.Point(512, 3) Me.CMB_AUDIO_CODEC.Location = New System.Drawing.Point(632, 3)
Me.CMB_AUDIO_CODEC.Name = "CMB_AUDIO_CODEC" Me.CMB_AUDIO_CODEC.Name = "CMB_AUDIO_CODEC"
Me.CMB_AUDIO_CODEC.Size = New System.Drawing.Size(74, 21) Me.CMB_AUDIO_CODEC.Size = New System.Drawing.Size(74, 21)
Me.CMB_AUDIO_CODEC.TabIndex = 3 Me.CMB_AUDIO_CODEC.TabIndex = 3
@@ -616,6 +621,24 @@ Namespace API.YouTube.Controls
Me.NUM_RES.TextAlign = System.Windows.Forms.HorizontalAlignment.Center Me.NUM_RES.TextAlign = System.Windows.Forms.HorizontalAlignment.Center
Me.NUM_RES.Value = New Decimal(New Integer() {1080, 0, 0, 0}) Me.NUM_RES.Value = New Decimal(New Integer() {1080, 0, 0, 0})
' '
'TXT_FPS
'
ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image)
ActionButton5.Name = "Clear"
ActionButton5.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_FPS.Buttons.Add(ActionButton5)
Me.TXT_FPS.CaptionText = "FPS"
Me.TXT_FPS.CaptionToolTipEnabled = True
Me.TXT_FPS.CaptionToolTipText = "You can reduce the video FPS by setting the FPS value in this field."
Me.TXT_FPS.CaptionWidth = 30.0R
Me.TXT_FPS.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_FPS.Location = New System.Drawing.Point(432, 2)
Me.TXT_FPS.Margin = New System.Windows.Forms.Padding(3, 2, 3, 3)
Me.TXT_FPS.Name = "TXT_FPS"
Me.TXT_FPS.Size = New System.Drawing.Size(114, 22)
Me.TXT_FPS.TabIndex = 6
Me.TXT_FPS.TextBoxWidthMinimal = 30
'
'TP_CONTROLS 'TP_CONTROLS
' '
Me.TP_CONTROLS.ColumnCount = 1 Me.TP_CONTROLS.ColumnCount = 1
@@ -626,29 +649,29 @@ Namespace API.YouTube.Controls
Me.TP_CONTROLS.Name = "TP_CONTROLS" Me.TP_CONTROLS.Name = "TP_CONTROLS"
Me.TP_CONTROLS.RowCount = 1 Me.TP_CONTROLS.RowCount = 1
Me.TP_CONTROLS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) Me.TP_CONTROLS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_CONTROLS.Size = New System.Drawing.Size(595, 25) Me.TP_CONTROLS.Size = New System.Drawing.Size(715, 25)
Me.TP_CONTROLS.TabIndex = 0 Me.TP_CONTROLS.TabIndex = 0
' '
'TXT_SUBS_ADDIT 'TXT_SUBS_ADDIT
' '
ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image)
ActionButton5.Enabled = False
ActionButton5.Name = "Open"
ActionButton5.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton5.ToolTipText = "Choose additional formats"
ActionButton6.BackgroundImage = CType(resources.GetObject("ActionButton6.BackgroundImage"), System.Drawing.Image) ActionButton6.BackgroundImage = CType(resources.GetObject("ActionButton6.BackgroundImage"), System.Drawing.Image)
ActionButton6.Enabled = False ActionButton6.Enabled = False
ActionButton6.Name = "Refresh" ActionButton6.Name = "Open"
ActionButton6.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh ActionButton6.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton6.ToolTipText = "Fill in additional formats from the defaults" ActionButton6.ToolTipText = "Choose additional formats"
ActionButton7.BackgroundImage = CType(resources.GetObject("ActionButton7.BackgroundImage"), System.Drawing.Image) ActionButton7.BackgroundImage = CType(resources.GetObject("ActionButton7.BackgroundImage"), System.Drawing.Image)
ActionButton7.Enabled = False ActionButton7.Enabled = False
ActionButton7.Name = "Clear" ActionButton7.Name = "Refresh"
ActionButton7.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton7.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton7.ToolTipText = "Remove all additional formats" ActionButton7.ToolTipText = "Fill in additional formats from the defaults"
Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton5) ActionButton8.BackgroundImage = CType(resources.GetObject("ActionButton8.BackgroundImage"), System.Drawing.Image)
ActionButton8.Enabled = False
ActionButton8.Name = "Clear"
ActionButton8.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
ActionButton8.ToolTipText = "Remove all additional formats"
Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton6) Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton6)
Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton7) Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton7)
Me.TXT_SUBS_ADDIT.Buttons.Add(ActionButton8)
Me.TXT_SUBS_ADDIT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox Me.TXT_SUBS_ADDIT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox
Me.TXT_SUBS_ADDIT.CaptionText = "Additional subtitle formats" Me.TXT_SUBS_ADDIT.CaptionText = "Additional subtitle formats"
Me.TXT_SUBS_ADDIT.CaptionToolTipEnabled = True Me.TXT_SUBS_ADDIT.CaptionToolTipEnabled = True
@@ -659,31 +682,31 @@ Namespace API.YouTube.Controls
Me.TXT_SUBS_ADDIT.Location = New System.Drawing.Point(6, 124) Me.TXT_SUBS_ADDIT.Location = New System.Drawing.Point(6, 124)
Me.TXT_SUBS_ADDIT.Margin = New System.Windows.Forms.Padding(6, 3, 6, 3) Me.TXT_SUBS_ADDIT.Margin = New System.Windows.Forms.Padding(6, 3, 6, 3)
Me.TXT_SUBS_ADDIT.Name = "TXT_SUBS_ADDIT" Me.TXT_SUBS_ADDIT.Name = "TXT_SUBS_ADDIT"
Me.TXT_SUBS_ADDIT.Size = New System.Drawing.Size(589, 22) Me.TXT_SUBS_ADDIT.Size = New System.Drawing.Size(709, 22)
Me.TXT_SUBS_ADDIT.TabIndex = 3 Me.TXT_SUBS_ADDIT.TabIndex = 3
Me.TXT_SUBS_ADDIT.Tag = "s" Me.TXT_SUBS_ADDIT.Tag = "s"
Me.TXT_SUBS_ADDIT.TextBoxReadOnly = True Me.TXT_SUBS_ADDIT.TextBoxReadOnly = True
' '
'TXT_EXTRA_AUDIO_FORMATS 'TXT_EXTRA_AUDIO_FORMATS
' '
ActionButton8.BackgroundImage = CType(resources.GetObject("ActionButton8.BackgroundImage"), System.Drawing.Image)
ActionButton8.Enabled = False
ActionButton8.Name = "Open"
ActionButton8.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton8.ToolTipText = "Choose additional formats"
ActionButton9.BackgroundImage = CType(resources.GetObject("ActionButton9.BackgroundImage"), System.Drawing.Image) ActionButton9.BackgroundImage = CType(resources.GetObject("ActionButton9.BackgroundImage"), System.Drawing.Image)
ActionButton9.Enabled = False ActionButton9.Enabled = False
ActionButton9.Name = "Refresh" ActionButton9.Name = "Open"
ActionButton9.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh ActionButton9.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton9.ToolTipText = "Fill in additional formats from the defaults" ActionButton9.ToolTipText = "Choose additional formats"
ActionButton10.BackgroundImage = CType(resources.GetObject("ActionButton10.BackgroundImage"), System.Drawing.Image) ActionButton10.BackgroundImage = CType(resources.GetObject("ActionButton10.BackgroundImage"), System.Drawing.Image)
ActionButton10.Enabled = False ActionButton10.Enabled = False
ActionButton10.Name = "Clear" ActionButton10.Name = "Refresh"
ActionButton10.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton10.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton10.ToolTipText = "Choose additional formats" ActionButton10.ToolTipText = "Fill in additional formats from the defaults"
Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton8) ActionButton11.BackgroundImage = CType(resources.GetObject("ActionButton11.BackgroundImage"), System.Drawing.Image)
ActionButton11.Enabled = False
ActionButton11.Name = "Clear"
ActionButton11.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
ActionButton11.ToolTipText = "Choose additional formats"
Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton9) Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton9)
Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton10) Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton10)
Me.TXT_EXTRA_AUDIO_FORMATS.Buttons.Add(ActionButton11)
Me.TXT_EXTRA_AUDIO_FORMATS.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox Me.TXT_EXTRA_AUDIO_FORMATS.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox
Me.TXT_EXTRA_AUDIO_FORMATS.CaptionText = "Additional audio formats" Me.TXT_EXTRA_AUDIO_FORMATS.CaptionText = "Additional audio formats"
Me.TXT_EXTRA_AUDIO_FORMATS.CaptionToolTipEnabled = True Me.TXT_EXTRA_AUDIO_FORMATS.CaptionToolTipEnabled = True
@@ -693,7 +716,7 @@ Namespace API.YouTube.Controls
Me.TXT_EXTRA_AUDIO_FORMATS.Location = New System.Drawing.Point(6, 152) Me.TXT_EXTRA_AUDIO_FORMATS.Location = New System.Drawing.Point(6, 152)
Me.TXT_EXTRA_AUDIO_FORMATS.Margin = New System.Windows.Forms.Padding(6, 3, 6, 3) Me.TXT_EXTRA_AUDIO_FORMATS.Margin = New System.Windows.Forms.Padding(6, 3, 6, 3)
Me.TXT_EXTRA_AUDIO_FORMATS.Name = "TXT_EXTRA_AUDIO_FORMATS" Me.TXT_EXTRA_AUDIO_FORMATS.Name = "TXT_EXTRA_AUDIO_FORMATS"
Me.TXT_EXTRA_AUDIO_FORMATS.Size = New System.Drawing.Size(589, 22) Me.TXT_EXTRA_AUDIO_FORMATS.Size = New System.Drawing.Size(709, 22)
Me.TXT_EXTRA_AUDIO_FORMATS.TabIndex = 4 Me.TXT_EXTRA_AUDIO_FORMATS.TabIndex = 4
Me.TXT_EXTRA_AUDIO_FORMATS.Tag = "a" Me.TXT_EXTRA_AUDIO_FORMATS.Tag = "a"
Me.TXT_EXTRA_AUDIO_FORMATS.TextBoxReadOnly = True Me.TXT_EXTRA_AUDIO_FORMATS.TextBoxReadOnly = True
@@ -704,13 +727,14 @@ Namespace API.YouTube.Controls
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.CancelButton = Me.BTT_CANCEL Me.CancelButton = Me.BTT_CANCEL
Me.ClientSize = New System.Drawing.Size(601, 271) Me.ClientSize = New System.Drawing.Size(721, 271)
Me.Controls.Add(Me.TP_MAIN) Me.Controls.Add(Me.TP_MAIN)
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
Me.Icon = Global.SCrawler.My.Resources.SiteYouTube.YouTubeIcon_32 Me.Icon = Global.SCrawler.My.Resources.SiteYouTube.YouTubeIcon_32
Me.KeyPreview = True Me.KeyPreview = True
Me.MaximizeBox = False Me.MaximizeBox = False
Me.MinimizeBox = False Me.MinimizeBox = False
Me.MinimumSize = New System.Drawing.Size(737, 310)
Me.Name = "VideoOptionsForm" Me.Name = "VideoOptionsForm"
Me.ShowInTaskbar = False Me.ShowInTaskbar = False
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
@@ -736,6 +760,7 @@ Namespace API.YouTube.Controls
Me.TP_OPTIONS.ResumeLayout(False) Me.TP_OPTIONS.ResumeLayout(False)
Me.TP_OPTIONS.PerformLayout() Me.TP_OPTIONS.PerformLayout()
CType(Me.NUM_RES, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.NUM_RES, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_FPS, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_SUBS_ADDIT, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_SUBS_ADDIT, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_EXTRA_AUDIO_FORMATS, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_EXTRA_AUDIO_FORMATS, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False) Me.ResumeLayout(False)
@@ -765,5 +790,6 @@ Namespace API.YouTube.Controls
Private WithEvents BTT_DOWN As Button Private WithEvents BTT_DOWN As Button
Private WithEvents BTT_CANCEL As Button Private WithEvents BTT_CANCEL As Button
Private WithEvents TP_HEADER_INFO_2 As TableLayoutPanel Private WithEvents TP_HEADER_INFO_2 As TableLayoutPanel
Private WithEvents TXT_FPS As PersonalUtilities.Forms.Controls.TextBoxExtended
End Class End Class
End Namespace End Namespace

View File

@@ -289,6 +289,14 @@
</value> </value>
</data> </data>
<data name="ActionButton5.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton5.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton6.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
@@ -299,7 +307,7 @@
cMaRN0UdBBkAAAAASUVORK5CYII= cMaRN0UdBBkAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="ActionButton6.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton7.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
@@ -315,7 +323,7 @@
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg== VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="ActionButton7.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton8.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
@@ -323,7 +331,7 @@
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<data name="ActionButton8.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton9.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
@@ -334,7 +342,7 @@
cMaRN0UdBBkAAAAASUVORK5CYII= cMaRN0UdBBkAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="ActionButton9.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton10.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
@@ -350,7 +358,7 @@
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg== VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="ActionButton10.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton11.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go

View File

@@ -22,6 +22,7 @@ Namespace API.YouTube.Controls
Friend Class VideoOptionsForm : Implements IDesignXMLContainer Friend Class VideoOptionsForm : Implements IDesignXMLContainer
#Region "Declarations" #Region "Declarations"
Private MyView As FormView Private MyView As FormView
Private ReadOnly MyFieldsChecker As FieldsChecker
Friend Property DesignXML As EContainer Implements IDesignXMLContainer.DesignXML Friend Property DesignXML As EContainer Implements IDesignXMLContainer.DesignXML
Private Property DesignXMLNodes As String() Implements IDesignXMLContainer.DesignXMLNodes Private Property DesignXMLNodes As String() Implements IDesignXMLContainer.DesignXMLNodes
Private Property DesignXMLNodeName As String Implements IDesignXMLContainer.DesignXMLNodeName Private Property DesignXMLNodeName As String Implements IDesignXMLContainer.DesignXMLNodeName
@@ -30,6 +31,25 @@ Namespace API.YouTube.Controls
Friend Property MyContainer As YouTubeMediaContainerBase Friend Property MyContainer As YouTubeMediaContainerBase
Private Initialization As Boolean = True Private Initialization As Boolean = True
Private ReadOnly IsSavedObject As Boolean Private ReadOnly IsSavedObject As Boolean
Private Class FpsFieldChecker : Inherits FieldsCheckerProviderBase
Private ReadOnly MyProvider As ANumbers = YouTubeSettings.FpsFormatProvider.MyProviderDefault
Public Overrides Property ErrorMessage As String
Get
Return IIf(HasError, YouTubeSettings.FpsFormatProvider.ErrorMessageDefault, String.Empty)
End Get
Set : End Set
End Property
Public Overrides Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider,
Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object
If ACheck(Of Double)(Value, AModes.Var, MyProvider) Then
Return Value
Else
HasError = True
TypeError = True
Return Nothing
End If
End Function
End Class
#End Region #End Region
#Region "Initializers" #Region "Initializers"
Friend Sub New(ByVal Container As YouTubeMediaContainerBase, Optional ByVal IsSavedObject As Boolean = False) Friend Sub New(ByVal Container As YouTubeMediaContainerBase, Optional ByVal IsSavedObject As Boolean = False)
@@ -37,6 +57,7 @@ Namespace API.YouTube.Controls
MyContainer = Container MyContainer = Container
CNT_PROCESSOR = New TableControlsProcessor(TP_CONTROLS) CNT_PROCESSOR = New TableControlsProcessor(TP_CONTROLS)
Me.IsSavedObject = IsSavedObject Me.IsSavedObject = IsSavedObject
MyFieldsChecker = New FieldsChecker
End Sub End Sub
#End Region #End Region
#Region "Form handlers" #Region "Form handlers"
@@ -132,6 +153,9 @@ Namespace API.YouTube.Controls
End If End If
setDef(CMB_SUBS_FORMAT, __optionValue) setDef(CMB_SUBS_FORMAT, __optionValue)
If MyYouTubeSettings.DefaultVideoFPS > 0 Then TXT_FPS.Text = MyYouTubeSettings.DefaultVideoFPS
MyFieldsChecker.AddControl(Of Double)(TXT_FPS, TXT_FPS.CaptionText, True, New FpsFieldChecker)
MyFieldsChecker.EndLoaderOperations()
TP_SUBS.Enabled = .Subtitles.Count > 0 TP_SUBS.Enabled = .Subtitles.Count > 0
TXT_SUBS_ADDIT.Enabled = .Subtitles.Count > 0 TXT_SUBS_ADDIT.Enabled = .Subtitles.Count > 0
RefillTextBoxes() RefillTextBoxes()
@@ -275,6 +299,7 @@ Namespace API.YouTube.Controls
#Region "OK, Cancel" #Region "OK, Cancel"
Private Sub BTT_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_DOWN.Click Private Sub BTT_DOWN_Click(sender As Object, e As EventArgs) Handles BTT_DOWN.Click
Try Try
If Not MyFieldsChecker.AllParamsOK Then Exit Sub
Dim f As SFile Dim f As SFile
If MyContainer.HasElements Then If MyContainer.HasElements Then
f = TXT_FILE.Text.CSFileP f = TXT_FILE.Text.CSFileP
@@ -284,6 +309,7 @@ Namespace API.YouTube.Controls
If f.IsEmptyString Then Throw New ArgumentNullException("File", "The output file cannot be null") If f.IsEmptyString Then Throw New ArgumentNullException("File", "The output file cannot be null")
With MyContainer With MyContainer
.OutputVideoExtension = CMB_FORMAT.Text.StringToLower .OutputVideoExtension = CMB_FORMAT.Text.StringToLower
.OutputVideoFPS = AConvert(Of Double)(TXT_FPS.Text, YouTubeSettings.FpsFormatProvider.MyProviderDefault, -1)
.OutputAudioCodec = CMB_AUDIO_CODEC.Text.StringToLower .OutputAudioCodec = CMB_AUDIO_CODEC.Text.StringToLower
.OutputSubtitlesFormat = CMB_SUBS_FORMAT.Text.StringToLower .OutputSubtitlesFormat = CMB_SUBS_FORMAT.Text.StringToLower

View File

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

View File

@@ -217,6 +217,16 @@ Namespace API.YouTube.Objects
If HasElements Then Elements.ForEach(Sub(e) e.OutputVideoExtension = _OutputVideoExtension) If HasElements Then Elements.ForEach(Sub(e) e.OutputVideoExtension = _OutputVideoExtension)
End Set End Set
End Property End Property
<XMLEC("OutputVideoFPS")> Protected _OutputVideoFPS As Double = -1
Friend Property OutputVideoFPS As Double
Get
Return _OutputVideoFPS
End Get
Set(ByVal fps As Double)
_OutputVideoFPS = fps
If HasElements Then Elements.ForEach(Sub(elem) DirectCast(elem, YouTubeMediaContainerBase).OutputVideoFPS = fps)
End Set
End Property
#End Region #End Region
#Region "Audio" #Region "Audio"
<XMLEC> Friend Property SelectedAudioIndex As Integer = -1 Implements IYouTubeMediaContainer.SelectedAudioIndex <XMLEC> Friend Property SelectedAudioIndex As Integer = -1 Implements IYouTubeMediaContainer.SelectedAudioIndex
@@ -1026,6 +1036,16 @@ Namespace API.YouTube.Objects
If fAacAudio.Exists And Not aacRequested Then fAacAudio.Delete() If fAacAudio.Exists And Not aacRequested Then fAacAudio.Delete()
If fAc3Audio.Exists And Not ac3Requested And SelectedVideoIndex >= 0 Then fAc3Audio.Delete() If fAc3Audio.Exists And Not ac3Requested And SelectedVideoIndex >= 0 Then fAc3Audio.Delete()
End If End If
If SelectedVideoIndex >= 0 AndAlso OutputVideoFPS > 0 AndAlso SelectedVideo.Bitrate > OutputVideoFPS Then
f = File
f.Name &= "tmp00"
.Execute($"ffmpeg -i ""{File}"" -filter:v fps={OutputVideoFPS.ToString.Replace(",", ".")} -c:a copy ""{f}""")
If f.Exists Then
File.Delete()
SFile.Rename(f, File,, EDP.LogMessageValue)
End If
End If
End If End If
End If End If
End With End With

View File

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

View File

@@ -15,6 +15,9 @@ Namespace API.Instagram
Friend Const InstagramSite As String = "Instagram" Friend Const InstagramSite As String = "Instagram"
Friend Const InstagramSiteKey As String = "AndyProgram_Instagram" Friend Const InstagramSiteKey As String = "AndyProgram_Instagram"
Friend ReadOnly FilesPattern As RParams = RParams.DMS(".+?([^/\?]+?\.[\w\d]{3,4})(?=(\?|\Z))", 1, EDP.ReturnValue) Friend ReadOnly FilesPattern As RParams = RParams.DMS(".+?([^/\?]+?\.[\w\d]{3,4})(?=(\?|\Z))", 1, EDP.ReturnValue)
Friend ReadOnly ObtainMedia_SizeFuncPic_RegexP As RParams = RParams.DMS("_p(\d+)x(\d+)", 1, EDP.ReturnValue)
Friend ReadOnly ObtainMedia_SizeFuncPic_RegexS As RParams = RParams.DMS("_s(\d+)x(\d+)", 1, EDP.ReturnValue)
Friend Const PageTokenRegexPatternDefault As String = "\[\],{""token"":""(.*?)""},\d+\]"
Friend Sub UpdateResponser(ByVal Source As IResponse, ByRef Destination As Responser) Friend Sub UpdateResponser(ByVal Source As IResponse, ByRef Destination As Responser)
Const r_wwwClaimName$ = "x-ig-set-www-claim" Const r_wwwClaimName$ = "x-ig-set-www-claim"
Const r_tokenName$ = SiteSettings.Header_CSRF_TOKEN_COOKIE Const r_tokenName$ = SiteSettings.Header_CSRF_TOKEN_COOKIE

View File

@@ -11,6 +11,8 @@ Namespace API.Instagram
Friend Class EditorExchangeOptions Friend Class EditorExchangeOptions
<PSetting(Caption:="Get timeline", ToolTip:="Download user timeline")> <PSetting(Caption:="Get timeline", ToolTip:="Download user timeline")>
Friend Property GetTimeline As Boolean Friend Property GetTimeline As Boolean
<PSetting(Caption:="Get reels", ToolTip:="Download user reels")>
Friend Property GetReels As Boolean
<PSetting(Caption:="Get stories", ToolTip:="Download user stories (pinned)")> <PSetting(Caption:="Get stories", ToolTip:="Download user stories (pinned)")>
Friend Property GetStories As Boolean Friend Property GetStories As Boolean
<PSetting(Caption:="Get stories: user", ToolTip:="Download user stories")> <PSetting(Caption:="Get stories: user", ToolTip:="Download user stories")>
@@ -20,6 +22,7 @@ Namespace API.Instagram
Friend Sub New(ByVal u As UserData) Friend Sub New(ByVal u As UserData)
With u With u
GetTimeline = .GetTimeline GetTimeline = .GetTimeline
GetReels = .GetReels
GetStories = .GetStories GetStories = .GetStories
GetStoriesUser = .GetStoriesUser GetStoriesUser = .GetStoriesUser
GetTagged = .GetTaggedData GetTagged = .GetTaggedData
@@ -28,6 +31,7 @@ Namespace API.Instagram
Friend Sub New(ByVal s As SiteSettings) Friend Sub New(ByVal s As SiteSettings)
With s With s
GetTimeline = CBool(.GetTimeline.Value) GetTimeline = CBool(.GetTimeline.Value)
GetReels = CBool(.GetReels.Value)
GetStories = CBool(.GetStories.Value) GetStories = CBool(.GetStories.Value)
GetStoriesUser = CBool(.GetStoriesUser.Value) GetStoriesUser = CBool(.GetStoriesUser.Value)
GetTagged = CBool(.GetTagged.Value) GetTagged = CBool(.GetTagged.Value)

View File

@@ -121,11 +121,13 @@ Namespace API.Instagram
Private ReadOnly Property SleepTimerOnPostsLimitProvider As IFormatProvider Private ReadOnly Property SleepTimerOnPostsLimitProvider As IFormatProvider
<PropertyOption(ControlText:="Get timeline", ControlToolTip:="Default value for new users"), PXML, ControlNumber(23), PClonable> <PropertyOption(ControlText:="Get timeline", ControlToolTip:="Default value for new users"), PXML, ControlNumber(23), PClonable>
Friend ReadOnly Property GetTimeline As PropertyValue Friend ReadOnly Property GetTimeline As PropertyValue
<PropertyOption(ControlText:="Get stories", ControlToolTip:="Default value for new users"), PXML, ControlNumber(24), PClonable> <PropertyOption(ControlText:="Get reels", ControlToolTip:="Default value for new users"), PXML, ControlNumber(24), PClonable>
Friend ReadOnly Property GetReels As PropertyValue
<PropertyOption(ControlText:="Get stories", ControlToolTip:="Default value for new users"), PXML, ControlNumber(25), PClonable>
Friend ReadOnly Property GetStories As PropertyValue Friend ReadOnly Property GetStories As PropertyValue
<PropertyOption(ControlText:="Get stories: user", ControlToolTip:="Default value for new users"), PXML, ControlNumber(25), PClonable> <PropertyOption(ControlText:="Get stories: user", ControlToolTip:="Default value for new users"), PXML, ControlNumber(26), PClonable>
Friend ReadOnly Property GetStoriesUser As PropertyValue Friend ReadOnly Property GetStoriesUser As PropertyValue
<PropertyOption(ControlText:="Get tagged photos", ControlToolTip:="Default value for new users"), PXML, ControlNumber(26), PClonable> <PropertyOption(ControlText:="Get tagged photos", ControlToolTip:="Default value for new users"), PXML, ControlNumber(27), PClonable>
Friend ReadOnly Property GetTagged As PropertyValue Friend ReadOnly Property GetTagged As PropertyValue
<PropertyOption(ControlText:="Tagged notify limit", <PropertyOption(ControlText:="Tagged notify limit",
ControlToolTip:="If the number of tagged posts exceeds this number you will be notified." & vbCr & ControlToolTip:="If the number of tagged posts exceeds this number you will be notified." & vbCr &
@@ -137,11 +139,13 @@ Namespace API.Instagram
#Region "Download ready" #Region "Download ready"
<PropertyOption(ControlText:="Download timeline", ControlToolTip:="Download timeline"), PXML, ControlNumber(10), PClonable> <PropertyOption(ControlText:="Download timeline", ControlToolTip:="Download timeline"), PXML, ControlNumber(10), PClonable>
Friend ReadOnly Property DownloadTimeline As PropertyValue Friend ReadOnly Property DownloadTimeline As PropertyValue
<PropertyOption(ControlText:="Download stories", ControlToolTip:="Download stories"), PXML, ControlNumber(11), PClonable> <PropertyOption(ControlText:="Download reels", ControlToolTip:="Download reels"), PXML, ControlNumber(11), PClonable>
Friend ReadOnly Property DownloadReels As PropertyValue
<PropertyOption(ControlText:="Download stories", ControlToolTip:="Download stories"), PXML, ControlNumber(12), PClonable>
Friend ReadOnly Property DownloadStories As PropertyValue Friend ReadOnly Property DownloadStories As PropertyValue
<PropertyOption(ControlText:="Download stories: user", ControlToolTip:="Download stories (user)"), PXML, ControlNumber(12), PClonable> <PropertyOption(ControlText:="Download stories: user", ControlToolTip:="Download stories (user)"), PXML, ControlNumber(13), PClonable>
Friend ReadOnly Property DownloadStoriesUser As PropertyValue Friend ReadOnly Property DownloadStoriesUser As PropertyValue
<PropertyOption(ControlText:="Download tagged", ControlToolTip:="Download tagged posts"), PXML, ControlNumber(13), PClonable> <PropertyOption(ControlText:="Download tagged", ControlToolTip:="Download tagged posts"), PXML, ControlNumber(14), PClonable>
Friend ReadOnly Property DownloadTagged As PropertyValue Friend ReadOnly Property DownloadTagged As PropertyValue
#End Region #End Region
#Region "429 bypass" #Region "429 bypass"
@@ -244,6 +248,7 @@ Namespace API.Instagram
HH_USER_AGENT = New PropertyValue(useragent, GetType(String), Sub(v) ChangeResponserFields(NameOf(HH_USER_AGENT), v)) HH_USER_AGENT = New PropertyValue(useragent, GetType(String), Sub(v) ChangeResponserFields(NameOf(HH_USER_AGENT), v))
DownloadTimeline = New PropertyValue(True) DownloadTimeline = New PropertyValue(True)
DownloadReels = New PropertyValue(True)
DownloadStories = New PropertyValue(True) DownloadStories = New PropertyValue(True)
DownloadStoriesUser = New PropertyValue(True) DownloadStoriesUser = New PropertyValue(True)
DownloadTagged = New PropertyValue(True) DownloadTagged = New PropertyValue(True)
@@ -256,6 +261,7 @@ Namespace API.Instagram
SleepTimerOnPostsLimitProvider = New TimersChecker(10000) SleepTimerOnPostsLimitProvider = New TimersChecker(10000)
GetTimeline = New PropertyValue(True) GetTimeline = New PropertyValue(True)
GetReels = New PropertyValue(False)
GetStories = New PropertyValue(False) GetStories = New PropertyValue(False)
GetStoriesUser = New PropertyValue(False) GetStoriesUser = New PropertyValue(False)
GetTagged = New PropertyValue(False) GetTagged = New PropertyValue(False)

View File

@@ -15,6 +15,7 @@ Imports PersonalUtilities.Functions.XML.Base
Imports PersonalUtilities.Functions.Messaging Imports PersonalUtilities.Functions.Messaging
Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Functions.RegularExpressions
Imports PersonalUtilities.Tools.Web.Clients Imports PersonalUtilities.Tools.Web.Clients
Imports PersonalUtilities.Tools.Web.Clients.Base
Imports PersonalUtilities.Tools.Web.Documents.JSON Imports PersonalUtilities.Tools.Web.Documents.JSON
Imports UTypes = SCrawler.API.Base.UserMedia.Types Imports UTypes = SCrawler.API.Base.UserMedia.Types
Imports UStates = SCrawler.API.Base.UserMedia.States Imports UStates = SCrawler.API.Base.UserMedia.States
@@ -24,6 +25,7 @@ Namespace API.Instagram
Private Const Name_LastCursor As String = "LastCursor" Private Const Name_LastCursor As String = "LastCursor"
Private Const Name_FirstLoadingDone As String = "FirstLoadingDone" Private Const Name_FirstLoadingDone As String = "FirstLoadingDone"
Private Const Name_GetTimeline As String = "GetTimeline" Private Const Name_GetTimeline As String = "GetTimeline"
Private Const Name_GetReels As String = "GetReels"
Private Const Name_GetStories As String = "GetStories" Private Const Name_GetStories As String = "GetStories"
Private Const Name_GetStoriesUser As String = "GetStoriesUser" Private Const Name_GetStoriesUser As String = "GetStoriesUser"
Private Const Name_GetTagged As String = "GetTaggedData" Private Const Name_GetTagged As String = "GetTaggedData"
@@ -66,6 +68,7 @@ Namespace API.Instagram
Return New EContainer("Post", ID, {New EAttribute(Name_Section, CInt(Section)), New EAttribute(Name_Code, Code)}) Return New EContainer("Post", ID, {New EAttribute(Name_Section, CInt(Section)), New EAttribute(Name_Code, Code)})
End Function End Function
End Structure End Structure
Friend Const Header_FB_LSD As String = "x-fb-lsd"
Private ReadOnly Property MySiteSettings As SiteSettings Private ReadOnly Property MySiteSettings As SiteSettings
Get Get
Return DirectCast(HOST.Source, SiteSettings) Return DirectCast(HOST.Source, SiteSettings)
@@ -76,6 +79,7 @@ Namespace API.Instagram
Private LastCursor As String = String.Empty Private LastCursor As String = String.Empty
Private FirstLoadingDone As Boolean = False Private FirstLoadingDone As Boolean = False
Friend Property GetTimeline As Boolean = True Friend Property GetTimeline As Boolean = True
Friend Property GetReels As Boolean = False
Friend Property GetStories As Boolean Friend Property GetStories As Boolean
Friend Property GetStoriesUser As Boolean Friend Property GetStoriesUser As Boolean
Friend Property GetTaggedData As Boolean Friend Property GetTaggedData As Boolean
@@ -94,6 +98,7 @@ Namespace API.Instagram
LastCursor = .Value(Name_LastCursor) LastCursor = .Value(Name_LastCursor)
FirstLoadingDone = .Value(Name_FirstLoadingDone).FromXML(Of Boolean)(False) FirstLoadingDone = .Value(Name_FirstLoadingDone).FromXML(Of Boolean)(False)
GetTimeline = .Value(Name_GetTimeline).FromXML(Of Boolean)(CBool(MySiteSettings.GetTimeline.Value)) GetTimeline = .Value(Name_GetTimeline).FromXML(Of Boolean)(CBool(MySiteSettings.GetTimeline.Value))
GetReels = .Value(Name_GetReels).FromXML(Of Boolean)(MySiteSettings.GetReels.Value)
GetStories = .Value(Name_GetStories).FromXML(Of Boolean)(CBool(MySiteSettings.GetStories.Value)) GetStories = .Value(Name_GetStories).FromXML(Of Boolean)(CBool(MySiteSettings.GetStories.Value))
GetStoriesUser = .Value(Name_GetStoriesUser).FromXML(Of Boolean)(MySiteSettings.GetStoriesUser.Value) GetStoriesUser = .Value(Name_GetStoriesUser).FromXML(Of Boolean)(MySiteSettings.GetStoriesUser.Value)
GetTaggedData = .Value(Name_GetTagged).FromXML(Of Boolean)(CBool(MySiteSettings.GetTagged.Value)) GetTaggedData = .Value(Name_GetTagged).FromXML(Of Boolean)(CBool(MySiteSettings.GetTagged.Value))
@@ -103,6 +108,7 @@ Namespace API.Instagram
.Add(Name_LastCursor, LastCursor) .Add(Name_LastCursor, LastCursor)
.Add(Name_FirstLoadingDone, FirstLoadingDone.BoolToInteger) .Add(Name_FirstLoadingDone, FirstLoadingDone.BoolToInteger)
.Add(Name_GetTimeline, GetTimeline.BoolToInteger) .Add(Name_GetTimeline, GetTimeline.BoolToInteger)
.Add(Name_GetReels, GetReels.BoolToInteger)
.Add(Name_GetStories, GetStories.BoolToInteger) .Add(Name_GetStories, GetStories.BoolToInteger)
.Add(Name_GetStoriesUser, GetStoriesUser.BoolToInteger) .Add(Name_GetStoriesUser, GetStoriesUser.BoolToInteger)
.Add(Name_GetTagged, GetTaggedData.BoolToInteger) .Add(Name_GetTagged, GetTaggedData.BoolToInteger)
@@ -120,6 +126,7 @@ Namespace API.Instagram
If Not Obj Is Nothing AndAlso TypeOf Obj Is EditorExchangeOptions Then If Not Obj Is Nothing AndAlso TypeOf Obj Is EditorExchangeOptions Then
With DirectCast(Obj, EditorExchangeOptions) With DirectCast(Obj, EditorExchangeOptions)
GetTimeline = .GetTimeline GetTimeline = .GetTimeline
GetReels = .GetReels
GetStories = .GetStories GetStories = .GetStories
GetStoriesUser = .GetStoriesUser GetStoriesUser = .GetStoriesUser
GetTaggedData = .GetTagged GetTaggedData = .GetTagged
@@ -253,6 +260,14 @@ Namespace API.Instagram
End If End If
If FirstLoadingDone Then LastCursor = String.Empty If FirstLoadingDone Then LastCursor = String.Empty
If Not IsSavedPosts AndAlso MySiteSettings.BaseAuthExists() Then If Not IsSavedPosts AndAlso MySiteSettings.BaseAuthExists() Then
If CBool(MySiteSettings.DownloadReels.Value) And GetReels Then
s = Sections.Reels
DefaultParser_ElemNode = {"node", "media"}
DownloadData(String.Empty, s, Token)
DefaultParser_ElemNode = Nothing
DownloadReels_SetEnvir = False
ProgressPre.Done()
End If
If CBool(MySiteSettings.DownloadStories.Value) And GetStories Then s = Sections.Stories : DownloadData(String.Empty, s, Token) : ProgressPre.Done() If CBool(MySiteSettings.DownloadStories.Value) And GetStories Then s = Sections.Stories : DownloadData(String.Empty, s, Token) : ProgressPre.Done()
If CBool(MySiteSettings.DownloadStoriesUser.Value) And GetStoriesUser Then s = Sections.UserStories : DownloadData(String.Empty, s, Token) : ProgressPre.Done() If CBool(MySiteSettings.DownloadStoriesUser.Value) And GetStoriesUser Then s = Sections.UserStories : DownloadData(String.Empty, s, Token) : ProgressPre.Done()
If CBool(MySiteSettings.DownloadTagged.Value) And GetTaggedData Then If CBool(MySiteSettings.DownloadTagged.Value) And GetTaggedData Then
@@ -268,6 +283,8 @@ Namespace API.Instagram
errorFound = True errorFound = True
Throw ex Throw ex
Finally Finally
DefaultParser_ElemNode = Nothing
DownloadReels_SetEnvir = False
E560Thrown = False E560Thrown = False
UpdateResponser() UpdateResponser()
ValidateExtension() ValidateExtension()
@@ -301,7 +318,7 @@ Namespace API.Instagram
Protected Overridable Sub Responser_ResponseReceived(ByVal Sender As Object, ByVal e As EventArguments.WebDataResponse) Protected Overridable Sub Responser_ResponseReceived(ByVal Sender As Object, ByVal e As EventArguments.WebDataResponse)
Declarations.UpdateResponser(e, Responser) Declarations.UpdateResponser(e, Responser)
End Sub End Sub
Protected Enum Sections : Timeline : Tagged : Stories : UserStories : SavedPosts : End Enum Protected Enum Sections : Timeline : Reels : Tagged : Stories : UserStories : SavedPosts : End Enum
Protected Const StoriesFolder As String = "Stories" Protected Const StoriesFolder As String = "Stories"
Private Const TaggedFolder As String = "Tagged" Private Const TaggedFolder As String = "Tagged"
#Region "429 bypass" #Region "429 bypass"
@@ -441,6 +458,7 @@ Namespace API.Instagram
ReconfigureAwaiter() ReconfigureAwaiter()
Try Try
Dim r$ = String.Empty
Dim n As EContainer, nn As EContainer Dim n As EContainer, nn As EContainer
Dim HasNextPage As Boolean = False Dim HasNextPage As Boolean = False
Dim EndCursor$ = String.Empty Dim EndCursor$ = String.Empty
@@ -461,6 +479,9 @@ Namespace API.Instagram
URL = $"https://www.instagram.com/api/v1/feed/user/{NameTrue}/username/?count=50" & URL = $"https://www.instagram.com/api/v1/feed/user/{NameTrue}/username/?count=50" &
If(Cursor.IsEmptyString, String.Empty, $"&max_id={Cursor}") If(Cursor.IsEmptyString, String.Empty, $"&max_id={Cursor}")
ENode = Nothing ENode = Nothing
Case Sections.Reels
r = DownloadReels(Cursor, Token)
ENode = {"data", "xdt_api__v1__clips__user__connection_v2"}
Case Sections.SavedPosts Case Sections.SavedPosts
SavedPostsDownload(String.Empty, Token) SavedPostsDownload(String.Empty, Token)
Exit Sub Exit Sub
@@ -496,7 +517,7 @@ Namespace API.Instagram
End Select End Select
'Get response 'Get response
Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException) If Not Section = Sections.Reels Then r = Responser.GetResponse(URL,, EDP.ThrowException)
MySiteSettings.TooManyRequests(False) MySiteSettings.TooManyRequests(False)
RequestsCount += 1 RequestsCount += 1
ThrowAny(Token) ThrowAny(Token)
@@ -518,6 +539,20 @@ Namespace API.Instagram
HasNextPage = False HasNextPage = False
End If End If
End With End With
Case Sections.Reels
With n
If .Contains("page_info") Then
With .Item("page_info")
HasNextPage = .Value("has_next_page").FromXML(Of Boolean)(False)
EndCursor = .Value("end_cursor")
End With
Else
HasNextPage = False
End If
If If(.Item("edges")?.Count, 0) > 0 Then
If Not DefaultParser(.Item("edges"), Section, Token, "Reels*") Then Throw New ExitException
End If
End With
Case Sections.Tagged Case Sections.Tagged
With n With n
If .Contains("page_info") Then If .Contains("page_info") Then
@@ -577,7 +612,7 @@ Namespace API.Instagram
End Try End Try
Loop Loop
Catch eex2 As ExitException Catch eex2 As ExitException
If (Section = Sections.Timeline Or Section = Sections.Tagged) And Not Cursor.IsEmptyString Then Throw eex2 If Not Section = Sections.Reels And (Section = Sections.Timeline Or Section = Sections.Tagged) And Not Cursor.IsEmptyString Then Throw eex2
Catch oex2 As OperationCanceledException When Token.IsCancellationRequested Or oex2.HelpLink = InstAborted Catch oex2 As OperationCanceledException When Token.IsCancellationRequested Or oex2.HelpLink = InstAborted
If oex2.HelpLink = InstAborted Then HasError = True If oex2.HelpLink = InstAborted Then HasError = True
Catch DoEx As Exception Catch DoEx As Exception
@@ -668,6 +703,7 @@ Namespace API.Instagram
End Sub End Sub
Protected DefaultParser_ElemNode() As Object = Nothing Protected DefaultParser_ElemNode() As Object = Nothing
Protected DefaultParser_IgnorePass As Boolean = False Protected DefaultParser_IgnorePass As Boolean = False
Private ReadOnly DefaultParser_PostUrlCreator_Default As Func(Of PostKV, String) = Function(post) $"https://www.instagram.com/p/{post.Code}/"
Protected DefaultParser_PostUrlCreator As Func(Of PostKV, String) = Function(post) $"https://www.instagram.com/p/{post.Code}/" Protected DefaultParser_PostUrlCreator As Func(Of PostKV, String) = Function(post) $"https://www.instagram.com/p/{post.Code}/"
Protected Function DefaultParser(ByVal Items As IEnumerable(Of EContainer), ByVal Section As Sections, ByVal Token As CancellationToken, Protected Function DefaultParser(ByVal Items As IEnumerable(Of EContainer), ByVal Section As Sections, ByVal Token As CancellationToken,
Optional ByVal SpecFolder As String = Nothing, Optional ByVal State As UStates = UStates.Unknown, Optional ByVal SpecFolder As String = Nothing, Optional ByVal State As UStates = UStates.Unknown,
@@ -717,6 +753,106 @@ Namespace API.Instagram
End If End If
End Function End Function
#End Region #End Region
#Region "Get reels"
Private _GetReels_LSD As String = String.Empty
Private _GetReels_dtsg As String = String.Empty
Private ReadOnly Property DownloadReels_Tokens_Valid As Boolean
Get
Return Not _GetReels_LSD.IsEmptyString And Not _GetReels_dtsg.IsEmptyString
End Get
End Property
Private WriteOnly Property DownloadReels_SetEnvir As Boolean
Set(ByVal init As Boolean)
If init Then
ObtainMedia_SetReelsFunc()
DefaultParser_PostUrlCreator = Function(post) $"{MySiteSettings.GetUserUrl(Me).TrimEnd("/")}/reel/{post.Code}"
Else
ObtainMedia_SizeFuncPic = Nothing
ObtainMedia_SizeFuncVid = Nothing
DefaultParser_PostUrlCreator = DefaultParser_PostUrlCreator_Default
End If
End Set
End Property
Private Class Responser2 : Inherits Responser
Friend Sub New(ByVal Source As Responser)
MyBase.New
Copy(Source)
ErrorProcessor = New ResponserErrorProcessor(Source)
End Sub
End Class
''' <returns>Response</returns>
Private Function DownloadReels(ByVal Cursor As String, ByVal Token As CancellationToken) As String
Const requestPattern$ = "https://www.instagram.com/api/graphql?fb_dtsg={0}&fb_api_req_friendly_name=PolarisProfileReelsTabContentQuery&lsd={1}&doc_id=7191572580905225&variables={2}"
DownloadReels_SetEnvir = True
If Cursor.IsEmptyString And Not DownloadReels_Tokens_Valid Then GetPageTokens()
If Cursor.IsEmptyString And Not DownloadReels_Tokens_Valid Then Throw New ExitException
Using resp As New Responser2(Responser)
Try
resp.Method = "POST"
AddHandler resp.ResponseReceived, AddressOf Responser_ResponseReceived
resp.Headers.Add(Header_FB_LSD, _GetReels_LSD)
Dim vars$ = """data"":{""include_feed_video"":true,""page_size"":50,""target_user_id"":""" & ID & """}"
If Not Cursor.IsEmptyString Then vars = $"""after"":""{Cursor}"",""before"":null,{vars},""first"":4,""last"":null"
vars = "{" & vars & "}"
Dim url$ = String.Format(requestPattern, _GetReels_dtsg, _GetReels_LSD, SymbolsConverter.ASCII.EncodeSymbolsOnly(vars))
Return resp.GetResponse(url,, EDP.ThrowException)
Finally
With resp
Responser.Cookies.Update(.Cookies)
With .Headers
If .Contains(SiteSettings.Header_IG_WWW_CLAIM) Then Responser.Headers.Add(SiteSettings.Header_IG_WWW_CLAIM, .Value(SiteSettings.Header_IG_WWW_CLAIM))
If .Contains(SiteSettings.Header_CSRF_TOKEN) Then Responser.Headers.Add(SiteSettings.Header_CSRF_TOKEN, .Value(SiteSettings.Header_CSRF_TOKEN))
End With
End With
End Try
End Using
End Function
Private Function GetPageTokens() As Boolean
_GetReels_LSD = String.Empty
_GetReels_dtsg = String.Empty
Try
Dim r$ = Responser.GetResponse(MySiteSettings.GetUserUrl(Me),, EDP.ThrowException)
If Not r.IsEmptyString Then
Dim rr As RParams = RParams.DM(PageTokenRegexPatternDefault, 0, RegexReturn.List, EDP.ReturnValue)
Dim tokens As List(Of String) = RegexReplace(r, rr)
Dim tt$, ttVal$
If tokens.ListExists Then
With rr
.Match = Nothing
.MatchSub = 1
.WhatGet = RegexReturn.Value
End With
For Each tt In tokens
If Not _GetReels_LSD.IsEmptyString And Not _GetReels_dtsg.IsEmptyString Then
Exit For
Else
ttVal = RegexReplace(tt, rr)
If Not ttVal.IsEmptyString Then
If ttVal.Contains(":") Then
If _GetReels_dtsg.IsEmptyString Then _GetReels_dtsg = ttVal
Else
If _GetReels_LSD.IsEmptyString Then _GetReels_LSD = ttVal
End If
End If
End If
Next
End If
End If
Catch ex As Exception
Dim notFound$ = String.Empty
If _GetReels_dtsg.IsEmptyString Then notFound.StringAppend(Header_FB_LSD)
If _GetReels_LSD.IsEmptyString Then notFound.StringAppend("lsd")
LogError(ex, $"failed to update some{IIf(notFound.IsEmptyString, String.Empty, $" ({notFound})")} credentials", EDP.SendToLog)
End Try
Return DownloadReels_Tokens_Valid
End Function
#End Region
#Region "Code ID converters" #Region "Code ID converters"
Protected Function CodeToID(ByVal Code As String) As String Protected Function CodeToID(ByVal Code As String) As String
Const CodeSymbols$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" Const CodeSymbols$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
@@ -741,6 +877,23 @@ Namespace API.Instagram
Protected ObtainMedia_SizeFuncVid As Func(Of EContainer, Sizes) = Nothing Protected ObtainMedia_SizeFuncVid As Func(Of EContainer, Sizes) = Nothing
Protected ObtainMedia_SizeFuncPic As Func(Of EContainer, Sizes) = Nothing Protected ObtainMedia_SizeFuncPic As Func(Of EContainer, Sizes) = Nothing
Protected ObtainMedia_AllowAbstract As Boolean = False Protected ObtainMedia_AllowAbstract As Boolean = False
Protected Sub ObtainMedia_SetReelsFunc()
ObtainMedia_SizeFuncPic = Function(ByVal ss As EContainer) As Sizes
If ss.Value("url").IsEmptyString Then
Return New Sizes("----", "")
ElseIf Not ss.Value("width").IsEmptyString Or Not ss.Value("width").IsEmptyString Then
Return New Sizes(CInt(AConvert(Of Integer)(ss.Value("width"), 0)) +
CInt(AConvert(Of Integer)(ss.Value("height"), 0)), ss.Value("url"))
Else
Dim rval$ = RegexReplace(ss.Value("url"), ObtainMedia_SizeFuncPic_RegexP)
If Not rval.IsEmptyString Then Return New Sizes(rval, ss.Value("url"))
rval = RegexReplace(ss.Value("url"), ObtainMedia_SizeFuncPic_RegexS)
If Not rval.IsEmptyString Then Return New Sizes(AConvert(Of Integer)(rval, 1) * -1, ss.Value("url"))
Return New Sizes(10000, ss.Value("url"))
End If
End Function
ObtainMedia_SizeFuncVid = Function(ss) If(ss.Value("url").IsEmptyString, New Sizes("----", ""), New Sizes(10000, ss.Value("url")))
End Sub
Protected Sub ObtainMedia(ByVal n As EContainer, ByVal PostID As String, Optional ByVal SpecialFolder As String = Nothing, Protected Sub ObtainMedia(ByVal n As EContainer, ByVal PostID As String, Optional ByVal SpecialFolder As String = Nothing,
Optional ByVal DateObj As String = Nothing, Optional ByVal InitialType As Integer = -1, Optional ByVal DateObj As String = Nothing, Optional ByVal InitialType As Integer = -1,
Optional ByVal PostOriginUrl As String = Nothing, Optional ByVal PostOriginUrl As String = Nothing,
@@ -749,6 +902,7 @@ Namespace API.Instagram
Dim maxSize As Func(Of EContainer, Integer) = Function(ByVal _ss As EContainer) As Integer Dim maxSize As Func(Of EContainer, Integer) = Function(ByVal _ss As EContainer) As Integer
Dim w% = AConvert(Of Integer)(_ss.Value("width"), 0) Dim w% = AConvert(Of Integer)(_ss.Value("width"), 0)
Dim h% = AConvert(Of Integer)(_ss.Value("height"), 0) Dim h% = AConvert(Of Integer)(_ss.Value("height"), 0)
'Return w + h
Return Math.Max(w, h) Return Math.Max(w, h)
End Function End Function
Dim wrongData As Predicate(Of Sizes) = Function(_ss) _ss.HasError Or _ss.Data.IsEmptyString Dim wrongData As Predicate(Of Sizes) = Function(_ss) _ss.HasError Or _ss.Data.IsEmptyString
@@ -1050,11 +1204,12 @@ Namespace API.Instagram
Dim s As Sections = DirectCast(Section, Sections) Dim s As Sections = DirectCast(Section, Sections)
Select Case s Select Case s
Case Sections.Timeline : MySiteSettings.DownloadTimeline.Value = False Case Sections.Timeline : MySiteSettings.DownloadTimeline.Value = False
Case Sections.Reels : MySiteSettings.DownloadReels.Value = False
Case Sections.Tagged : MySiteSettings.DownloadTagged.Value = False
Case Sections.Stories, Sections.UserStories Case Sections.Stories, Sections.UserStories
MySiteSettings.DownloadTimeline.Value = False MySiteSettings.DownloadTimeline.Value = False
MySiteSettings.DownloadStories.Value = False MySiteSettings.DownloadStories.Value = False
MySiteSettings.DownloadStoriesUser.Value = False MySiteSettings.DownloadStoriesUser.Value = False
Case Else : MySiteSettings.DownloadTagged.Value = False
End Select End Select
MyMainLOG = $"[{s}] downloading is disabled until you update your credentials".ToUpper MyMainLOG = $"[{s}] downloading is disabled until you update your credentials".ToUpper
End If End If

View File

@@ -106,9 +106,12 @@ Namespace API.LPSG
End Sub End Sub
Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False, Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False,
Optional ByVal EObj As Object = Nothing) As Integer Optional ByVal EObj As Object = Nothing) As Integer
If Responser.StatusCode = Net.HttpStatusCode.ServiceUnavailable Then If Responser.StatusCode = Net.HttpStatusCode.ServiceUnavailable Then '503
MyMainLOG = $"{ToStringForLog()}: LPSG not available" MyMainLOG = $"{ToStringForLog()}: LPSG not available"
Return 1 Return 1
ElseIf Responser.StatusCode = Net.HttpStatusCode.NotFound Then '404
UserExists = False
Return 1
Else Else
Return 0 Return 0
End If End If

View File

@@ -18,14 +18,11 @@ Imports IGS = SCrawler.API.Instagram.SiteSettings
Namespace API.ThreadsNet Namespace API.ThreadsNet
Friend Class UserData : Inherits Instagram.UserData Friend Class UserData : Inherits Instagram.UserData
#Region "Declarations" #Region "Declarations"
Friend Const Header_FB_LSD As String = "x-fb-lsd"
Private ReadOnly Property MySettings As SiteSettings Private ReadOnly Property MySettings As SiteSettings
Get Get
Return HOST.Source Return HOST.Source
End Get End Get
End Property End Property
Private ReadOnly ObtainMedia_SizeFuncPic_RegexP As RParams = RParams.DMS("_p(\d+)x(\d+)", 1, EDP.ReturnValue)
Private ReadOnly ObtainMedia_SizeFuncPic_RegexS As RParams = RParams.DMS("_s(\d+)x(\d+)", 1, EDP.ReturnValue)
Private ReadOnly DefaultParser_ElemNode_Default() As Object = {"node", "thread_items", 0, "post"} Private ReadOnly DefaultParser_ElemNode_Default() As Object = {"node", "thread_items", 0, "post"}
Private OPT_LSD As String = String.Empty Private OPT_LSD As String = String.Empty
Private OPT_FB_DTSG As String = String.Empty Private OPT_FB_DTSG As String = String.Empty
@@ -48,20 +45,7 @@ Namespace API.ThreadsNet
#End Region #End Region
#Region "Initializer" #Region "Initializer"
Friend Sub New() Friend Sub New()
ObtainMedia_SizeFuncPic = Function(ByVal ss As EContainer) As Sizes ObtainMedia_SetReelsFunc()
If ss.Value("url").IsEmptyString Then
Return New Sizes("----", "")
ElseIf Not ss.Value("width").IsEmptyString Then
Return New Sizes(ss.Value("height").IfNullOrEmpty(ss.Value("width")), ss.Value("url"))
Else
Dim rval$ = RegexReplace(ss.Value("url"), ObtainMedia_SizeFuncPic_RegexP)
If Not rval.IsEmptyString Then Return New Sizes(rval, ss.Value("url"))
rval = RegexReplace(ss.Value("url"), ObtainMedia_SizeFuncPic_RegexS)
If Not rval.IsEmptyString Then Return New Sizes(AConvert(Of Integer)(rval, 1) * -1, ss.Value("url"))
Return New Sizes(10000, ss.Value("url"))
End If
End Function
ObtainMedia_SizeFuncVid = Function(ss) If(ss.Value("url").IsEmptyString, New Sizes("----", ""), New Sizes(10000, ss.Value("url")))
ObtainMedia_AllowAbstract = True ObtainMedia_AllowAbstract = True
DefaultParser_ElemNode = DefaultParser_ElemNode_Default DefaultParser_ElemNode = DefaultParser_ElemNode_Default
DefaultParser_PostUrlCreator = Function(post) $"https://www.threads.net/@{NameTrue}/post/{post.Code}" DefaultParser_PostUrlCreator = Function(post) $"https://www.threads.net/@{NameTrue}/post/{post.Code}"
@@ -174,7 +158,7 @@ Namespace API.ThreadsNet
Dim rr As RParams Dim rr As RParams
Dim tt$, ttVal$ Dim tt$, ttVal$
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
rr = RParams.DM("\[\],{""token"":""(.*?)""},\d+\]", 0, RegexReturn.List, EDP.ReturnValue) rr = RParams.DM(Instagram.PageTokenRegexPatternDefault, 0, RegexReturn.List, EDP.ReturnValue)
Dim tokens As List(Of String) = RegexReplace(r, rr) Dim tokens As List(Of String) = RegexReplace(r, rr)
If tokens.ListExists Then If tokens.ListExists Then
With rr With rr

View File

@@ -22,6 +22,10 @@ Namespace API.TikTok
Friend ReadOnly Property TitleUseNativeSTD As PropertyValue Friend ReadOnly Property TitleUseNativeSTD As PropertyValue
<PropertyOption(ControlText:="Add video ID to video title"), PXML, PClonable> <PropertyOption(ControlText:="Add video ID to video title"), PXML, PClonable>
Friend ReadOnly Property TitleAddVideoID As PropertyValue Friend ReadOnly Property TitleAddVideoID As PropertyValue
<PropertyOption(ControlText:="Use regex to clean video title"), PXML, PClonable>
Friend ReadOnly Property TitleUseRegexForTitle As PropertyValue
<PropertyOption(ControlText:="Title regex", ControlToolTip:="Regex to clean video title"), PXML, PClonable>
Friend ReadOnly Property TitleUseRegexForTitle_Value As PropertyValue
<PropertyOption(ControlText:="Use video date as file date", <PropertyOption(ControlText:="Use video date as file date",
ControlToolTip:="Set the file date to the date the video was added (website) (if available)."), PXML, PClonable> ControlToolTip:="Set the file date to the date the video was added (website) (if available)."), PXML, PClonable>
Friend ReadOnly Property UseParsedVideoDate As PropertyValue Friend ReadOnly Property UseParsedVideoDate As PropertyValue
@@ -31,6 +35,8 @@ Namespace API.TikTok
TitleUseNative = New PropertyValue(True) TitleUseNative = New PropertyValue(True)
TitleUseNativeSTD = New PropertyValue(False) TitleUseNativeSTD = New PropertyValue(False)
TitleAddVideoID = New PropertyValue(True) TitleAddVideoID = New PropertyValue(True)
TitleUseRegexForTitle = New PropertyValue(False)
TitleUseRegexForTitle_Value = New PropertyValue(String.Empty, GetType(String))
UseParsedVideoDate = New PropertyValue(True) UseParsedVideoDate = New PropertyValue(True)
UseNetscapeCookies = True UseNetscapeCookies = True
UrlPatternUser = "https://www.tiktok.com/@{0}/" UrlPatternUser = "https://www.tiktok.com/@{0}/"

View File

@@ -20,6 +20,9 @@ Namespace API.TikTok
Private Const Name_TitleUseNative As String = "TitleUseNative" Private Const Name_TitleUseNative As String = "TitleUseNative"
Private Const Name_TitleAddVideoID As String = "TitleAddVideoID" Private Const Name_TitleAddVideoID As String = "TitleAddVideoID"
Private Const Name_LastDownloadDate As String = "LastDownloadDate" Private Const Name_LastDownloadDate As String = "LastDownloadDate"
Private Const Name_TitleUseRegexForTitle As String = "TitleUseRegexForTitle"
Private Const Name_TitleUseRegexForTitle_Value As String = "TitleUseRegexForTitle_Value"
Private Const Name_TitleUseGlobalRegexOptions As String = "TitleUseGlobalRegexOptions"
#End Region #End Region
#Region "Declarations" #Region "Declarations"
Private ReadOnly Property MySettings As SiteSettings Private ReadOnly Property MySettings As SiteSettings
@@ -27,8 +30,15 @@ Namespace API.TikTok
Return HOST.Source Return HOST.Source
End Get End Get
End Property End Property
Private UserCache As CacheKeeper = Nothing
Private ReadOnly Property RootCacheTikTok As ICacheKeeper Private ReadOnly Property RootCacheTikTok As ICacheKeeper
Get Get
If Not UserCache Is Nothing AndAlso Not UserCache.Disposed Then
With DirectCast(UserCache.NewInstance(Of BatchFileExchanger), BatchFileExchanger)
.Validate()
Return .Self
End With
Else
With Settings.Cache With Settings.Cache
Dim f As SFile = $"{Settings.Cache.RootDirectory.PathWithSeparator}TikTokCache\" Dim f As SFile = $"{Settings.Cache.RootDirectory.PathWithSeparator}TikTokCache\"
If .ContainsFolder(f) Then If .ContainsFolder(f) Then
@@ -42,11 +52,15 @@ Namespace API.TikTok
End With End With
End If End If
End With End With
End If
End Get End Get
End Property End Property
Friend Property RemoveTagsFromTitle As Boolean = False Friend Property RemoveTagsFromTitle As Boolean = False
Friend Property TitleUseNative As Boolean = True Friend Property TitleUseNative As Boolean = True
Friend Property TitleAddVideoID As Boolean = True Friend Property TitleAddVideoID As Boolean = True
Friend Property TitleUseRegexForTitle As Boolean = False
Friend Property TitleUseRegexForTitle_Value As String = String.Empty
Friend Property TitleUseGlobalRegexOptions As Boolean = True
Private Property LastDownloadDate As Date? = Nothing Private Property LastDownloadDate As Date? = Nothing
Private _TrueName As String = String.Empty Private _TrueName As String = String.Empty
Friend Property TrueName As String Friend Property TrueName As String
@@ -68,6 +82,9 @@ Namespace API.TikTok
RemoveTagsFromTitle = .RemoveTagsFromTitle RemoveTagsFromTitle = .RemoveTagsFromTitle
TitleUseNative = .TitleUseNative TitleUseNative = .TitleUseNative
TitleAddVideoID = .TitleAddVideoID TitleAddVideoID = .TitleAddVideoID
TitleUseRegexForTitle = .TitleUseRegexForTitle
TitleUseRegexForTitle_Value = .TitleUseRegexForTitle_Value
TitleUseGlobalRegexOptions = .TitleUseGlobalRegexOptions
End With End With
End If End If
End Sub End Sub
@@ -82,12 +99,18 @@ Namespace API.TikTok
LastDownloadDate = AConvert(Of Date)(.Value(Name_LastDownloadDate), ADateTime.Formats.BaseDateTime, Nothing) LastDownloadDate = AConvert(Of Date)(.Value(Name_LastDownloadDate), ADateTime.Formats.BaseDateTime, Nothing)
If Not LastDownloadDate.HasValue Then LastDownloadDate = LastUpdated If Not LastDownloadDate.HasValue Then LastDownloadDate = LastUpdated
_TrueName = .Value(Name_TrueName) _TrueName = .Value(Name_TrueName)
TitleUseRegexForTitle = .Value(Name_TitleUseRegexForTitle).FromXML(Of Boolean)(False)
TitleUseRegexForTitle_Value = .Value(Name_TitleUseRegexForTitle_Value)
TitleUseGlobalRegexOptions = .Value(Name_TitleUseGlobalRegexOptions).FromXML(Of Boolean)(True)
Else Else
.Add(Name_RemoveTagsFromTitle, RemoveTagsFromTitle.BoolToInteger) .Add(Name_RemoveTagsFromTitle, RemoveTagsFromTitle.BoolToInteger)
.Add(Name_TitleUseNative, TitleUseNative.BoolToInteger) .Add(Name_TitleUseNative, TitleUseNative.BoolToInteger)
.Add(Name_TitleAddVideoID, TitleAddVideoID.BoolToInteger) .Add(Name_TitleAddVideoID, TitleAddVideoID.BoolToInteger)
.Add(Name_LastDownloadDate, AConvert(Of String)(LastDownloadDate, AModes.XML, ADateTime.Formats.BaseDateTime, String.Empty)) .Add(Name_LastDownloadDate, AConvert(Of String)(LastDownloadDate, AModes.XML, ADateTime.Formats.BaseDateTime, String.Empty))
.Add(Name_TrueName, _TrueName) .Add(Name_TrueName, _TrueName)
.Add(Name_TitleUseRegexForTitle, TitleUseRegexForTitle.BoolToInteger)
.Add(Name_TitleUseRegexForTitle_Value, TitleUseRegexForTitle_Value)
.Add(Name_TitleUseGlobalRegexOptions, TitleUseGlobalRegexOptions.BoolToInteger)
End If End If
End With End With
End Sub End Sub
@@ -99,9 +122,43 @@ Namespace API.TikTok
End Sub End Sub
#End Region #End Region
#Region "Download functions" #Region "Download functions"
Private Function GetTitleRegex() As RParams
Dim titleRegex As RParams = Nothing
If TitleUseGlobalRegexOptions Then
If CBool(MySettings.TitleUseRegexForTitle.Value) AndAlso Not CStr(MySettings.TitleUseRegexForTitle_Value.Value).IsEmptyString Then _
titleRegex = RParams.DM(MySettings.TitleUseRegexForTitle_Value.Value, 0, RegexReturn.List, EDP.ReturnValue)
ElseIf TitleUseRegexForTitle And Not TitleUseRegexForTitle_Value.IsEmptyString Then
titleRegex = RParams.DM(TitleUseRegexForTitle_Value, 0, RegexReturn.List, EDP.ReturnValue)
End If
If Not titleRegex Is Nothing Then
titleRegex.NothingExists = True
titleRegex.Nothing = New List(Of String)
titleRegex.Converter = Function(input) input.StringTrim
End If
Return titleRegex
End Function
Private Function ChangeTitleRegex(ByVal Title As String, ByVal Regex As RParams) As String
Try
If Not Regex Is Nothing Then
With DirectCast(RegexReplace(Title, Regex), List(Of String))
If .ListExists Then
Dim newTitle$ = .ListToString(String.Empty, EDP.ReturnValue).StringTrim
If Not newTitle.IsEmptyString Then Return newTitle
End If
End With
End If
Catch ex As Exception
End Try
Return Title
End Function
Friend Overrides Sub DownloadData(ByVal Token As CancellationToken)
MyBase.DownloadData(Token)
UserCache.DisposeIfReady(False)
UserCache = Nothing
End Sub
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
Dim URL$ = $"https://www.tiktok.com/@{TrueName}" Dim URL$ = $"https://www.tiktok.com/@{TrueName}"
Using cache As CacheKeeper = CreateCache() UserCache = CreateCache()
Try Try
Dim postID$, title$, postUrl$, newName$ Dim postID$, title$, postUrl$, newName$
Dim postDate As Date? Dim postDate As Date?
@@ -109,6 +166,7 @@ Namespace API.TikTok
Dim dateBefore As Date? = DownloadDateTo Dim dateBefore As Date? = DownloadDateTo
Dim dateAfter As Date? = DownloadDateFrom Dim dateAfter As Date? = DownloadDateFrom
Dim baseDataObtained As Boolean = False Dim baseDataObtained As Boolean = False
Dim titleRegex As RParams = GetTitleRegex()
If _ContentList.Count > 0 Then If _ContentList.Count > 0 Then
With (From d In _ContentList Where d.Post.Date.HasValue Select d.Post.Date.Value) With (From d In _ContentList Where d.Post.Date.HasValue Select d.Post.Date.Value)
@@ -136,14 +194,14 @@ Namespace API.TikTok
Using b As New YTDLP.YTDLPBatch(Token) With {.TempPostsList = _TempPostsList} Using b As New YTDLP.YTDLPBatch(Token) With {.TempPostsList = _TempPostsList}
b.Commands.Clear() b.Commands.Clear()
b.ChangeDirectory(cache) b.ChangeDirectory(UserCache)
b.Encoding = BatchExecutor.UnicodeEncoding b.Encoding = BatchExecutor.UnicodeEncoding
b.Execute(CreateYTCommand(cache.RootDirectory, URL, False, dateBefore, dateAfter)) b.Execute(CreateYTCommand(UserCache.RootDirectory, URL, False, dateBefore, dateAfter))
End Using End Using
ThrowAny(Token) ThrowAny(Token)
Dim files As List(Of SFile) = SFile.GetFiles(cache, "*.json",, EDP.ReturnValue) Dim files As List(Of SFile) = SFile.GetFiles(UserCache, "*.json",, EDP.ReturnValue)
If files.ListExists Then If files.ListExists Then
Dim j As EContainer Dim j As EContainer
For Each file As SFile In files For Each file As SFile In files
@@ -181,6 +239,7 @@ Namespace API.TikTok
ElseIf TitleAddVideoID Then ElseIf TitleAddVideoID Then
title &= $" ({postID})" title &= $" ({postID})"
End If End If
title = ChangeTitleRegex(title, titleRegex)
End If End If
postDate = AConvert(Of Date)(j.Value("timestamp"), UnixDate32Provider, Nothing) postDate = AConvert(Of Date)(j.Value("timestamp"), UnixDate32Provider, Nothing)
If Not postDate.HasValue Then postDate = AConvert(Of Date)(j.Value("upload_date"), SimpleDateConverter, Nothing) If Not postDate.HasValue Then postDate = AConvert(Of Date)(j.Value("upload_date"), SimpleDateConverter, Nothing)
@@ -202,7 +261,6 @@ Namespace API.TikTok
Catch ex As Exception Catch ex As Exception
ProcessException(ex, Token, $"data downloading error [{URL}]") ProcessException(ex, Token, $"data downloading error [{URL}]")
End Try End Try
End Using
End Sub End Sub
#End Region #End Region
#Region "ReparseMissing" #Region "ReparseMissing"
@@ -292,6 +350,7 @@ Namespace API.TikTok
f = f.StringTrim f = f.StringTrim
If Not f.IsEmptyString Then If Not f.IsEmptyString Then
If CBool(MySettings.TitleAddVideoID.Value) Then f &= $" ({m.File.Name})" If CBool(MySettings.TitleAddVideoID.Value) Then f &= $" ({m.File.Name})"
f = ChangeTitleRegex(f, GetTitleRegex)
m.File.Name = f m.File.Name = f
End If End If
End If End If
@@ -303,6 +362,15 @@ Namespace API.TikTok
Optional ByVal EObj As Object = Nothing) As Integer Optional ByVal EObj As Object = Nothing) As Integer
Return 0 Return 0
End Function End Function
#End Region
#Region "IDisposable Support"
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If Not disposedValue And disposing Then
UserCache.DisposeIfReady(False)
UserCache = Nothing
End If
MyBase.Dispose(disposing)
End Sub
#End Region #End Region
End Class End Class
End Namespace End Namespace

View File

@@ -15,18 +15,29 @@ Namespace API.TikTok
Friend Property TitleUseNative As Boolean Friend Property TitleUseNative As Boolean
<PSetting(NameOf(SiteSettings.TitleAddVideoID), NameOf(MySettings))> <PSetting(NameOf(SiteSettings.TitleAddVideoID), NameOf(MySettings))>
Friend Property TitleAddVideoID As Boolean Friend Property TitleAddVideoID As Boolean
<PSetting(NameOf(SiteSettings.TitleUseRegexForTitle), NameOf(MySettings))>
Friend Property TitleUseRegexForTitle As Boolean
<PSetting(NameOf(SiteSettings.TitleUseRegexForTitle_Value), NameOf(MySettings))>
Friend Property TitleUseRegexForTitle_Value As String
<PSetting(Caption:="Use global regex", ToolTip:="Use the global regex from the site settings to clean the video title")>
Friend Property TitleUseGlobalRegexOptions As Boolean = True
Private ReadOnly MySettings As SiteSettings Private ReadOnly MySettings As SiteSettings
Friend Sub New(ByVal u As UserData) Friend Sub New(ByVal u As UserData)
MySettings = u.HOST.Source MySettings = u.HOST.Source
RemoveTagsFromTitle = u.RemoveTagsFromTitle RemoveTagsFromTitle = u.RemoveTagsFromTitle
TitleUseNative = u.TitleUseNative TitleUseNative = u.TitleUseNative
TitleAddVideoID = u.TitleAddVideoID TitleAddVideoID = u.TitleAddVideoID
TitleUseRegexForTitle = u.TitleUseRegexForTitle
TitleUseRegexForTitle_Value = u.TitleUseRegexForTitle_Value
TitleUseGlobalRegexOptions = u.TitleUseGlobalRegexOptions
End Sub End Sub
Friend Sub New(ByVal s As SiteSettings) Friend Sub New(ByVal s As SiteSettings)
MySettings = s MySettings = s
RemoveTagsFromTitle = s.RemoveTagsFromTitle.Value RemoveTagsFromTitle = s.RemoveTagsFromTitle.Value
TitleUseNative = s.TitleUseNative.Value TitleUseNative = s.TitleUseNative.Value
TitleAddVideoID = s.TitleAddVideoID.Value TitleAddVideoID = s.TitleAddVideoID.Value
TitleUseRegexForTitle = s.TitleUseRegexForTitle.Value
TitleUseRegexForTitle_Value = s.TitleUseRegexForTitle_Value.Value
End Sub End Sub
End Class End Class
End Namespace End Namespace

View File

@@ -741,6 +741,15 @@ Namespace API
Return GetEnumerator() Return GetEnumerator()
End Function End Function
#End Region #End Region
#Region "IComparable Support"
Friend Overrides Function CompareTo(ByVal Other As UserDataBase) As Integer
If TypeOf Other Is UserDataBind Then
Return CollectionName.CompareTo(Other.CollectionName)
Else
Return -1
End If
End Function
#End Region
#Region "IEquatable support" #Region "IEquatable support"
Friend Overrides Function Equals(ByVal Other As UserDataBase) As Boolean Friend Overrides Function Equals(ByVal Other As UserDataBase) As Boolean
If Other.IsCollection Then If Other.IsCollection Then

View File

@@ -84,10 +84,15 @@ Namespace API.Xhamster
End Function End Function
Private Shared Function ObtainUrls(ByVal URL As String, ByVal Responser As Responser, ByVal UHD As Boolean) As List(Of M3U8URL) Private Shared Function ObtainUrls(ByVal URL As String, ByVal Responser As Responser, ByVal UHD As Boolean) As List(Of M3U8URL)
Try Try
Const sk$ = "/key="
Dim file$ = ParseFirstM3U8(URL, Responser, UHD) Dim file$ = ParseFirstM3U8(URL, Responser, UHD)
If Not file.IsEmptyString Then If Not file.IsEmptyString Then
Responser.UseGZipStream = False Responser.UseGZipStream = False
Dim appender$ = URL.Replace(URL.Split("/").LastOrDefault, String.Empty) Dim appender$ = URL.Replace(URL.Split("/").LastOrDefault, String.Empty)
If file.StartsWith(sk) Then
Dim position% = InStr(URL, sk)
If position > 0 Then appender = URL.Remove(position - 1)
End If
URL = M3U8Base.CreateUrl(appender, file) URL = M3U8Base.CreateUrl(appender, file)
Dim l As List(Of M3U8URL) = ParseSecondM3U8(URL, Responser, appender) Dim l As List(Of M3U8URL) = ParseSecondM3U8(URL, Responser, appender)
If l.ListExists Then Return l If l.ListExists Then Return l

View File

@@ -24,6 +24,8 @@ Namespace API.YouTube
Friend ReadOnly Property DownloadCommunityImages As PropertyValue Friend ReadOnly Property DownloadCommunityImages As PropertyValue
<PXML, PropertyOption(ControlText:="Download user community: videos"), PClonable> <PXML, PropertyOption(ControlText:="Download user community: videos"), PClonable>
Friend ReadOnly Property DownloadCommunityVideos As PropertyValue Friend ReadOnly Property DownloadCommunityVideos As PropertyValue
<PXML, PropertyOption(ControlText:="Ignore community errors", ControlToolTip:="If true, community errors will not be added to the log."), PClonable>
Friend ReadOnly Property IgnoreCommunityErrors As PropertyValue
<PXML, PropertyOption(ControlText:="Use cookies", ControlToolTip:="Default value for new users." & vbCr & "Use cookies when downloading data."), PClonable> <PXML, PropertyOption(ControlText:="Use cookies", ControlToolTip:="Default value for new users." & vbCr & "Use cookies when downloading data."), PClonable>
Friend ReadOnly Property UseCookies As PropertyValue Friend ReadOnly Property UseCookies As PropertyValue
#End Region #End Region
@@ -36,6 +38,7 @@ Namespace API.YouTube
DownloadPlaylists = New PropertyValue(False) DownloadPlaylists = New PropertyValue(False)
DownloadCommunityImages = New PropertyValue(False) DownloadCommunityImages = New PropertyValue(False)
DownloadCommunityVideos = New PropertyValue(False) DownloadCommunityVideos = New PropertyValue(False)
IgnoreCommunityErrors = New PropertyValue(False)
UseCookies = New PropertyValue(False) UseCookies = New PropertyValue(False)
_SubscriptionsAllowed = True _SubscriptionsAllowed = True
UseNetscapeCookies = True UseNetscapeCookies = True

View File

@@ -333,7 +333,7 @@ Namespace API.YouTube
Next Next
End If End If
End With End With
Else ElseIf Not CBool(DirectCast(HOST.Source, SiteSettings).IgnoreCommunityErrors.Value) Then
With j({"error"}) With j({"error"})
If .ListExists Then MyMainLOG = $"{ToStringForLog()} {errMsg} [{ .Value("code")}]: { .Value("message")}" If .ListExists Then MyMainLOG = $"{ToStringForLog()} {errMsg} [{ .Value("code")}]: { .Value("message")}"
End With End With

View File

@@ -580,7 +580,7 @@ Namespace DownloadObjects
x.Dispose() x.Dispose()
For i = 1 To files.Count - 1 : files(i).Delete(SFO.File, SFODelete.DeleteToRecycleBin, EDP.ReturnValue) : Next For i = 1 To files.Count - 1 : files(i).Delete(SFO.File, SFODelete.DeleteToRecycleBin, EDP.ReturnValue) : Next
MsgBoxE({$"Session data was combined into '{files(0).Name}'.{vbCr}{vbCr}" & MsgBoxE({$"Session data was combined into '{files(0).Name}'.{vbCr}{vbCr}" &
files.ListToStringE(, New CustomProvider(Function(ff As SFile) ff.Name),,, EDP.ReturnValue), msgTitle}) files.ListToStringE(vbCr, New CustomProvider(Function(ff As SFile) ff.Name),,, EDP.ReturnValue), msgTitle})
files.Clear() files.Clear()
data.Clear() data.Clear()
Else Else

View File

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