mirror of
https://github.com/AAndyProgram/SCrawler.git
synced 2026-03-15 16:22:17 +00:00
Compare commits
3 Commits
2025.6.12.
...
2025.8.30.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5857fcfae3 | ||
|
|
e09752a2d5 | ||
|
|
05772a9fc4 |
51
Changelog.md
51
Changelog.md
@@ -1,3 +1,54 @@
|
|||||||
|
# 2025.8.30.0
|
||||||
|
|
||||||
|
*2025-08-30*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- YouTube:
|
||||||
|
- **video trim** *(button `Trim`)*
|
||||||
|
- embed chapters into video file
|
||||||
|
- add artist name when downloading audio
|
||||||
|
- Correct handling of `webp` files
|
||||||
|
- Minor improvements
|
||||||
|
- Updated
|
||||||
|
- yt-dlp up to version **2025.08.27**
|
||||||
|
- gallery-dl up to version **1.30.5**
|
||||||
|
- Fixed
|
||||||
|
- **YouTube: downloading error**
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2025.8.1.0
|
||||||
|
|
||||||
|
*2025-08-01*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Sites:
|
||||||
|
- Reddit: **bypass error `429`**
|
||||||
|
- Twitter: **[large profile option](https://github.com/AAndyProgram/SCrawler/wiki/Settings#twitter-user-settings) in user settings**
|
||||||
|
- Minor improvements
|
||||||
|
- Updated
|
||||||
|
- yt-dlp up to version **2025.07.21**
|
||||||
|
- gallery-dl up to version **1.30.2**
|
||||||
|
- Fixed
|
||||||
|
- Reddit: in some cases crossposts don't download
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
|
# 2025.7.18.0
|
||||||
|
|
||||||
|
*2025-07-18*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Sites:
|
||||||
|
- OnlyFans: support for GIF files
|
||||||
|
- Reddit: extended `429` error handling
|
||||||
|
- Xhamster: support for downloading 'moments'
|
||||||
|
- Minor improvements
|
||||||
|
- Updated
|
||||||
|
- yt-dlp up to version **2025.06.30**
|
||||||
|
- gallery-dl up to version **1.30.0**
|
||||||
|
- Fixed
|
||||||
|
- OnlyFans: **hanging on purchased content**
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
# 2025.6.12.0
|
# 2025.6.12.0
|
||||||
|
|
||||||
*2025-06-12*
|
*2025-06-12*
|
||||||
|
|||||||
@@ -136,4 +136,34 @@ Namespace API.YouTube.Base
|
|||||||
End If
|
End If
|
||||||
End Function
|
End Function
|
||||||
End Structure
|
End Structure
|
||||||
|
Public Structure TrimOption : Implements IComparable(Of TrimOption)
|
||||||
|
Public Name As String
|
||||||
|
Public Start As Integer
|
||||||
|
Public ReadOnly Property StartTime As TimeSpan
|
||||||
|
Get
|
||||||
|
Return TimeSpan.FromSeconds(Start)
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Public [End] As Integer
|
||||||
|
Public ReadOnly Property EndTime As TimeSpan
|
||||||
|
Get
|
||||||
|
Return TimeSpan.FromSeconds([End])
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Public Shared Widening Operator CType(ByVal t As TrimOption) As String
|
||||||
|
Return t.ToString
|
||||||
|
End Operator
|
||||||
|
Public Overrides Function ToString() As String
|
||||||
|
Dim v$ = $"{Start} - {[End]}"
|
||||||
|
If Not Name.IsEmptyString Then v = $"[{v}] - {Name}"
|
||||||
|
Return v
|
||||||
|
End Function
|
||||||
|
Public Overrides Function Equals(ByVal Obj As Object) As Boolean
|
||||||
|
Try : With DirectCast(Obj, TrimOption) : Return Start = .Start And [End] = .End : End With : Catch : End Try
|
||||||
|
Return False
|
||||||
|
End Function
|
||||||
|
Private Function CompareTo(ByVal Other As TrimOption) As Integer Implements IComparable(Of TrimOption).CompareTo
|
||||||
|
Return Start.CompareTo(Other.Start)
|
||||||
|
End Function
|
||||||
|
End Structure
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -319,8 +319,11 @@ Namespace API.YouTube.Base
|
|||||||
Description("Convert non-AVC codecs (eg 'VP9') to AVC. Not recommended due to high CPU usage!")>
|
Description("Convert non-AVC codecs (eg 'VP9') to AVC. Not recommended due to high CPU usage!")>
|
||||||
Public ReadOnly Property DefaultVideoConvertNonAVC As XMLValue(Of Boolean)
|
Public ReadOnly Property DefaultVideoConvertNonAVC As XMLValue(Of Boolean)
|
||||||
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, False), Category("Defaults Video"), DisplayName("Embed thumbnail (video)"),
|
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, False), Category("Defaults Video"), DisplayName("Embed thumbnail (video)"),
|
||||||
Description("Embed thumbnail in the video as cover art. Default: true.")>
|
Description("Embed thumbnail in the video as cover art. Default: false.")>
|
||||||
Public ReadOnly Property DefaultVideoEmbedThumbnail As XMLValue(Of Boolean)
|
Public ReadOnly Property DefaultVideoEmbedThumbnail As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, True), Category("Defaults Video"), DisplayName("Embed chapters"),
|
||||||
|
Description("Embed chapters in the video. Default: true.")>
|
||||||
|
Public ReadOnly Property DefaultVideoEmbedChapters As XMLValue(Of Boolean)
|
||||||
<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)
|
||||||
@@ -496,6 +499,26 @@ Namespace API.YouTube.Base
|
|||||||
Description("Additional format for downloading subtitles. This means that all subtitles will be converted to the formats you choose and saved as separate files.")>
|
Description("Additional format for downloading subtitles. This means that all subtitles will be converted to the formats you choose and saved as separate files.")>
|
||||||
Public ReadOnly Property DefaultSubtitlesFormatAddit As XMLValuesCollection(Of String)
|
Public ReadOnly Property DefaultSubtitlesFormatAddit As XMLValuesCollection(Of String)
|
||||||
#End Region
|
#End Region
|
||||||
|
#Region "Trim"
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsTrim"}, False), Category("Defaults Trimming"), DisplayName("Delete original file"),
|
||||||
|
Description("If true, the original file will be deleted after trimming")>
|
||||||
|
Public ReadOnly Property TrimDeleteOriginalFile As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsTrim"}, False), Category("Defaults Trimming"), DisplayName("Add to M3U8"),
|
||||||
|
Description("If true, the trimmed files will be added to the M3U8 playlist (if selected)")>
|
||||||
|
Public ReadOnly Property TrimAddTrimmedFilesToM3U8 As XMLValue(Of Boolean)
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsTrim"}, False), Category("Defaults Trimming"), DisplayName("Separate folder"),
|
||||||
|
Description("Place the trimmed files in a separate folder")>
|
||||||
|
Public ReadOnly Property TrimSeparateFolder As XMLValue(Of Boolean)
|
||||||
|
Friend Const TrimSeparateFolderNameDefault As String = "Trim"
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"DefaultsTrim"}, TrimSeparateFolderNameDefault), Category("Defaults Trimming"), DisplayName("Separate folder name"),
|
||||||
|
Description("Name of a separate folder")>
|
||||||
|
Public ReadOnly Property TrimSeparateFolderName As XMLValue(Of String)
|
||||||
|
#End Region
|
||||||
|
#Region "Errors"
|
||||||
|
<Browsable(True), GridVisible, XMLVN({"Errors"}, True), Category("ERRORS"), DisplayName("Ignore downloading errors"),
|
||||||
|
Description("Ignore download errors if some files are missing (e.g. subtitles) and continue downloading")>
|
||||||
|
Public ReadOnly Property ErrorsIgnore As XMLValue(Of Boolean)
|
||||||
|
#End Region
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
Public Sub New()
|
Public Sub New()
|
||||||
|
|||||||
158
SCrawler.YouTube/Controls/ChaptersForm.Designer.vb
generated
Normal file
158
SCrawler.YouTube/Controls/ChaptersForm.Designer.vb
generated
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Namespace API.YouTube.Controls
|
||||||
|
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
|
||||||
|
Partial Friend Class ChaptersForm : Inherits System.Windows.Forms.Form
|
||||||
|
<System.Diagnostics.DebuggerNonUserCode()>
|
||||||
|
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
|
||||||
|
Try
|
||||||
|
If disposing AndAlso components IsNot Nothing Then
|
||||||
|
components.Dispose()
|
||||||
|
End If
|
||||||
|
Finally
|
||||||
|
MyBase.Dispose(disposing)
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
Private components As System.ComponentModel.IContainer
|
||||||
|
<System.Diagnostics.DebuggerStepThrough()>
|
||||||
|
Private Sub InitializeComponent()
|
||||||
|
Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
|
||||||
|
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
|
||||||
|
Dim TP_BUTTONS As System.Windows.Forms.TableLayoutPanel
|
||||||
|
Me.BTT_ALL = New System.Windows.Forms.Button()
|
||||||
|
Me.BTT_NONE = New System.Windows.Forms.Button()
|
||||||
|
Me.BTT_INVERT = New System.Windows.Forms.Button()
|
||||||
|
Me.LIST_CHAPTERS = New System.Windows.Forms.CheckedListBox()
|
||||||
|
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
|
||||||
|
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
TP_BUTTONS = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
CONTAINER_MAIN.ContentPanel.SuspendLayout()
|
||||||
|
CONTAINER_MAIN.SuspendLayout()
|
||||||
|
TP_MAIN.SuspendLayout()
|
||||||
|
TP_BUTTONS.SuspendLayout()
|
||||||
|
Me.SuspendLayout()
|
||||||
|
'
|
||||||
|
'CONTAINER_MAIN
|
||||||
|
'
|
||||||
|
'
|
||||||
|
'CONTAINER_MAIN.ContentPanel
|
||||||
|
'
|
||||||
|
CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
|
||||||
|
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(384, 361)
|
||||||
|
CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
CONTAINER_MAIN.LeftToolStripPanelVisible = False
|
||||||
|
CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||||
|
CONTAINER_MAIN.Name = "CONTAINER_MAIN"
|
||||||
|
CONTAINER_MAIN.RightToolStripPanelVisible = False
|
||||||
|
CONTAINER_MAIN.Size = New System.Drawing.Size(384, 361)
|
||||||
|
CONTAINER_MAIN.TabIndex = 0
|
||||||
|
CONTAINER_MAIN.TopToolStripPanelVisible = False
|
||||||
|
'
|
||||||
|
'TP_MAIN
|
||||||
|
'
|
||||||
|
TP_MAIN.ColumnCount = 1
|
||||||
|
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||||
|
TP_MAIN.Controls.Add(TP_BUTTONS, 0, 1)
|
||||||
|
TP_MAIN.Controls.Add(Me.LIST_CHAPTERS, 0, 0)
|
||||||
|
TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
TP_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||||
|
TP_MAIN.Name = "TP_MAIN"
|
||||||
|
TP_MAIN.RowCount = 2
|
||||||
|
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30.0!))
|
||||||
|
TP_MAIN.Size = New System.Drawing.Size(384, 361)
|
||||||
|
TP_MAIN.TabIndex = 0
|
||||||
|
'
|
||||||
|
'TP_BUTTONS
|
||||||
|
'
|
||||||
|
TP_BUTTONS.ColumnCount = 3
|
||||||
|
TP_BUTTONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
TP_BUTTONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
TP_BUTTONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
TP_BUTTONS.Controls.Add(Me.BTT_ALL, 0, 0)
|
||||||
|
TP_BUTTONS.Controls.Add(Me.BTT_NONE, 1, 0)
|
||||||
|
TP_BUTTONS.Controls.Add(Me.BTT_INVERT, 2, 0)
|
||||||
|
TP_BUTTONS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
TP_BUTTONS.Location = New System.Drawing.Point(0, 331)
|
||||||
|
TP_BUTTONS.Margin = New System.Windows.Forms.Padding(0)
|
||||||
|
TP_BUTTONS.Name = "TP_BUTTONS"
|
||||||
|
TP_BUTTONS.RowCount = 1
|
||||||
|
TP_BUTTONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_BUTTONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||||
|
TP_BUTTONS.Size = New System.Drawing.Size(384, 30)
|
||||||
|
TP_BUTTONS.TabIndex = 1
|
||||||
|
'
|
||||||
|
'BTT_ALL
|
||||||
|
'
|
||||||
|
Me.BTT_ALL.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.BTT_ALL.Location = New System.Drawing.Point(3, 3)
|
||||||
|
Me.BTT_ALL.Name = "BTT_ALL"
|
||||||
|
Me.BTT_ALL.Size = New System.Drawing.Size(122, 24)
|
||||||
|
Me.BTT_ALL.TabIndex = 0
|
||||||
|
Me.BTT_ALL.Text = "All"
|
||||||
|
Me.BTT_ALL.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'BTT_NONE
|
||||||
|
'
|
||||||
|
Me.BTT_NONE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.BTT_NONE.Location = New System.Drawing.Point(131, 3)
|
||||||
|
Me.BTT_NONE.Name = "BTT_NONE"
|
||||||
|
Me.BTT_NONE.Size = New System.Drawing.Size(122, 24)
|
||||||
|
Me.BTT_NONE.TabIndex = 1
|
||||||
|
Me.BTT_NONE.Text = "None"
|
||||||
|
Me.BTT_NONE.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'BTT_INVERT
|
||||||
|
'
|
||||||
|
Me.BTT_INVERT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.BTT_INVERT.Location = New System.Drawing.Point(259, 3)
|
||||||
|
Me.BTT_INVERT.Name = "BTT_INVERT"
|
||||||
|
Me.BTT_INVERT.Size = New System.Drawing.Size(122, 24)
|
||||||
|
Me.BTT_INVERT.TabIndex = 2
|
||||||
|
Me.BTT_INVERT.Text = "Invert"
|
||||||
|
Me.BTT_INVERT.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'LIST_CHAPTERS
|
||||||
|
'
|
||||||
|
Me.LIST_CHAPTERS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.LIST_CHAPTERS.FormattingEnabled = True
|
||||||
|
Me.LIST_CHAPTERS.Location = New System.Drawing.Point(3, 3)
|
||||||
|
Me.LIST_CHAPTERS.Name = "LIST_CHAPTERS"
|
||||||
|
Me.LIST_CHAPTERS.Size = New System.Drawing.Size(378, 325)
|
||||||
|
Me.LIST_CHAPTERS.TabIndex = 0
|
||||||
|
'
|
||||||
|
'ChaptersForm
|
||||||
|
'
|
||||||
|
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
||||||
|
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
||||||
|
Me.ClientSize = New System.Drawing.Size(384, 361)
|
||||||
|
Me.Controls.Add(CONTAINER_MAIN)
|
||||||
|
Me.KeyPreview = True
|
||||||
|
Me.MinimizeBox = False
|
||||||
|
Me.MinimumSize = New System.Drawing.Size(400, 400)
|
||||||
|
Me.Name = "ChaptersForm"
|
||||||
|
Me.ShowIcon = False
|
||||||
|
Me.ShowInTaskbar = False
|
||||||
|
Me.Text = "Chapters"
|
||||||
|
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.PerformLayout()
|
||||||
|
TP_MAIN.ResumeLayout(False)
|
||||||
|
TP_BUTTONS.ResumeLayout(False)
|
||||||
|
Me.ResumeLayout(False)
|
||||||
|
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private WithEvents BTT_ALL As Button
|
||||||
|
Private WithEvents BTT_NONE As Button
|
||||||
|
Private WithEvents BTT_INVERT As Button
|
||||||
|
Private WithEvents LIST_CHAPTERS As CheckedListBox
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
129
SCrawler.YouTube/Controls/ChaptersForm.resx
Normal file
129
SCrawler.YouTube/Controls/ChaptersForm.resx
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<metadata name="CONTAINER_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="TP_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="TP_BUTTONS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
</root>
|
||||||
66
SCrawler.YouTube/Controls/ChaptersForm.vb
Normal file
66
SCrawler.YouTube/Controls/ChaptersForm.vb
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports PersonalUtilities.Forms
|
||||||
|
Imports PersonalUtilities.Forms.Toolbars
|
||||||
|
Imports SCrawler.API.YouTube.Base
|
||||||
|
Imports SCrawler.API.YouTube.Objects
|
||||||
|
Namespace API.YouTube.Controls
|
||||||
|
Friend Class ChaptersForm
|
||||||
|
Private WithEvents MyDefs As DefaultFormOptions
|
||||||
|
Private ReadOnly Property MyData As YouTubeMediaContainerBase
|
||||||
|
Private ReadOnly Property MyDataSelected As List(Of TrimOption)
|
||||||
|
Friend ReadOnly Property MyResult As List(Of TrimOption)
|
||||||
|
Friend Sub New(ByRef data As YouTubeMediaContainerBase, ByVal selected As IEnumerable(Of TrimOption))
|
||||||
|
InitializeComponent()
|
||||||
|
MyDefs = New DefaultFormOptions(Me, MyYouTubeSettings.DesignXml)
|
||||||
|
MyData = data
|
||||||
|
MyDataSelected = New List(Of TrimOption)
|
||||||
|
MyDataSelected.ListAddList(selected)
|
||||||
|
MyResult = New List(Of TrimOption)
|
||||||
|
End Sub
|
||||||
|
Private Sub ChaptersForm_Load(sender As Object, e As EventArgs) Handles Me.Load
|
||||||
|
With MyDefs
|
||||||
|
.MyViewInitialize()
|
||||||
|
.AddOkCancelToolbar()
|
||||||
|
|
||||||
|
With LIST_CHAPTERS
|
||||||
|
.BeginUpdate()
|
||||||
|
.Items.AddRange(MyData.Chapters.Cast(Of Object).ToArray)
|
||||||
|
If MyDataSelected.Count > 0 Then
|
||||||
|
For i% = 0 To .Items.Count - 1 : .SetItemChecked(i, MyDataSelected.Contains(MyData.Chapters(i))) : Next
|
||||||
|
End If
|
||||||
|
.EndUpdate()
|
||||||
|
End With
|
||||||
|
|
||||||
|
.EndLoaderOperations()
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
|
Private Sub ChaptersForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
|
||||||
|
MyResult.Clear()
|
||||||
|
MyDataSelected.Clear()
|
||||||
|
End Sub
|
||||||
|
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
|
||||||
|
With LIST_CHAPTERS
|
||||||
|
For i% = 0 To .Items.Count - 1
|
||||||
|
If .GetItemChecked(i) Then MyResult.Add(MyData.Chapters(i))
|
||||||
|
Next
|
||||||
|
End With
|
||||||
|
MyDefs.CloseForm()
|
||||||
|
End Sub
|
||||||
|
Private Sub BTT_ALL_NONE_INVERT_Click(sender As Object, e As EventArgs) Handles BTT_ALL.Click, BTT_NONE.Click, BTT_INVERT.Click
|
||||||
|
Dim v As Boolean = sender Is BTT_ALL
|
||||||
|
Dim isInvert As Boolean = sender Is BTT_INVERT
|
||||||
|
With LIST_CHAPTERS
|
||||||
|
.BeginUpdate()
|
||||||
|
For i% = 0 To .Items.Count - 1 : .SetItemChecked(i, If(isInvert, Not .GetItemChecked(i), v)) : Next
|
||||||
|
.EndUpdate()
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
274
SCrawler.YouTube/Controls/TrimOptionForm.Designer.vb
generated
Normal file
274
SCrawler.YouTube/Controls/TrimOptionForm.Designer.vb
generated
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Namespace API.YouTube.Controls
|
||||||
|
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
|
||||||
|
Partial Friend Class TrimOptionForm : Inherits System.Windows.Forms.Form
|
||||||
|
<System.Diagnostics.DebuggerNonUserCode()>
|
||||||
|
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
|
||||||
|
Try
|
||||||
|
If disposing AndAlso components IsNot Nothing Then
|
||||||
|
components.Dispose()
|
||||||
|
End If
|
||||||
|
Finally
|
||||||
|
MyBase.Dispose(disposing)
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
Private components As System.ComponentModel.IContainer
|
||||||
|
<System.Diagnostics.DebuggerStepThrough()>
|
||||||
|
Private Sub InitializeComponent()
|
||||||
|
Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
|
||||||
|
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
|
||||||
|
Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
|
||||||
|
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(TrimOptionForm))
|
||||||
|
Dim TP_OPTIONS As System.Windows.Forms.TableLayoutPanel
|
||||||
|
Me.TXT_NAME = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
|
Me.TP_TIME_TIME = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
Me.TXT_FROM_DATE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
|
Me.TXT_TO_DATE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
|
Me.OPT_INT = New System.Windows.Forms.RadioButton()
|
||||||
|
Me.OPT_TIME = New System.Windows.Forms.RadioButton()
|
||||||
|
Me.TP_TIME_INT = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
Me.TXT_FROM_INT = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
|
Me.TXT_TO_INT = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
|
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
|
||||||
|
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
TP_OPTIONS = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
CONTAINER_MAIN.ContentPanel.SuspendLayout()
|
||||||
|
CONTAINER_MAIN.SuspendLayout()
|
||||||
|
TP_MAIN.SuspendLayout()
|
||||||
|
CType(Me.TXT_NAME, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
|
TP_OPTIONS.SuspendLayout()
|
||||||
|
Me.TP_TIME_TIME.SuspendLayout()
|
||||||
|
CType(Me.TXT_FROM_DATE, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
|
CType(Me.TXT_TO_DATE, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
|
Me.TP_TIME_INT.SuspendLayout()
|
||||||
|
CType(Me.TXT_FROM_INT, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
|
CType(Me.TXT_TO_INT, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||||
|
Me.SuspendLayout()
|
||||||
|
'
|
||||||
|
'CONTAINER_MAIN
|
||||||
|
'
|
||||||
|
'
|
||||||
|
'CONTAINER_MAIN.ContentPanel
|
||||||
|
'
|
||||||
|
CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
|
||||||
|
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(334, 112)
|
||||||
|
CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
CONTAINER_MAIN.LeftToolStripPanelVisible = False
|
||||||
|
CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||||
|
CONTAINER_MAIN.Name = "CONTAINER_MAIN"
|
||||||
|
CONTAINER_MAIN.RightToolStripPanelVisible = False
|
||||||
|
CONTAINER_MAIN.Size = New System.Drawing.Size(334, 112)
|
||||||
|
CONTAINER_MAIN.TabIndex = 0
|
||||||
|
CONTAINER_MAIN.TopToolStripPanelVisible = False
|
||||||
|
'
|
||||||
|
'TP_MAIN
|
||||||
|
'
|
||||||
|
TP_MAIN.ColumnCount = 1
|
||||||
|
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||||
|
TP_MAIN.Controls.Add(Me.TXT_NAME, 0, 0)
|
||||||
|
TP_MAIN.Controls.Add(TP_OPTIONS, 0, 1)
|
||||||
|
TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
TP_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||||
|
TP_MAIN.Name = "TP_MAIN"
|
||||||
|
TP_MAIN.RowCount = 2
|
||||||
|
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
||||||
|
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_MAIN.Size = New System.Drawing.Size(334, 112)
|
||||||
|
TP_MAIN.TabIndex = 0
|
||||||
|
'
|
||||||
|
'TXT_NAME
|
||||||
|
'
|
||||||
|
ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image)
|
||||||
|
ActionButton1.Name = "Clear"
|
||||||
|
ActionButton1.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
|
||||||
|
Me.TXT_NAME.Buttons.Add(ActionButton1)
|
||||||
|
Me.TXT_NAME.CaptionText = "Name"
|
||||||
|
Me.TXT_NAME.CaptionToolTipText = "Section name"
|
||||||
|
Me.TXT_NAME.CaptionWidth = 50.0R
|
||||||
|
Me.TXT_NAME.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_NAME.Location = New System.Drawing.Point(3, 3)
|
||||||
|
Me.TXT_NAME.Name = "TXT_NAME"
|
||||||
|
Me.TXT_NAME.Size = New System.Drawing.Size(328, 22)
|
||||||
|
Me.TXT_NAME.TabIndex = 0
|
||||||
|
'
|
||||||
|
'TP_OPTIONS
|
||||||
|
'
|
||||||
|
TP_OPTIONS.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
|
||||||
|
TP_OPTIONS.ColumnCount = 2
|
||||||
|
TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 30.0!))
|
||||||
|
TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_OPTIONS.Controls.Add(Me.TP_TIME_TIME, 1, 1)
|
||||||
|
TP_OPTIONS.Controls.Add(Me.OPT_INT, 0, 0)
|
||||||
|
TP_OPTIONS.Controls.Add(Me.OPT_TIME, 0, 1)
|
||||||
|
TP_OPTIONS.Controls.Add(Me.TP_TIME_INT, 1, 0)
|
||||||
|
TP_OPTIONS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
TP_OPTIONS.Location = New System.Drawing.Point(3, 31)
|
||||||
|
TP_OPTIONS.Name = "TP_OPTIONS"
|
||||||
|
TP_OPTIONS.RowCount = 3
|
||||||
|
TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
||||||
|
TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
|
||||||
|
TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_OPTIONS.Size = New System.Drawing.Size(328, 78)
|
||||||
|
TP_OPTIONS.TabIndex = 1
|
||||||
|
'
|
||||||
|
'TP_TIME_TIME
|
||||||
|
'
|
||||||
|
Me.TP_TIME_TIME.ColumnCount = 2
|
||||||
|
Me.TP_TIME_TIME.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||||
|
Me.TP_TIME_TIME.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||||
|
Me.TP_TIME_TIME.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||||
|
Me.TP_TIME_TIME.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||||
|
Me.TP_TIME_TIME.Controls.Add(Me.TXT_FROM_DATE, 0, 0)
|
||||||
|
Me.TP_TIME_TIME.Controls.Add(Me.TXT_TO_DATE, 1, 0)
|
||||||
|
Me.TP_TIME_TIME.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TP_TIME_TIME.Location = New System.Drawing.Point(32, 27)
|
||||||
|
Me.TP_TIME_TIME.Margin = New System.Windows.Forms.Padding(0)
|
||||||
|
Me.TP_TIME_TIME.Name = "TP_TIME_TIME"
|
||||||
|
Me.TP_TIME_TIME.RowCount = 1
|
||||||
|
Me.TP_TIME_TIME.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
Me.TP_TIME_TIME.Size = New System.Drawing.Size(295, 25)
|
||||||
|
Me.TP_TIME_TIME.TabIndex = 3
|
||||||
|
'
|
||||||
|
'TXT_FROM_DATE
|
||||||
|
'
|
||||||
|
Me.TXT_FROM_DATE.CaptionPadding = New System.Windows.Forms.Padding(0, 0, 6, 0)
|
||||||
|
Me.TXT_FROM_DATE.CaptionText = "From"
|
||||||
|
Me.TXT_FROM_DATE.CaptionWidth = 40.0R
|
||||||
|
Me.TXT_FROM_DATE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_FROM_DATE.Location = New System.Drawing.Point(3, 3)
|
||||||
|
Me.TXT_FROM_DATE.Name = "TXT_FROM_DATE"
|
||||||
|
Me.TXT_FROM_DATE.PlaceholderEnabled = True
|
||||||
|
Me.TXT_FROM_DATE.PlaceholderText = "h:mm:ss"
|
||||||
|
Me.TXT_FROM_DATE.Size = New System.Drawing.Size(141, 22)
|
||||||
|
Me.TXT_FROM_DATE.TabIndex = 0
|
||||||
|
'
|
||||||
|
'TXT_TO_DATE
|
||||||
|
'
|
||||||
|
Me.TXT_TO_DATE.CaptionPadding = New System.Windows.Forms.Padding(0, 0, 6, 0)
|
||||||
|
Me.TXT_TO_DATE.CaptionText = "To"
|
||||||
|
Me.TXT_TO_DATE.CaptionWidth = 40.0R
|
||||||
|
Me.TXT_TO_DATE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_TO_DATE.Location = New System.Drawing.Point(150, 3)
|
||||||
|
Me.TXT_TO_DATE.Name = "TXT_TO_DATE"
|
||||||
|
Me.TXT_TO_DATE.PlaceholderEnabled = True
|
||||||
|
Me.TXT_TO_DATE.PlaceholderText = "h:mm:ss"
|
||||||
|
Me.TXT_TO_DATE.Size = New System.Drawing.Size(142, 22)
|
||||||
|
Me.TXT_TO_DATE.TabIndex = 1
|
||||||
|
'
|
||||||
|
'OPT_INT
|
||||||
|
'
|
||||||
|
Me.OPT_INT.AutoSize = True
|
||||||
|
Me.OPT_INT.CheckAlign = System.Drawing.ContentAlignment.MiddleCenter
|
||||||
|
Me.OPT_INT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.OPT_INT.Location = New System.Drawing.Point(4, 4)
|
||||||
|
Me.OPT_INT.Name = "OPT_INT"
|
||||||
|
Me.OPT_INT.Size = New System.Drawing.Size(24, 19)
|
||||||
|
Me.OPT_INT.TabIndex = 0
|
||||||
|
Me.OPT_INT.TabStop = True
|
||||||
|
Me.OPT_INT.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'OPT_TIME
|
||||||
|
'
|
||||||
|
Me.OPT_TIME.AutoSize = True
|
||||||
|
Me.OPT_TIME.CheckAlign = System.Drawing.ContentAlignment.MiddleCenter
|
||||||
|
Me.OPT_TIME.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.OPT_TIME.Location = New System.Drawing.Point(4, 30)
|
||||||
|
Me.OPT_TIME.Name = "OPT_TIME"
|
||||||
|
Me.OPT_TIME.Size = New System.Drawing.Size(24, 19)
|
||||||
|
Me.OPT_TIME.TabIndex = 1
|
||||||
|
Me.OPT_TIME.TabStop = True
|
||||||
|
Me.OPT_TIME.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'TP_TIME_INT
|
||||||
|
'
|
||||||
|
Me.TP_TIME_INT.ColumnCount = 2
|
||||||
|
Me.TP_TIME_INT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||||
|
Me.TP_TIME_INT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||||
|
Me.TP_TIME_INT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||||
|
Me.TP_TIME_INT.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
|
||||||
|
Me.TP_TIME_INT.Controls.Add(Me.TXT_FROM_INT, 0, 0)
|
||||||
|
Me.TP_TIME_INT.Controls.Add(Me.TXT_TO_INT, 1, 0)
|
||||||
|
Me.TP_TIME_INT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TP_TIME_INT.Location = New System.Drawing.Point(32, 1)
|
||||||
|
Me.TP_TIME_INT.Margin = New System.Windows.Forms.Padding(0)
|
||||||
|
Me.TP_TIME_INT.Name = "TP_TIME_INT"
|
||||||
|
Me.TP_TIME_INT.RowCount = 1
|
||||||
|
Me.TP_TIME_INT.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
Me.TP_TIME_INT.Size = New System.Drawing.Size(295, 25)
|
||||||
|
Me.TP_TIME_INT.TabIndex = 2
|
||||||
|
'
|
||||||
|
'TXT_FROM_INT
|
||||||
|
'
|
||||||
|
Me.TXT_FROM_INT.CaptionPadding = New System.Windows.Forms.Padding(0, 0, 6, 0)
|
||||||
|
Me.TXT_FROM_INT.CaptionText = "From"
|
||||||
|
Me.TXT_FROM_INT.CaptionWidth = 40.0R
|
||||||
|
Me.TXT_FROM_INT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_FROM_INT.Location = New System.Drawing.Point(3, 3)
|
||||||
|
Me.TXT_FROM_INT.Name = "TXT_FROM_INT"
|
||||||
|
Me.TXT_FROM_INT.Size = New System.Drawing.Size(141, 22)
|
||||||
|
Me.TXT_FROM_INT.TabIndex = 0
|
||||||
|
'
|
||||||
|
'TXT_TO_INT
|
||||||
|
'
|
||||||
|
Me.TXT_TO_INT.CaptionPadding = New System.Windows.Forms.Padding(0, 0, 6, 0)
|
||||||
|
Me.TXT_TO_INT.CaptionText = "To"
|
||||||
|
Me.TXT_TO_INT.CaptionWidth = 40.0R
|
||||||
|
Me.TXT_TO_INT.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.TXT_TO_INT.Location = New System.Drawing.Point(150, 3)
|
||||||
|
Me.TXT_TO_INT.Name = "TXT_TO_INT"
|
||||||
|
Me.TXT_TO_INT.Size = New System.Drawing.Size(142, 22)
|
||||||
|
Me.TXT_TO_INT.TabIndex = 1
|
||||||
|
'
|
||||||
|
'TrimOptionForm
|
||||||
|
'
|
||||||
|
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
||||||
|
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
||||||
|
Me.ClientSize = New System.Drawing.Size(334, 112)
|
||||||
|
Me.Controls.Add(CONTAINER_MAIN)
|
||||||
|
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
|
||||||
|
Me.KeyPreview = True
|
||||||
|
Me.MaximizeBox = False
|
||||||
|
Me.MaximumSize = New System.Drawing.Size(350, 151)
|
||||||
|
Me.MinimizeBox = False
|
||||||
|
Me.MinimumSize = New System.Drawing.Size(350, 151)
|
||||||
|
Me.Name = "TrimOptionForm"
|
||||||
|
Me.ShowIcon = False
|
||||||
|
Me.ShowInTaskbar = False
|
||||||
|
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
|
||||||
|
Me.Text = "Trim option"
|
||||||
|
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.PerformLayout()
|
||||||
|
TP_MAIN.ResumeLayout(False)
|
||||||
|
CType(Me.TXT_NAME, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
|
TP_OPTIONS.ResumeLayout(False)
|
||||||
|
TP_OPTIONS.PerformLayout()
|
||||||
|
Me.TP_TIME_TIME.ResumeLayout(False)
|
||||||
|
CType(Me.TXT_FROM_DATE, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
|
CType(Me.TXT_TO_DATE, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
|
Me.TP_TIME_INT.ResumeLayout(False)
|
||||||
|
CType(Me.TXT_FROM_INT, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
|
CType(Me.TXT_TO_INT, System.ComponentModel.ISupportInitialize).EndInit()
|
||||||
|
Me.ResumeLayout(False)
|
||||||
|
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private WithEvents TXT_NAME As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
|
Private WithEvents OPT_INT As RadioButton
|
||||||
|
Private WithEvents OPT_TIME As RadioButton
|
||||||
|
Private WithEvents TP_TIME_INT As TableLayoutPanel
|
||||||
|
Private WithEvents TP_TIME_TIME As TableLayoutPanel
|
||||||
|
Private WithEvents TXT_FROM_DATE As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
|
Private WithEvents TXT_TO_DATE As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
|
Private WithEvents TXT_FROM_INT As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
|
Private WithEvents TXT_TO_INT As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
138
SCrawler.YouTube/Controls/TrimOptionForm.resx
Normal file
138
SCrawler.YouTube/Controls/TrimOptionForm.resx
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<metadata name="CONTAINER_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="TP_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||||
|
<data name="ActionButton1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
|
vgAADr4B6kKxwAAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<metadata name="TP_OPTIONS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
</root>
|
||||||
79
SCrawler.YouTube/Controls/TrimOptionForm.vb
Normal file
79
SCrawler.YouTube/Controls/TrimOptionForm.vb
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports PersonalUtilities.Forms
|
||||||
|
Imports PersonalUtilities.Forms.Toolbars
|
||||||
|
Imports SCrawler.API.YouTube.Base
|
||||||
|
Namespace API.YouTube.Controls
|
||||||
|
Friend Class TrimOptionForm
|
||||||
|
Private WithEvents MyDefs As DefaultFormOptions
|
||||||
|
Friend Property MyTrimOption As TrimOption
|
||||||
|
Private ReadOnly FieldsDateProvider As New CustomProvider(Function(v) AConvert(Of TimeSpan)(v, Nothing, EDP.ReturnValue))
|
||||||
|
Private ReadOnly TCE As New ErrorsDescriber(False, False, False, New TimeSpan)
|
||||||
|
Friend Sub New(Optional ByVal Opt As TrimOption = Nothing)
|
||||||
|
InitializeComponent()
|
||||||
|
MyDefs = New DefaultFormOptions(Me, MyYouTubeSettings.DesignXml)
|
||||||
|
MyTrimOption = Opt
|
||||||
|
End Sub
|
||||||
|
Private Sub TrimOptionForm_Load(sender As Object, e As EventArgs) Handles Me.Load
|
||||||
|
Try
|
||||||
|
With MyDefs
|
||||||
|
.MyViewInitialize()
|
||||||
|
.AddOkCancelToolbar()
|
||||||
|
|
||||||
|
TXT_NAME.Text = MyTrimOption.Name
|
||||||
|
TXT_FROM_INT.Text = MyTrimOption.Start
|
||||||
|
TXT_TO_INT.Text = MyTrimOption.End
|
||||||
|
|
||||||
|
OPT_INT.Checked = True
|
||||||
|
|
||||||
|
.MyFieldsCheckerE = New FieldsChecker
|
||||||
|
With .MyFieldsCheckerE
|
||||||
|
.AddControl(Of Integer)(TXT_FROM_INT, "From")
|
||||||
|
.AddControl(Of Integer)(TXT_TO_INT, "To")
|
||||||
|
.AddControl(Of String)(TXT_FROM_DATE, "From (time)",, FieldsDateProvider)
|
||||||
|
.AddControl(Of String)(TXT_TO_DATE, "To (time)",, FieldsDateProvider)
|
||||||
|
.EndLoaderOperations()
|
||||||
|
End With
|
||||||
|
|
||||||
|
.EndLoaderOperations()
|
||||||
|
End With
|
||||||
|
Catch ex As Exception
|
||||||
|
MyDefs.InvokeLoaderError(ex)
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
|
||||||
|
If MyDefs.MyFieldsChecker.AllParamsOK Then
|
||||||
|
MyTrimOption = New TrimOption With {
|
||||||
|
.Name = TXT_NAME.Text,
|
||||||
|
.Start = AConvert(Of Integer)(TXT_FROM_INT.Text, 0),
|
||||||
|
.[End] = AConvert(Of Integer)(TXT_TO_INT.Text, 0)
|
||||||
|
}
|
||||||
|
MyDefs.CloseForm()
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
Private Sub OPT_INT_TIME_CheckedChanged(sender As Object, e As EventArgs) Handles OPT_INT.CheckedChanged, OPT_TIME.CheckedChanged
|
||||||
|
TP_TIME_INT.Enabled = OPT_INT.Checked
|
||||||
|
TP_TIME_TIME.Enabled = OPT_TIME.Checked
|
||||||
|
End Sub
|
||||||
|
Private _TextHandlersEnabled As Boolean = True
|
||||||
|
Private Sub TXT_FROM_TO_TextChanged(sender As Object, e As EventArgs) Handles TXT_FROM_INT.ActionOnTextChanged, TXT_TO_INT.ActionOnTextChanged,
|
||||||
|
TXT_FROM_DATE.ActionOnTextChanged, TXT_TO_DATE.ActionOnTextChanged
|
||||||
|
If _TextHandlersEnabled Then
|
||||||
|
_TextHandlersEnabled = False
|
||||||
|
Select Case DirectCast(sender, Control).Name
|
||||||
|
Case TXT_FROM_INT.Name : TXT_FROM_DATE.Value = AConvert(Of String)(TimeSpan.FromSeconds(AConvert(Of Integer)(TXT_FROM_INT.Text, 0)), TimeToStringProviderH)
|
||||||
|
Case TXT_TO_INT.Name : TXT_TO_DATE.Value = AConvert(Of String)(TimeSpan.FromSeconds(AConvert(Of Integer)(TXT_TO_INT.Text, 0)), TimeToStringProviderH)
|
||||||
|
Case TXT_FROM_DATE.Name : TXT_FROM_INT.Text = CInt(CType(AConvert(Of TimeSpan)(TXT_FROM_DATE.Text, TCE), TimeSpan).TotalSeconds)
|
||||||
|
Case TXT_TO_DATE.Name : TXT_TO_INT.Text = CInt(CType(AConvert(Of TimeSpan)(TXT_TO_DATE.Text, TCE), TimeSpan).TotalSeconds)
|
||||||
|
End Select
|
||||||
|
_TextHandlersEnabled = True
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
@@ -73,6 +73,7 @@ Namespace API.YouTube.Controls
|
|||||||
Me.OPT_VIDEO = New System.Windows.Forms.RadioButton()
|
Me.OPT_VIDEO = New System.Windows.Forms.RadioButton()
|
||||||
Me.OPT_AUDIO = New System.Windows.Forms.RadioButton()
|
Me.OPT_AUDIO = New System.Windows.Forms.RadioButton()
|
||||||
Me.LBL_AUDIO_CODEC = New System.Windows.Forms.Label()
|
Me.LBL_AUDIO_CODEC = New System.Windows.Forms.Label()
|
||||||
|
Me.BTT_TRIM = New System.Windows.Forms.Button()
|
||||||
Me.TXT_FPS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
Me.TXT_FPS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
Me.TXT_AUDIO_BITRATE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
Me.TXT_AUDIO_BITRATE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
|
||||||
Me.TP_HEADER_BASE = New System.Windows.Forms.TableLayoutPanel()
|
Me.TP_HEADER_BASE = New System.Windows.Forms.TableLayoutPanel()
|
||||||
@@ -545,20 +546,32 @@ Namespace API.YouTube.Controls
|
|||||||
Me.LBL_AUDIO_CODEC.TextAlign = System.Drawing.ContentAlignment.MiddleRight
|
Me.LBL_AUDIO_CODEC.TextAlign = System.Drawing.ContentAlignment.MiddleRight
|
||||||
TT_MAIN.SetToolTip(Me.LBL_AUDIO_CODEC, "Output Audio Codec")
|
TT_MAIN.SetToolTip(Me.LBL_AUDIO_CODEC, "Output Audio Codec")
|
||||||
'
|
'
|
||||||
|
'BTT_TRIM
|
||||||
|
'
|
||||||
|
Me.BTT_TRIM.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.BTT_TRIM.Location = New System.Drawing.Point(541, 3)
|
||||||
|
Me.BTT_TRIM.Name = "BTT_TRIM"
|
||||||
|
Me.BTT_TRIM.Size = New System.Drawing.Size(45, 22)
|
||||||
|
Me.BTT_TRIM.TabIndex = 2
|
||||||
|
Me.BTT_TRIM.Text = "Trim"
|
||||||
|
TT_MAIN.SetToolTip(Me.BTT_TRIM, "Trim the file by setting trimming options and/or selecting chapters")
|
||||||
|
Me.BTT_TRIM.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
'TP_FPS_BITRATE
|
'TP_FPS_BITRATE
|
||||||
'
|
'
|
||||||
TP_FPS_BITRATE.ColumnCount = 2
|
TP_FPS_BITRATE.ColumnCount = 3
|
||||||
TP_FPS_BITRATE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
TP_FPS_BITRATE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||||
TP_FPS_BITRATE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
TP_FPS_BITRATE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
|
||||||
|
TP_FPS_BITRATE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 51.0!))
|
||||||
TP_FPS_BITRATE.Controls.Add(Me.TXT_FPS, 0, 0)
|
TP_FPS_BITRATE.Controls.Add(Me.TXT_FPS, 0, 0)
|
||||||
TP_FPS_BITRATE.Controls.Add(Me.TXT_AUDIO_BITRATE, 1, 0)
|
TP_FPS_BITRATE.Controls.Add(Me.TXT_AUDIO_BITRATE, 1, 0)
|
||||||
|
TP_FPS_BITRATE.Controls.Add(Me.BTT_TRIM, 2, 0)
|
||||||
TP_FPS_BITRATE.Dock = System.Windows.Forms.DockStyle.Fill
|
TP_FPS_BITRATE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
TP_FPS_BITRATE.Location = New System.Drawing.Point(6, 93)
|
TP_FPS_BITRATE.Location = New System.Drawing.Point(6, 93)
|
||||||
TP_FPS_BITRATE.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0)
|
TP_FPS_BITRATE.Margin = New System.Windows.Forms.Padding(6, 0, 6, 0)
|
||||||
TP_FPS_BITRATE.Name = "TP_FPS_BITRATE"
|
TP_FPS_BITRATE.Name = "TP_FPS_BITRATE"
|
||||||
TP_FPS_BITRATE.RowCount = 1
|
TP_FPS_BITRATE.RowCount = 1
|
||||||
TP_FPS_BITRATE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
TP_FPS_BITRATE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
TP_FPS_BITRATE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
|
|
||||||
TP_FPS_BITRATE.Size = New System.Drawing.Size(589, 28)
|
TP_FPS_BITRATE.Size = New System.Drawing.Size(589, 28)
|
||||||
TP_FPS_BITRATE.TabIndex = 6
|
TP_FPS_BITRATE.TabIndex = 6
|
||||||
'
|
'
|
||||||
@@ -577,7 +590,7 @@ Namespace API.YouTube.Controls
|
|||||||
Me.TXT_FPS.Location = New System.Drawing.Point(3, 2)
|
Me.TXT_FPS.Location = New System.Drawing.Point(3, 2)
|
||||||
Me.TXT_FPS.Margin = New System.Windows.Forms.Padding(3, 2, 3, 3)
|
Me.TXT_FPS.Margin = New System.Windows.Forms.Padding(3, 2, 3, 3)
|
||||||
Me.TXT_FPS.Name = "TXT_FPS"
|
Me.TXT_FPS.Name = "TXT_FPS"
|
||||||
Me.TXT_FPS.Size = New System.Drawing.Size(288, 22)
|
Me.TXT_FPS.Size = New System.Drawing.Size(263, 22)
|
||||||
Me.TXT_FPS.TabIndex = 0
|
Me.TXT_FPS.TabIndex = 0
|
||||||
Me.TXT_FPS.TextBoxWidthMinimal = 30
|
Me.TXT_FPS.TextBoxWidthMinimal = 30
|
||||||
'
|
'
|
||||||
@@ -593,9 +606,9 @@ Namespace API.YouTube.Controls
|
|||||||
" to change."
|
" to change."
|
||||||
Me.TXT_AUDIO_BITRATE.CaptionWidth = 75.0R
|
Me.TXT_AUDIO_BITRATE.CaptionWidth = 75.0R
|
||||||
Me.TXT_AUDIO_BITRATE.Dock = System.Windows.Forms.DockStyle.Fill
|
Me.TXT_AUDIO_BITRATE.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
Me.TXT_AUDIO_BITRATE.Location = New System.Drawing.Point(297, 3)
|
Me.TXT_AUDIO_BITRATE.Location = New System.Drawing.Point(272, 3)
|
||||||
Me.TXT_AUDIO_BITRATE.Name = "TXT_AUDIO_BITRATE"
|
Me.TXT_AUDIO_BITRATE.Name = "TXT_AUDIO_BITRATE"
|
||||||
Me.TXT_AUDIO_BITRATE.Size = New System.Drawing.Size(289, 22)
|
Me.TXT_AUDIO_BITRATE.Size = New System.Drawing.Size(263, 22)
|
||||||
Me.TXT_AUDIO_BITRATE.TabIndex = 1
|
Me.TXT_AUDIO_BITRATE.TabIndex = 1
|
||||||
'
|
'
|
||||||
'TP_HEADER_BASE
|
'TP_HEADER_BASE
|
||||||
@@ -920,5 +933,6 @@ Namespace API.YouTube.Controls
|
|||||||
Private WithEvents CMB_PLS As PersonalUtilities.Forms.Controls.ComboBoxExtended
|
Private WithEvents CMB_PLS As PersonalUtilities.Forms.Controls.ComboBoxExtended
|
||||||
Private WithEvents BTT_PLS_BROWSE As SCrawler.API.YouTube.Controls.ButtonRC
|
Private WithEvents BTT_PLS_BROWSE As SCrawler.API.YouTube.Controls.ButtonRC
|
||||||
Private WithEvents TXT_AUDIO_BITRATE As PersonalUtilities.Forms.Controls.TextBoxExtended
|
Private WithEvents TXT_AUDIO_BITRATE As PersonalUtilities.Forms.Controls.TextBoxExtended
|
||||||
|
Private WithEvents BTT_TRIM As Button
|
||||||
End Class
|
End Class
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -139,98 +139,96 @@
|
|||||||
<data name="ActionButton1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
wwAADsMBx2+oZAAAAFFJREFUOE9joAr49u3bf1Lw169f50O1QgBI0MnJCY4/vP8Ix8hiILqtrQ3TEFIM
|
vAAADrwBlbxySQAAAEhJREFUOE9jYKAG+Pbt239S8NevX+djGODk5ATHH95/hGNkMRDd1taGaQgpBiAb
|
||||||
AGGYIVDtpBsAwkQbgIyR1dDWAGLwqAGD0gByMFQ7JYCBAQChNviRiQ8ETwAAAABJRU5ErkJggg==
|
QrYBIEy0AdgMo70BxOBRAwalAeRguAGUAAChNviRcuLCdwAAAABJRU5ErkJggg==
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton2.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE65JREFUeF7t
|
iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE0xJREFUeF7t
|
||||||
3X2sJWddB/DdLi2lQG2hdOHuvfM887J7Cxca4ELTQMDWKigIFpBAEAgi9g+CJpJo9Q8NJhgBiYZIYspL
|
3X2MZWddB/BZSkspUFsoXZidOc/vnOfsTmGgARaaBgK2VkFBsIAEgkAQsX8QNJFEq39oMMEoSDREElOB
|
||||||
GlAKCkhEC4KgQlsLQkqhKi/lrYWWlxaw3dLddrerz/Q89+7dc2fbfTn3npf5fJJv2rS758z85nnOzJz5
|
EFAKCkhEAUGqQlsLQkoBlZfy1kJ5awH7QrvtbldzdndmZ597Snd37szce8/nk3xTQjsz5/zOefbO3vO9
|
||||||
nZktAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
58zNAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
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
|
||||||
k/LT6hD+Mu2oR/4rgXTW/+X02r+U3woAmDTtz/GaIv5F2nH/ZHhHfpS5J+Vf01n/S9LLbhu8OgAw0dpb
|
mQO/EFTVctfezxEXtlX9vLaqX9z9s6mqC5YWF+fLrwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
8TYL5XPTmfvb0o78v/MOvWtHvybtzXzKT1Qx/n5d1wv5pQCAaXXvAUFRLLXd+3WMFzZF+cKUl7X/rIri
|
|
||||||
gsWFhbn8RwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6LEtW/4flgYiLD1qeX0A
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAASUVORK5CYII=
|
AAAAAAAAAAAAYIj+H5YGIizEb/aEAAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<metadata name="TT_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="TT_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
@@ -248,115 +246,113 @@
|
|||||||
<data name="ActionButton3.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton3.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
wwAADsMBx2+oZAAAAFFJREFUOE9joAr49u3bf1Lw169f50O1QgBI0MnJCY4/vP8Ix8hiILqtrQ3TEFIM
|
vAAADrwBlbxySQAAAEhJREFUOE9jYKAG+Pbt239S8NevX+djGODk5ATHH95/hGNkMRDd1taGaQgpBiAb
|
||||||
AGGYIVDtpBsAwkQbgIyR1dDWAGLwqAGD0gByMFQ7JYCBAQChNviRiQ8ETwAAAABJRU5ErkJggg==
|
QrYBIEy0AdgMo70BxOBRAwalAeRguAGUAAChNviRcuLCdwAAAABJRU5ErkJggg==
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton4.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton4.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
|
||||||
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAeElE
|
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAAAd0lE
|
||||||
QVQ4T2P4//8/RRhMFHQfKgDi/yAaXQEhDCZAmkNbnvyXta4CciESLEws//FhmDqYAQUgzUBMngsowVgF
|
QVQ4T2P4//8/AyUYTBR0Hyoo6D70H0SjKyCEYQb8D2158l/Wuuo/TIKFieU/PoxuQAFIs6x1FXkuoARj
|
||||||
ScFgYjQQsUsQi8FEYsXyAiD+D6LRFRDCYAKk2bPo6H9J40wgFyKBLeCQMUwdzIACkGYgHnKB+J8BAD5Q
|
CJCKwcRoIGIKkoLBRGLF8oLEiuX/QTS6AkIYZsB/z6Kj/yWNM8kLRJDNIM2SxpnkuYASjCFAKgYAPlC2
|
||||||
tqhi4tzWAAAAAElFTkSuQmCC
|
qCS4LQgAAAAASUVORK5CYII=
|
||||||
</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>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
vAAADrwBlbxySQAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton6.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton6.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE65JREFUeF7t
|
iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE0xJREFUeF7t
|
||||||
3X2sJWddB/DdLi2lQG2hdOHuvfM887J7Cxca4ELTQMDWKigIFpBAEAgi9g+CJpJo9Q8NJhgBiYZIYspL
|
3X2MZWddB/BZSkspUFsoXZidOc/vnOfsTmGgARaaBgK2VkFBsIAEgkAQsX8QNJFEq39oMMEoSDREElOB
|
||||||
GlAKCkhEC4KgQlsLQkqhKi/lrYWWlxaw3dLddrerz/Q89+7dc2fbfTn3npf5fJJv2rS758z85nnOzJz5
|
EFAKCkhEAUGqQlsLQkoBlZfy1kJ5awH7QrvtbldzdndmZ597Snd37szce8/nk3xTQjsz5/zOefbO3vO9
|
||||||
nZktAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
58zNAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
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
|
||||||
k/LT6hD+Mu2oR/4rgXTW/+X02r+U3woAmDTtz/GaIv5F2nH/ZHhHfpS5J+Vf01n/S9LLbhu8OgAw0dpb
|
mQO/EFTVctfezxEXtlX9vLaqX9z9s6mqC5YWF+fLrwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
8TYL5XPTmfvb0o78v/MOvWtHvybtzXzKT1Qx/n5d1wv5pQCAaXXvAUFRLLXd+3WMFzZF+cKUl7X/rIri
|
|
||||||
gsWFhbn8RwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6LEtW/4flgYiLD1qeX0A
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAASUVORK5CYII=
|
AAAAAAAAAAAAYIj+H5YGIizEb/aEAAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<metadata name="LB_SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="LB_SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
@@ -383,122 +379,122 @@
|
|||||||
<data name="ActionButton7.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/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
vAAADrwBlbxySQAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton8.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
|
vAAADrwBlbxySQAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton9.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
|
vAAADrwBlbxySQAAARlJREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbWujg3dATZPKYZC6BQhvw1AMkg3dP
|
||||||
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
|
XQyl7WIyJIEW5CbS0/jKE5GwpCghgg9s6/8/y5Kj6DA45zcAwAAAezB6rjNnB4XX244NHt8wGs7wblop
|
||||||
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
|
yRGxwZQBYKIfbn477EvqusY4jj2MgMpPiwav7l9UyYXmdrs9duzP4ApUmd72sfrxVsD33JQISyClvFUX
|
||||||
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
|
w9nJssvJFei9CJUtgQ7394Du3YKLJaCbLMuwqips21ZNuDve/35X8J7nuRcMsVwsbYEQYlSWpRcMMR5P
|
||||||
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
|
bAH9fU3TeMEQSZLYgsMpsDRNvXCIr89vWyCEeC6KwguGmL/ObYGU8oFOwA2ewwgYY9f6f7iUf3DGkTcu
|
||||||
cMaRN0UdBBkAAAAASUVORK5CYII=
|
khP7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton10.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>
|
||||||
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
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton11.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
|
vAAADrwBlbxySQAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton12.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton12.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
|
vAAADrwBlbxySQAAARlJREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbWujg3dATZPKYZC6BQhvw1AMkg3dP
|
||||||
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
|
XQyl7WIyJIEW5CbS0/jKE5GwpCghgg9s6/8/y5Kj6DA45zcAwAAAezB6rjNnB4XX244NHt8wGs7wblop
|
||||||
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
|
yRGxwZQBYKIfbn477EvqusY4jj2MgMpPiwav7l9UyYXmdrs9duzP4ApUmd72sfrxVsD33JQISyClvFUX
|
||||||
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
|
w9nJssvJFei9CJUtgQ7394Du3YKLJaCbLMuwqips21ZNuDve/35X8J7nuRcMsVwsbYEQYlSWpRcMMR5P
|
||||||
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
|
bAH9fU3TeMEQSZLYgsMpsDRNvXCIr89vWyCEeC6KwguGmL/ObYGU8oFOwA2ewwgYY9f6f7iUf3DGkTcu
|
||||||
cMaRN0UdBBkAAAAASUVORK5CYII=
|
khP7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton13.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton13.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+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAACM0lE
|
||||||
QVQ4T2P4//8/QczOJyyqHpzfiE0OQwAZC8iqszAzs7CJ69o4BR768V/W2jcGXQ0KB4aFNS3dDQtnrbCb
|
QVQ4T2P4//8/AyHMzicsqh6c34guDsIYAshYQFadhZmZhU1c18Yp8NCP/7LWvjHoajA0gbCwpqW7YeGs
|
||||||
ePCK48wTN1wXXXzge/jXf/clV55zC4hIIatF0cjIyMikElzc57z0wX+XHd/+2+//99/ywP//xlu//tdb
|
FXYTD15xnHnihuuiiw98D//6777kynNuAREpnAYwMjIyqQQX9zkvffDfZce3//b7//23PPD/v/HWr//1
|
||||||
+eK/4Zp3/1WTOhYzARViNUAluKjTdf37/0ZTTn9TbdhwXblhwwW1/qOP1Ja9+K8w+95/6cm3/6v2Xvkv
|
Vr74b7jm3X/VpI7FTIyMjFgNUAku6nRd//6/0ZTT31QbNlxXbthwQa3/6CO1ZS/+K8y+91968u3/qr1X
|
||||||
qKjniGGAoIqRpW3/4e8S9uGdzFz82gwMDFxAzCxm4ZegtuLDf+VJ1/8rZM25IqLvnM/CximCYYCic1QN
|
/gsq6jliGCCoYmRp23/4u4R9eCczF782AwMDFwMDA7OYhV+C2ooP/5UnXf+vkDXnioi+cz4LG6cIhgGK
|
||||||
v7x2JIwPwyrJ3XNUylddE9G2TWNmZOBDl4czmJiZMSRBmFdSyYyJgUEQmxwIYxWEYXZBCUls4sgYq6CA
|
zlE1/PLakcguArsquXuOSvmqayLatmnMjAx86PJwBhMzM4YkCPNKKpkxMTAIootjGIANswtKSKKLoWMM
|
||||||
prWNbtG8nXKeaVPR5XiVjSxEzf0yYXy4BBMLO6eQjoOXZvrkbbazrv53Xf/2v4CSbjBMXkhBl1/CMyNZ
|
ARAW0LS20S2at1POM20quhyvspGFqLlfJoYBTCzsnEI6Dl6a6ZO32c66+t91/dv/Akq6wTB5IQVdfgnP
|
||||||
qWnvGy5pNQ+YONwAfjXzAOupl/47LLr333L50/96q9/8l23YdES6cO5KuYqVW+R7Tj6SnfP0v4hryjyY
|
jGSlpr1vuKTVPDAM4FczD7Ceeum/w6J7/y2XP/2vt/rNf9mGTUekC+eulKtYuUW+5+Qj2TlP/4u4psxD
|
||||||
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
|
dhGSC9h4dUoWntZf9e6/0qr3/5V3/Puvuu//f6Xt///Lrvr8X3ryzf8SfsWbmNBiAsV/bJIqpkpLX/xU
|
||||||
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
|
2/n3v+qcmx9VZl77oth97L1U2pQTgtq2WUwMDGzI6jEMAGFR/7wGzS3f//PIagawcvIqsLJzKTAyMLCi
|
||||||
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
|
q8NpABMLK4dCfOsSZlYOUXQ5bBgArRReBMoH61gAAAAASUVORK5CYII=
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton14.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton14.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
|
vAAADrwBlbxySQAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton15.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton15.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
|
vAAADrwBlbxySQAAARlJREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbWujg3dATZPKYZC6BQhvw1AMkg3dP
|
||||||
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
|
XQyl7WIyJIEW5CbS0/jKE5GwpCghgg9s6/8/y5Kj6DA45zcAwAAAezB6rjNnB4XX244NHt8wGs7wblop
|
||||||
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
|
yRGxwZQBYKIfbn477EvqusY4jj2MgMpPiwav7l9UyYXmdrs9duzP4ApUmd72sfrxVsD33JQISyClvFUX
|
||||||
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
|
w9nJssvJFei9CJUtgQ7394Du3YKLJaCbLMuwqips21ZNuDve/35X8J7nuRcMsVwsbYEQYlSWpRcMMR5P
|
||||||
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
|
bAH9fU3TeMEQSZLYgsMpsDRNvXCIr89vWyCEeC6KwguGmL/ObYGU8oFOwA2ewwgYY9f6f7iUf3DGkTcu
|
||||||
cMaRN0UdBBkAAAAASUVORK5CYII=
|
khP7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton16.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton16.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
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
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ActionButton17.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="ActionButton17.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
|
||||||
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
|
vAAADrwBlbxySQAAAHpJREFUOE+1kVEKgDAMQ3e2/e+MXqpn6W/HxM7SpkIVB4HxSMKiTUTaFwVQ1X25
|
||||||
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
|
DjMfSxskHBYsAxHJkjUjHgrUNMY4peaMPxb03rcZMVhgn2oDKAwn+L0aROH/Cny4NAGFSx8x+10ZDwV2
|
||||||
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
|
gt+LOCxQsw1nPBS8VQBVTTzyhrdZSUm7AAAAAElFTkSuQmCC
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -465,6 +465,9 @@ Namespace API.YouTube.Controls
|
|||||||
TXT_FILE.Text = f
|
TXT_FILE.Text = f
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Sub BTT_TRIM_Click(sender As Object, e As EventArgs) Handles BTT_TRIM.Click
|
||||||
|
Using f As New VideoOptionsTrimForm(MyContainer) : f.ShowDialog() : End Using
|
||||||
|
End Sub
|
||||||
Private Sub TXT_SUBS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_SUBS.ActionOnButtonClick
|
Private Sub TXT_SUBS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_SUBS.ActionOnButtonClick
|
||||||
Select Case Sender.DefaultButton
|
Select Case Sender.DefaultButton
|
||||||
Case ADB.Open
|
Case ADB.Open
|
||||||
|
|||||||
166
SCrawler.YouTube/Controls/VideoOptionsTrimForm.Designer.vb
generated
Normal file
166
SCrawler.YouTube/Controls/VideoOptionsTrimForm.Designer.vb
generated
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Namespace API.YouTube.Controls
|
||||||
|
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
|
||||||
|
Partial Friend Class VideoOptionsTrimForm : Inherits System.Windows.Forms.Form
|
||||||
|
<System.Diagnostics.DebuggerNonUserCode()>
|
||||||
|
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
|
||||||
|
Try
|
||||||
|
If disposing AndAlso components IsNot Nothing Then
|
||||||
|
components.Dispose()
|
||||||
|
End If
|
||||||
|
Finally
|
||||||
|
MyBase.Dispose(disposing)
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
Private components As System.ComponentModel.IContainer
|
||||||
|
<System.Diagnostics.DebuggerStepThrough()>
|
||||||
|
Private Sub InitializeComponent()
|
||||||
|
Me.components = New System.ComponentModel.Container()
|
||||||
|
Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
|
||||||
|
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
|
||||||
|
Dim TP_OPTIONS As System.Windows.Forms.TableLayoutPanel
|
||||||
|
Dim TT_MAIN As System.Windows.Forms.ToolTip
|
||||||
|
Me.LIST_TRIM = New System.Windows.Forms.ListBox()
|
||||||
|
Me.CH_DEL_ORIG = New System.Windows.Forms.CheckBox()
|
||||||
|
Me.CH_ADD_M3U8 = New System.Windows.Forms.CheckBox()
|
||||||
|
Me.CH_SEP_FOLDER = New System.Windows.Forms.CheckBox()
|
||||||
|
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
|
||||||
|
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
TP_OPTIONS = New System.Windows.Forms.TableLayoutPanel()
|
||||||
|
TT_MAIN = New System.Windows.Forms.ToolTip(Me.components)
|
||||||
|
CONTAINER_MAIN.ContentPanel.SuspendLayout()
|
||||||
|
CONTAINER_MAIN.SuspendLayout()
|
||||||
|
TP_MAIN.SuspendLayout()
|
||||||
|
TP_OPTIONS.SuspendLayout()
|
||||||
|
Me.SuspendLayout()
|
||||||
|
'
|
||||||
|
'CONTAINER_MAIN
|
||||||
|
'
|
||||||
|
'
|
||||||
|
'CONTAINER_MAIN.ContentPanel
|
||||||
|
'
|
||||||
|
CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
|
||||||
|
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(434, 236)
|
||||||
|
CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
CONTAINER_MAIN.LeftToolStripPanelVisible = False
|
||||||
|
CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||||
|
CONTAINER_MAIN.Name = "CONTAINER_MAIN"
|
||||||
|
CONTAINER_MAIN.RightToolStripPanelVisible = False
|
||||||
|
CONTAINER_MAIN.Size = New System.Drawing.Size(434, 261)
|
||||||
|
CONTAINER_MAIN.TabIndex = 0
|
||||||
|
'
|
||||||
|
'TP_MAIN
|
||||||
|
'
|
||||||
|
TP_MAIN.ColumnCount = 1
|
||||||
|
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_MAIN.Controls.Add(Me.LIST_TRIM, 0, 1)
|
||||||
|
TP_MAIN.Controls.Add(TP_OPTIONS, 0, 0)
|
||||||
|
TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
TP_MAIN.Location = New System.Drawing.Point(0, 0)
|
||||||
|
TP_MAIN.Name = "TP_MAIN"
|
||||||
|
TP_MAIN.RowCount = 2
|
||||||
|
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30.0!))
|
||||||
|
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_MAIN.Size = New System.Drawing.Size(434, 236)
|
||||||
|
TP_MAIN.TabIndex = 0
|
||||||
|
'
|
||||||
|
'LIST_TRIM
|
||||||
|
'
|
||||||
|
Me.LIST_TRIM.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.LIST_TRIM.FormattingEnabled = True
|
||||||
|
Me.LIST_TRIM.Location = New System.Drawing.Point(3, 33)
|
||||||
|
Me.LIST_TRIM.Name = "LIST_TRIM"
|
||||||
|
Me.LIST_TRIM.Size = New System.Drawing.Size(428, 200)
|
||||||
|
Me.LIST_TRIM.TabIndex = 0
|
||||||
|
'
|
||||||
|
'TP_OPTIONS
|
||||||
|
'
|
||||||
|
TP_OPTIONS.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
|
||||||
|
TP_OPTIONS.ColumnCount = 3
|
||||||
|
TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333!))
|
||||||
|
TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33334!))
|
||||||
|
TP_OPTIONS.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33334!))
|
||||||
|
TP_OPTIONS.Controls.Add(Me.CH_DEL_ORIG, 0, 0)
|
||||||
|
TP_OPTIONS.Controls.Add(Me.CH_ADD_M3U8, 1, 0)
|
||||||
|
TP_OPTIONS.Controls.Add(Me.CH_SEP_FOLDER, 2, 0)
|
||||||
|
TP_OPTIONS.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
TP_OPTIONS.Location = New System.Drawing.Point(3, 3)
|
||||||
|
TP_OPTIONS.Name = "TP_OPTIONS"
|
||||||
|
TP_OPTIONS.RowCount = 1
|
||||||
|
TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
|
||||||
|
TP_OPTIONS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 23.0!))
|
||||||
|
TP_OPTIONS.Size = New System.Drawing.Size(428, 24)
|
||||||
|
TP_OPTIONS.TabIndex = 1
|
||||||
|
'
|
||||||
|
'CH_DEL_ORIG
|
||||||
|
'
|
||||||
|
Me.CH_DEL_ORIG.AutoSize = True
|
||||||
|
Me.CH_DEL_ORIG.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CH_DEL_ORIG.Location = New System.Drawing.Point(4, 4)
|
||||||
|
Me.CH_DEL_ORIG.Name = "CH_DEL_ORIG"
|
||||||
|
Me.CH_DEL_ORIG.Size = New System.Drawing.Size(135, 16)
|
||||||
|
Me.CH_DEL_ORIG.TabIndex = 0
|
||||||
|
Me.CH_DEL_ORIG.Text = "Delete original file"
|
||||||
|
TT_MAIN.SetToolTip(Me.CH_DEL_ORIG, "If checked, the original file will be deleted after trimming")
|
||||||
|
Me.CH_DEL_ORIG.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'CH_ADD_M3U8
|
||||||
|
'
|
||||||
|
Me.CH_ADD_M3U8.AutoSize = True
|
||||||
|
Me.CH_ADD_M3U8.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CH_ADD_M3U8.Location = New System.Drawing.Point(146, 4)
|
||||||
|
Me.CH_ADD_M3U8.Name = "CH_ADD_M3U8"
|
||||||
|
Me.CH_ADD_M3U8.Size = New System.Drawing.Size(135, 16)
|
||||||
|
Me.CH_ADD_M3U8.TabIndex = 1
|
||||||
|
Me.CH_ADD_M3U8.Text = "Add to M3U8"
|
||||||
|
TT_MAIN.SetToolTip(Me.CH_ADD_M3U8, "If checked, the trimmed files will be added to the M3U8 playlist (if selected)")
|
||||||
|
Me.CH_ADD_M3U8.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'CH_SEP_FOLDER
|
||||||
|
'
|
||||||
|
Me.CH_SEP_FOLDER.AutoSize = True
|
||||||
|
Me.CH_SEP_FOLDER.Dock = System.Windows.Forms.DockStyle.Fill
|
||||||
|
Me.CH_SEP_FOLDER.Location = New System.Drawing.Point(288, 4)
|
||||||
|
Me.CH_SEP_FOLDER.Name = "CH_SEP_FOLDER"
|
||||||
|
Me.CH_SEP_FOLDER.Size = New System.Drawing.Size(136, 16)
|
||||||
|
Me.CH_SEP_FOLDER.TabIndex = 2
|
||||||
|
Me.CH_SEP_FOLDER.Text = "Separate folder"
|
||||||
|
TT_MAIN.SetToolTip(Me.CH_SEP_FOLDER, "Place the trimmed files in a separate folder")
|
||||||
|
Me.CH_SEP_FOLDER.UseVisualStyleBackColor = True
|
||||||
|
'
|
||||||
|
'VideoOptionsTrimForm
|
||||||
|
'
|
||||||
|
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
|
||||||
|
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
|
||||||
|
Me.ClientSize = New System.Drawing.Size(434, 261)
|
||||||
|
Me.Controls.Add(CONTAINER_MAIN)
|
||||||
|
Me.KeyPreview = True
|
||||||
|
Me.MinimizeBox = False
|
||||||
|
Me.MinimumSize = New System.Drawing.Size(450, 300)
|
||||||
|
Me.Name = "VideoOptionsTrimForm"
|
||||||
|
Me.ShowIcon = False
|
||||||
|
Me.ShowInTaskbar = False
|
||||||
|
Me.Text = "Trimming options"
|
||||||
|
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.ResumeLayout(False)
|
||||||
|
CONTAINER_MAIN.PerformLayout()
|
||||||
|
TP_MAIN.ResumeLayout(False)
|
||||||
|
TP_OPTIONS.ResumeLayout(False)
|
||||||
|
TP_OPTIONS.PerformLayout()
|
||||||
|
Me.ResumeLayout(False)
|
||||||
|
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private WithEvents LIST_TRIM As ListBox
|
||||||
|
Private WithEvents CH_DEL_ORIG As CheckBox
|
||||||
|
Private WithEvents CH_ADD_M3U8 As CheckBox
|
||||||
|
Private WithEvents CH_SEP_FOLDER As CheckBox
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
135
SCrawler.YouTube/Controls/VideoOptionsTrimForm.resx
Normal file
135
SCrawler.YouTube/Controls/VideoOptionsTrimForm.resx
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<metadata name="CONTAINER_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="TP_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="TP_OPTIONS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="TT_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="TT_MAIN.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>17, 17</value>
|
||||||
|
</metadata>
|
||||||
|
</root>
|
||||||
167
SCrawler.YouTube/Controls/VideoOptionsTrimForm.vb
Normal file
167
SCrawler.YouTube/Controls/VideoOptionsTrimForm.vb
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports PersonalUtilities.Forms
|
||||||
|
Imports PersonalUtilities.Forms.Toolbars
|
||||||
|
Imports SCrawler.API.YouTube.Objects
|
||||||
|
Imports SCrawler.API.YouTube.Base
|
||||||
|
Imports ETC = PersonalUtilities.Forms.Toolbars.EditToolbar.ControlItem
|
||||||
|
Namespace API.YouTube.Controls
|
||||||
|
Friend Class VideoOptionsTrimForm
|
||||||
|
#Region "Declarations"
|
||||||
|
Private WithEvents MyDefs As DefaultFormOptions
|
||||||
|
Private ReadOnly Property MyMedia As YouTubeMediaContainerBase
|
||||||
|
Private ReadOnly Property TrimData As List(Of TrimOption)
|
||||||
|
Private WithEvents BTT_CLEAR_ALL As ToolStripButton
|
||||||
|
Private WithEvents BTT_CHAPTERS As ToolStripButton
|
||||||
|
#End Region
|
||||||
|
#Region "Initializer"
|
||||||
|
Friend Sub New(ByRef Media As YouTubeMediaContainerBase)
|
||||||
|
InitializeComponent()
|
||||||
|
MyDefs = New DefaultFormOptions(Me, MyYouTubeSettings.DesignXml)
|
||||||
|
MyMedia = Media
|
||||||
|
TrimData = New List(Of TrimOption)
|
||||||
|
TrimData.ListAddList(Media.TrimOptions)
|
||||||
|
BTT_CLEAR_ALL = New ToolStripButton("Clear", PersonalUtilities.My.Resources.DeletePic_Red_24) With {
|
||||||
|
.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText,
|
||||||
|
.BackColor = MyColor.DeleteBack,
|
||||||
|
.ForeColor = MyColor.DeleteFore
|
||||||
|
}
|
||||||
|
BTT_CHAPTERS = New ToolStripButton("Chapters") With {.DisplayStyle = ToolStripItemDisplayStyle.Text, .Enabled = Media.Chapters.Count > 0}
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "Form handlers"
|
||||||
|
Private Sub VideoOptionsTrimForm_Load(sender As Object, e As EventArgs) Handles Me.Load
|
||||||
|
With MyDefs
|
||||||
|
.MyViewInitialize()
|
||||||
|
.AddOkCancelToolbar()
|
||||||
|
.AddEditToolbar({ETC.Add, ETC.Edit, ETC.Delete, BTT_CLEAR_ALL, ETC.Separator, BTT_CHAPTERS})
|
||||||
|
|
||||||
|
Refill()
|
||||||
|
|
||||||
|
With MyMedia
|
||||||
|
If Not .TrimOptionsSet Then
|
||||||
|
With MyYouTubeSettings
|
||||||
|
CH_DEL_ORIG.Checked = .TrimDeleteOriginalFile
|
||||||
|
CH_ADD_M3U8.Checked = .TrimAddTrimmedFilesToM3U8
|
||||||
|
CH_SEP_FOLDER.Checked = .TrimSeparateFolder
|
||||||
|
End With
|
||||||
|
Else
|
||||||
|
CH_DEL_ORIG.Checked = .TrimDeleteOriginalFile
|
||||||
|
CH_ADD_M3U8.Checked = .TrimAddTrimmedFilesToM3U8
|
||||||
|
CH_SEP_FOLDER.Checked = .TrimSeparateFolder
|
||||||
|
End If
|
||||||
|
End With
|
||||||
|
|
||||||
|
.EndLoaderOperations()
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
|
Private Sub VideoOptionsTrimForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
|
||||||
|
TrimData.Clear()
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "Refill"
|
||||||
|
Private Sub Refill(Optional ByVal DEL As Boolean = False)
|
||||||
|
Dim indx% = _CurrentIndex
|
||||||
|
With LIST_TRIM
|
||||||
|
.BeginUpdate()
|
||||||
|
.Items.Clear()
|
||||||
|
If TrimData.Count > 0 Then
|
||||||
|
TrimData.Sort()
|
||||||
|
.Items.AddRange(TrimData.Cast(Of Object).ToArray)
|
||||||
|
If DEL Then indx -= IIf(indx - 1 < 0, 0, 1)
|
||||||
|
If indx.ValueBetween(0, TrimData.Count - 1) Then
|
||||||
|
.SelectedIndex = indx
|
||||||
|
ElseIf (indx - 1).ValueBetween(0, TrimData.Count - 1) Then
|
||||||
|
.SelectedIndex = indx - 1
|
||||||
|
ElseIf (indx + 1).ValueBetween(0, TrimData.Count - 1) Then
|
||||||
|
.SelectedIndex = indx + 1
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
.EndUpdate()
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "Ok"
|
||||||
|
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
|
||||||
|
With MyMedia
|
||||||
|
.TrimOptions.Clear()
|
||||||
|
.TrimDeleteOriginalFile = CH_DEL_ORIG.Checked
|
||||||
|
.TrimAddTrimmedFilesToM3U8 = CH_ADD_M3U8.Checked
|
||||||
|
.TrimSeparateFolder = CH_SEP_FOLDER.Checked
|
||||||
|
.TrimOptionsSet = True
|
||||||
|
End With
|
||||||
|
|
||||||
|
If TrimData.Count > 0 Then
|
||||||
|
TrimData.Sort()
|
||||||
|
Dim indx% = 0
|
||||||
|
Dim c%
|
||||||
|
Dim opt As TrimOption
|
||||||
|
Dim dic As New Dictionary(Of String, Integer)
|
||||||
|
For i% = 0 To TrimData.Count - 1
|
||||||
|
opt = TrimData(i)
|
||||||
|
If opt.Name.IsEmptyString Then
|
||||||
|
indx += 1
|
||||||
|
opt.Name = indx
|
||||||
|
Else
|
||||||
|
c = TrimData.LongCount(Function(d) Not d.Name.IsEmptyString AndAlso d.Name = opt.Name)
|
||||||
|
If c > 1 Then
|
||||||
|
If Not dic.ContainsKey(opt.Name) Then dic.Add(opt.Name, 0)
|
||||||
|
dic(opt.Name) += 1
|
||||||
|
opt.Name &= $"_{dic(opt.Name)}"
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
TrimData(i) = opt
|
||||||
|
Next
|
||||||
|
dic.Clear()
|
||||||
|
MyMedia.TrimOptions.AddRange(TrimData)
|
||||||
|
End If
|
||||||
|
|
||||||
|
MyDefs.CloseForm()
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "Edit"
|
||||||
|
Private Sub MyDefs_ButtonAddClick(ByVal Sender As Object, ByVal e As EditToolbarEventArgs) Handles MyDefs.ButtonAddClick
|
||||||
|
Using f As New TrimOptionForm
|
||||||
|
f.ShowDialog()
|
||||||
|
If f.DialogResult = DialogResult.OK AndAlso
|
||||||
|
(TrimData.Count = 0 OrElse Not TrimData.Any(Function(t) t.End = f.MyTrimOption.End And t.Start = f.MyTrimOption.Start)) Then _
|
||||||
|
TrimData.Add(f.MyTrimOption) : Refill()
|
||||||
|
End Using
|
||||||
|
End Sub
|
||||||
|
Private Sub MyDefs_ButtonEditClick(ByVal Sender As Object, ByVal e As EditToolbarEventArgs) Handles MyDefs.ButtonEditClick
|
||||||
|
If _CurrentIndex.ValueBetween(0, TrimData.Count - 1) Then
|
||||||
|
Using f As New TrimOptionForm(TrimData(_CurrentIndex))
|
||||||
|
f.ShowDialog()
|
||||||
|
If f.DialogResult = DialogResult.OK Then TrimData(_CurrentIndex) = f.MyTrimOption : Refill()
|
||||||
|
End Using
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
Private Sub MyDefs_ButtonDeleteClickE(ByVal Sender As Object, ByVal e As EditToolbarEventArgs) Handles MyDefs.ButtonDeleteClickE
|
||||||
|
If _CurrentIndex.ValueBetween(0, TrimData.Count - 1) AndAlso
|
||||||
|
MsgBoxE({$"Are you sure you want to remove the following trim option?{vbCr}{vbCr}{TrimData(_CurrentIndex)}", "Remove trim option"}, vbYesNo + vbExclamation) = vbYes Then _
|
||||||
|
TrimData.RemoveAt(_CurrentIndex) : Refill(True)
|
||||||
|
End Sub
|
||||||
|
Private Sub BTT_CLEAR_ALL_Click(sender As Object, e As EventArgs) Handles BTT_CLEAR_ALL.Click
|
||||||
|
If MsgBoxE({$"Are you sure you want to remove ALL trim options?", "Remove trim option"}, vbYesNo + vbCritical) = vbYes Then TrimData.Clear() : Refill()
|
||||||
|
End Sub
|
||||||
|
Private Sub BTT_CHAPTERS_Click(sender As Object, e As EventArgs) Handles BTT_CHAPTERS.Click
|
||||||
|
Using f As New ChaptersForm(MyMedia, TrimData)
|
||||||
|
f.ShowDialog()
|
||||||
|
If f.DialogResult = DialogResult.OK AndAlso f.MyResult.Count > 0 Then TrimData.ListAddList(f.MyResult, LAP.NotContainsOnly) : Refill()
|
||||||
|
End Using
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
#Region "List"
|
||||||
|
Private _CurrentIndex As Integer = -1
|
||||||
|
Private Sub LIST_TRIM_SelectedIndexChanged(sender As Object, e As EventArgs) Handles LIST_TRIM.SelectedIndexChanged
|
||||||
|
_CurrentIndex = LIST_TRIM.SelectedIndex
|
||||||
|
End Sub
|
||||||
|
#End Region
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
@@ -54,6 +54,7 @@ Namespace API.YouTube
|
|||||||
Friend ReadOnly DateBaseProvider As New ADateTime(ADateTime.Formats.BaseDateTime)
|
Friend ReadOnly DateBaseProvider As New ADateTime(ADateTime.Formats.BaseDateTime)
|
||||||
Friend ReadOnly DateAddedProvider As New ADateTime(ADateTime.Formats.yyyymmdd) With {.DateSeparator = String.Empty}
|
Friend ReadOnly DateAddedProvider As New ADateTime(ADateTime.Formats.yyyymmdd) With {.DateSeparator = String.Empty}
|
||||||
Friend ReadOnly TimeToStringProvider As IFormatProvider = New TimeToStringConverter
|
Friend ReadOnly TimeToStringProvider As IFormatProvider = New TimeToStringConverter
|
||||||
|
Friend ReadOnly TimeToStringProviderH As IFormatProvider = New TimeToStringConverter(True)
|
||||||
Friend ReadOnly TitleHtmlConverter As Func(Of String, String) = Function(Input) Input.StringRemoveWinForbiddenSymbols().StringTrim()
|
Friend ReadOnly TitleHtmlConverter As Func(Of String, String) = Function(Input) Input.StringRemoveWinForbiddenSymbols().StringTrim()
|
||||||
Friend ReadOnly ProgressProvider As IMyProgressNumberProvider = MyProgressNumberProvider.Percentage
|
Friend ReadOnly ProgressProvider As IMyProgressNumberProvider = MyProgressNumberProvider.Percentage
|
||||||
Public ReadOnly TrueUrlRegEx As RParams = RParams.DM(Base.YouTubeFunctions.TrueUrlPattern, 0, EDP.ReturnValue)
|
Public ReadOnly TrueUrlRegEx As RParams = RParams.DM(Base.YouTubeFunctions.TrueUrlPattern, 0, EDP.ReturnValue)
|
||||||
@@ -80,11 +81,15 @@ Namespace API.YouTube
|
|||||||
Private Class TimeToStringConverter : Implements ICustomProvider
|
Private Class TimeToStringConverter : Implements ICustomProvider
|
||||||
Private ReadOnly _Provider As New ADateTime("mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan}
|
Private ReadOnly _Provider As New ADateTime("mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan}
|
||||||
Private ReadOnly _ProviderWithHours As New ADateTime("h\:mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan}
|
Private ReadOnly _ProviderWithHours As New ADateTime("h\:mm\:ss") With {.TimeParseMode = ADateTime.TimeModes.TimeSpan}
|
||||||
|
Private ReadOnly ForceHours As Boolean
|
||||||
Private ReadOnly Property Provider(ByVal t As TimeSpan) As IFormatProvider
|
Private ReadOnly Property Provider(ByVal t As TimeSpan) As IFormatProvider
|
||||||
Get
|
Get
|
||||||
Return If(t.Hours > 0, _ProviderWithHours, _Provider)
|
Return If(t.Hours > 0 Or ForceHours, _ProviderWithHours, _Provider)
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
|
Friend Sub New(Optional ByVal ForceHours As Boolean = False)
|
||||||
|
Me.ForceHours = ForceHours
|
||||||
|
End Sub
|
||||||
Private Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider,
|
Private Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider,
|
||||||
Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert
|
Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert
|
||||||
If Not IsNothing(Value) Then
|
If Not IsNothing(Value) Then
|
||||||
|
|||||||
@@ -336,6 +336,7 @@ Namespace DownloadObjects.STDownloader
|
|||||||
pForm.Dispose()
|
pForm.Dispose()
|
||||||
End If
|
End If
|
||||||
If Not c Is Nothing Then
|
If Not c Is Nothing Then
|
||||||
|
If Not c.HasElements Then DirectCast(c, YouTubeMediaContainerBase).FileForceArtist()
|
||||||
Dim f As Form
|
Dim f As Form
|
||||||
Select Case c.ObjectType
|
Select Case c.ObjectType
|
||||||
Case YouTubeMediaType.Single : f = New VideoOptionsForm(c) With {.UseCookies = useCookies}
|
Case YouTubeMediaType.Single : f = New VideoOptionsForm(c) With {.UseCookies = useCookies}
|
||||||
|
|||||||
@@ -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("2025.6.12.0")>
|
<Assembly: AssemblyVersion("2025.8.30.0")>
|
||||||
<Assembly: AssemblyFileVersion("2025.6.12.0")>
|
<Assembly: AssemblyFileVersion("2025.8.30.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("en")>
|
<Assembly: NeutralResourcesLanguage("en")>
|
||||||
|
|||||||
@@ -30,6 +30,11 @@ Namespace API.YouTube.Objects
|
|||||||
_File = CleanFileName(_File)
|
_File = CleanFileName(_File)
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
Protected Friend Overrides Sub FileForceArtist()
|
||||||
|
Dim __artistName$ = UserTitle.IfNullOrEmpty(AccountName)
|
||||||
|
If Not _File.Name.IsEmptyString AndAlso Not _File.Name.ToLower.Contains(__artistName.ToLower) Then _
|
||||||
|
_File.Name = $"{__artistName} - {_File.Name}"
|
||||||
|
End Sub
|
||||||
Public Overrides Function ToString(ByVal ForMediaItem As Boolean) As String
|
Public Overrides Function ToString(ByVal ForMediaItem As Boolean) As String
|
||||||
Dim s$ = SizeStr
|
Dim s$ = SizeStr
|
||||||
If Not s.IsEmptyString Then s = $" [{s}]"
|
If Not s.IsEmptyString Then s = $" [{s}]"
|
||||||
|
|||||||
@@ -356,6 +356,14 @@ Namespace API.YouTube.Objects
|
|||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
|
#Region "Chapters, Trimming"
|
||||||
|
Friend ReadOnly Property Chapters As List(Of TrimOption)
|
||||||
|
Friend ReadOnly Property TrimOptions As List(Of TrimOption)
|
||||||
|
Friend Property TrimDeleteOriginalFile As Boolean = False
|
||||||
|
Friend Property TrimAddTrimmedFilesToM3U8 As Boolean = False
|
||||||
|
Friend Property TrimSeparateFolder As Boolean = False
|
||||||
|
Friend Property TrimOptionsSet As Boolean = False
|
||||||
|
#End Region
|
||||||
#Region "IUserMedia Support"
|
#Region "IUserMedia Support"
|
||||||
<XMLEC> Private Property Attempts As Integer Implements IUserMedia.Attempts
|
<XMLEC> Private Property Attempts As Integer Implements IUserMedia.Attempts
|
||||||
Private _Object As Object = Nothing
|
Private _Object As Object = Nothing
|
||||||
@@ -684,6 +692,8 @@ Namespace API.YouTube.Objects
|
|||||||
End If
|
End If
|
||||||
End Set
|
End Set
|
||||||
End Property
|
End Property
|
||||||
|
Protected Friend Overridable Sub FileForceArtist()
|
||||||
|
End Sub
|
||||||
Friend Sub FileDateUpdate()
|
Friend Sub FileDateUpdate()
|
||||||
Dim n$ = _File.Name.StringTrim
|
Dim n$ = _File.Name.StringTrim
|
||||||
Dim s$ = IIf(n.IsEmptyString, String.Empty, " ")
|
Dim s$ = IIf(n.IsEmptyString, String.Empty, " ")
|
||||||
@@ -823,9 +833,13 @@ Namespace API.YouTube.Objects
|
|||||||
'cmd = $"yt-dlp -f ""{cmd}"""
|
'cmd = $"yt-dlp -f ""{cmd}"""
|
||||||
'cmd = $"yt-dlp -f {cmd}"
|
'cmd = $"yt-dlp -f {cmd}"
|
||||||
cmd = $"{YTDLP_NAME} -f {cmd}"
|
cmd = $"{YTDLP_NAME} -f {cmd}"
|
||||||
If Not MyYouTubeSettings.ReplaceModificationDate Then cmd &= " --no-mtime"
|
'yt-dlp 2025.07.21
|
||||||
|
'If Not MyYouTubeSettings.ReplaceModificationDate Then cmd &= " --no-mtime"
|
||||||
|
cmd &= $" --{IIf(MyYouTubeSettings.ReplaceModificationDate.Value, String.Empty, "no-")}mtime"
|
||||||
|
If MyYouTubeSettings.DefaultVideoEmbedChapters Then cmd &= " --embed-chapters --add-chapters"
|
||||||
cmd.StringAppend(formats, " ")
|
cmd.StringAppend(formats, " ")
|
||||||
cmd.StringAppend(subs, " ")
|
cmd.StringAppend(subs, " ")
|
||||||
|
If MyYouTubeSettings.ErrorsIgnore Then cmd &= " --no-abort-on-error --ignore-errors"
|
||||||
cmd.StringAppend(YouTubeFunctions.GetCookiesCommand(WithCookies, YouTubeCookieNetscapeFile), " ")
|
cmd.StringAppend(YouTubeFunctions.GetCookiesCommand(WithCookies, YouTubeCookieNetscapeFile), " ")
|
||||||
cmd &= $" {URL} -o ""{File.PathWithSeparator}{File.Name}"""
|
cmd &= $" {URL} -o ""{File.PathWithSeparator}{File.Name}"""
|
||||||
File.Exists(SFO.Path, True)
|
File.Exists(SFO.Path, True)
|
||||||
@@ -843,6 +857,8 @@ Namespace API.YouTube.Objects
|
|||||||
_Subtitles = New List(Of Subtitles)
|
_Subtitles = New List(Of Subtitles)
|
||||||
_SubtitlesDelegated = New List(Of Subtitles)
|
_SubtitlesDelegated = New List(Of Subtitles)
|
||||||
SubtitlesSelectedIndexes = New List(Of Integer)
|
SubtitlesSelectedIndexes = New List(Of Integer)
|
||||||
|
Chapters = New List(Of TrimOption)
|
||||||
|
TrimOptions = New List(Of TrimOption)
|
||||||
MediaObjects = New List(Of MediaObject)
|
MediaObjects = New List(Of MediaObject)
|
||||||
_Files = New List(Of SFile)
|
_Files = New List(Of SFile)
|
||||||
|
|
||||||
@@ -1265,6 +1281,7 @@ Namespace API.YouTube.Objects
|
|||||||
Dim fPatternFiles$ = $"{File.Name}*." & "{0}"
|
Dim fPatternFiles$ = $"{File.Name}*." & "{0}"
|
||||||
Dim fAacAudio As New TempFileConversion(New SFile(String.Format(fPattern, aac)), Me)
|
Dim fAacAudio As New TempFileConversion(New SFile(String.Format(fPattern, aac)), Me)
|
||||||
Dim mp3ThumbEmbedded As Boolean = False
|
Dim mp3ThumbEmbedded As Boolean = False
|
||||||
|
Dim audioFiles As New List(Of SFile)
|
||||||
|
|
||||||
Dim tempFilesList As New List(Of TempFileConversion)
|
Dim tempFilesList As New List(Of TempFileConversion)
|
||||||
Dim ttFile As TempFileConversion
|
Dim ttFile As TempFileConversion
|
||||||
@@ -1372,13 +1389,17 @@ Namespace API.YouTube.Objects
|
|||||||
format = format.StringToLower
|
format = format.StringToLower
|
||||||
f = String.Format(fPattern, format)
|
f = String.Format(fPattern, format)
|
||||||
AddFile(f)
|
AddFile(f)
|
||||||
|
audioFiles.Add(f)
|
||||||
If Not f.Exists Then
|
If Not f.Exists Then
|
||||||
tryToConvert.Invoke(format, f)
|
tryToConvert.Invoke(format, f)
|
||||||
updateBitrate(f)
|
updateBitrate(f)
|
||||||
If format = mp3 And Not mp3ThumbEmbedded And MyYouTubeSettings.DefaultAudioEmbedThumbnail_ExtractedFiles Then _
|
If f.Exists Then
|
||||||
embedThumbTo.Invoke(f) : mp3ThumbEmbedded = True
|
If format = mp3 And Not mp3ThumbEmbedded And MyYouTubeSettings.DefaultAudioEmbedThumbnail_ExtractedFiles Then _
|
||||||
If Not M3U8_PlaylistFiles.ListExists AndAlso f.Exists Then M3U8_Append(f)
|
embedThumbTo.Invoke(f) : mp3ThumbEmbedded = True
|
||||||
If format = mp3 AndAlso f.Exists AndAlso MyYouTubeSettings.VideoPlaylist_AddExtractedMP3.Value Then M3U8_Append(f)
|
If M3U8_PlaylistFiles.ListExists OrElse
|
||||||
|
(format = mp3 AndAlso MyYouTubeSettings.VideoPlaylist_AddExtractedMP3.Value) Then _
|
||||||
|
M3U8_Append(f)
|
||||||
|
End If
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
@@ -1431,6 +1452,43 @@ Namespace API.YouTube.Objects
|
|||||||
If OutputVideoFPS > 0 AndAlso SelectedVideo.Bitrate <> OutputVideoFPS Then _
|
If OutputVideoFPS > 0 AndAlso SelectedVideo.Bitrate <> OutputVideoFPS Then _
|
||||||
reencodeFile("ffmpeg -i ""{0}"" -filter:v fps=" & OutputVideoFPS.ToString.Replace(", ", ".") & " -c:a copy ""{1}""")
|
reencodeFile("ffmpeg -i ""{0}"" -filter:v fps=" & OutputVideoFPS.ToString.Replace(", ", ".") & " -c:a copy ""{1}""")
|
||||||
End If
|
End If
|
||||||
|
|
||||||
|
'Trimming
|
||||||
|
If TrimOptions.Count > 0 AndAlso File.Exists Then
|
||||||
|
Const trimCommand$ = "ffmpeg -i ""{0}"" -ss {1} -to {2} -c:v copy -c:a copy ""{3}"""
|
||||||
|
Dim trimFirstFile As SFile = Nothing
|
||||||
|
Dim trimFirstAdded As Boolean = False
|
||||||
|
Dim processTrim As Action(Of TrimOption, SFile) =
|
||||||
|
Sub(ByVal opt As TrimOption, ByVal pFile As SFile)
|
||||||
|
Dim fNew As SFile = pFile
|
||||||
|
fNew.Name &= $"_{opt.Name}"
|
||||||
|
If TrimSeparateFolder Then fNew = $"{fNew.PathNoSeparator}\{MyYouTubeSettings.TrimSeparateFolderName.Value.IfNullOrEmpty(YouTubeSettings.TrimSeparateFolderNameDefault)}\{fNew.File}" : fNew.Exists(SFO.Path)
|
||||||
|
format = fNew.Extension.StringToLower
|
||||||
|
.Execute(String.Format(trimCommand,
|
||||||
|
pFile,
|
||||||
|
AConvert(Of String)(opt.StartTime, TimeToStringProvider),
|
||||||
|
AConvert(Of String)(opt.EndTime, TimeToStringProvider),
|
||||||
|
fNew))
|
||||||
|
If fNew.Exists Then
|
||||||
|
If trimFirstFile.IsEmptyString Then trimFirstFile = fNew
|
||||||
|
AddFile(fNew)
|
||||||
|
If format = mp3 And MyYouTubeSettings.DefaultAudioEmbedThumbnail_ExtractedFiles Then _
|
||||||
|
embedThumbTo.Invoke(fNew) : mp3ThumbEmbedded = True
|
||||||
|
If (TrimAddTrimmedFilesToM3U8 Or (TrimDeleteOriginalFile And Not trimFirstAdded)) AndAlso
|
||||||
|
(M3U8_PlaylistFiles.ListExists OrElse
|
||||||
|
(format = mp3 AndAlso MyYouTubeSettings.VideoPlaylist_AddExtractedMP3.Value)) Then _
|
||||||
|
M3U8_Append(fNew) : trimFirstAdded = True
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
For Each tr As TrimOption In TrimOptions
|
||||||
|
processTrim(tr, File)
|
||||||
|
If audioFiles.Count > 0 Then
|
||||||
|
For Each f In audioFiles : processTrim(tr, f) : Next
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
If TrimDeleteOriginalFile Then File.Delete() : File = trimFirstFile
|
||||||
|
|
||||||
|
End If
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
@@ -1690,6 +1748,8 @@ Namespace API.YouTube.Objects
|
|||||||
ParseThumbnails(.Self)
|
ParseThumbnails(.Self)
|
||||||
|
|
||||||
ParseSubtitles(.Self)
|
ParseSubtitles(.Self)
|
||||||
|
|
||||||
|
ParseChapters(.Self)
|
||||||
End With
|
End With
|
||||||
Return True
|
Return True
|
||||||
End If
|
End If
|
||||||
@@ -1955,6 +2015,15 @@ Namespace API.YouTube.Objects
|
|||||||
End With
|
End With
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
|
Protected Sub ParseChapters(ByVal e As EContainer)
|
||||||
|
With e({"chapters"})
|
||||||
|
If .ListExists Then Chapters.AddRange(.Select(Function(ee) New TrimOption With {
|
||||||
|
.Start = CInt(AConvert(Of Double)(ee.Value("start_time"), 0, EDP.ReturnValue)),
|
||||||
|
.[End] = CInt(AConvert(Of Double)(ee.Value("end_time"), 0, EDP.ReturnValue)),
|
||||||
|
.Name = CleanFileName(New SFile With {.Name = ee.Value("title")}).Name
|
||||||
|
}))
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "IEContainerProvider Support"
|
#Region "IEContainerProvider Support"
|
||||||
Private Function GetElementsChecked() As IEnumerable(Of EContainer)
|
Private Function GetElementsChecked() As IEnumerable(Of EContainer)
|
||||||
@@ -2029,6 +2098,8 @@ Namespace API.YouTube.Objects
|
|||||||
_Subtitles.Clear()
|
_Subtitles.Clear()
|
||||||
_SubtitlesDelegated.Clear()
|
_SubtitlesDelegated.Clear()
|
||||||
SubtitlesSelectedIndexes.Clear()
|
SubtitlesSelectedIndexes.Clear()
|
||||||
|
Chapters.Clear()
|
||||||
|
TrimOptions.Clear()
|
||||||
MediaObjects.Clear()
|
MediaObjects.Clear()
|
||||||
_Files.Clear()
|
_Files.Clear()
|
||||||
PostProcessing_OutputAudioFormats.Clear()
|
PostProcessing_OutputAudioFormats.Clear()
|
||||||
|
|||||||
@@ -124,6 +124,12 @@
|
|||||||
<Compile Include="Controls\ChannelTabsChooserForm.vb">
|
<Compile Include="Controls\ChannelTabsChooserForm.vb">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Controls\ChaptersForm.Designer.vb">
|
||||||
|
<DependentUpon>ChaptersForm.vb</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Controls\ChaptersForm.vb">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Controls\FilterForm.Designer.vb">
|
<Compile Include="Controls\FilterForm.Designer.vb">
|
||||||
<DependentUpon>FilterForm.vb</DependentUpon>
|
<DependentUpon>FilterForm.vb</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -136,6 +142,18 @@
|
|||||||
<Compile Include="Controls\PlayListParserForm.vb">
|
<Compile Include="Controls\PlayListParserForm.vb">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Controls\TrimOptionForm.Designer.vb">
|
||||||
|
<DependentUpon>TrimOptionForm.vb</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Controls\TrimOptionForm.vb">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Controls\VideoOptionsTrimForm.Designer.vb">
|
||||||
|
<DependentUpon>VideoOptionsTrimForm.vb</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Controls\VideoOptionsTrimForm.vb">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Controls\YTDataFilter.vb" />
|
<Compile Include="Controls\YTDataFilter.vb" />
|
||||||
<Compile Include="Downloader\DownloadLocationsCollection.vb" />
|
<Compile Include="Downloader\DownloadLocationsCollection.vb" />
|
||||||
<Compile Include="Downloader\IDownloaderSettings.vb" />
|
<Compile Include="Downloader\IDownloaderSettings.vb" />
|
||||||
@@ -227,12 +245,21 @@
|
|||||||
<EmbeddedResource Include="Controls\ChannelTabsChooserForm.resx">
|
<EmbeddedResource Include="Controls\ChannelTabsChooserForm.resx">
|
||||||
<DependentUpon>ChannelTabsChooserForm.vb</DependentUpon>
|
<DependentUpon>ChannelTabsChooserForm.vb</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Controls\ChaptersForm.resx">
|
||||||
|
<DependentUpon>ChaptersForm.vb</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="Controls\FilterForm.resx">
|
<EmbeddedResource Include="Controls\FilterForm.resx">
|
||||||
<DependentUpon>FilterForm.vb</DependentUpon>
|
<DependentUpon>FilterForm.vb</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="Controls\PlayListParserForm.resx">
|
<EmbeddedResource Include="Controls\PlayListParserForm.resx">
|
||||||
<DependentUpon>PlayListParserForm.vb</DependentUpon>
|
<DependentUpon>PlayListParserForm.vb</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Controls\TrimOptionForm.resx">
|
||||||
|
<DependentUpon>TrimOptionForm.vb</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Controls\VideoOptionsTrimForm.resx">
|
||||||
|
<DependentUpon>VideoOptionsTrimForm.vb</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="Downloader\MediaItem.resx">
|
<EmbeddedResource Include="Downloader\MediaItem.resx">
|
||||||
<DependentUpon>MediaItem.vb</DependentUpon>
|
<DependentUpon>MediaItem.vb</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
|||||||
@@ -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("2025.6.12.0")>
|
<Assembly: AssemblyVersion("2025.8.30.0")>
|
||||||
<Assembly: AssemblyFileVersion("2025.6.12.0")>
|
<Assembly: AssemblyFileVersion("2025.8.30.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("en")>
|
<Assembly: NeutralResourcesLanguage("en")>
|
||||||
|
|||||||
14
SCrawler.sln
14
SCrawler.sln
@@ -29,6 +29,8 @@ Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "SCrawler.Updater", "SCrawle
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "SCrawler.Shared", "SCrawler.Shared\SCrawler.Shared.vbproj", "{DC634700-24C7-42DD-BF8F-87E6CC54E625}"
|
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "SCrawler.Shared", "SCrawler.Shared\SCrawler.Shared.vbproj", "{DC634700-24C7-42DD-BF8F-87E6CC54E625}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "PersonalUtilities.Images", "..\..\MyUtilities\PersonalUtilities.Images\PersonalUtilities.Images.vbproj", "{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -135,6 +137,18 @@ Global
|
|||||||
{DC634700-24C7-42DD-BF8F-87E6CC54E625}.Release|x64.Build.0 = Release|x64
|
{DC634700-24C7-42DD-BF8F-87E6CC54E625}.Release|x64.Build.0 = Release|x64
|
||||||
{DC634700-24C7-42DD-BF8F-87E6CC54E625}.Release|x86.ActiveCfg = Release|x86
|
{DC634700-24C7-42DD-BF8F-87E6CC54E625}.Release|x86.ActiveCfg = Release|x86
|
||||||
{DC634700-24C7-42DD-BF8F-87E6CC54E625}.Release|x86.Build.0 = Release|x86
|
{DC634700-24C7-42DD-BF8F-87E6CC54E625}.Release|x86.Build.0 = Release|x86
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|x64.Build.0 = Release|x64
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{B7EF76A9-96F3-4C53-B252-0AB5F79B67B3}.Release|x86.Build.0 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
43
SCrawler/API/Base/EditorExchangeOptionsBase_P.vb
Normal file
43
SCrawler/API/Base/EditorExchangeOptionsBase_P.vb
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||||
|
' This program is free software: you can redistribute it and/or modify
|
||||||
|
' it under the terms of the GNU General Public License as published by
|
||||||
|
' the Free Software Foundation, either version 3 of the License, or
|
||||||
|
' (at your option) any later version.
|
||||||
|
'
|
||||||
|
' This program is distributed in the hope that it will be useful,
|
||||||
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports SCrawler.Plugin.Attributes
|
||||||
|
Namespace API.Base
|
||||||
|
Friend Interface IPSite
|
||||||
|
Property QueryString As String
|
||||||
|
End Interface
|
||||||
|
Friend Class EditorExchangeOptionsBase_P : Inherits EditorExchangeOptionsBase : Implements IPSite
|
||||||
|
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property UserName As String
|
||||||
|
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadText As Boolean
|
||||||
|
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadTextPosts As Boolean
|
||||||
|
<PSetting(Address:=SettingAddress.None)> Friend Overrides Property DownloadTextSpecialFolder As Boolean
|
||||||
|
<PSetting(Address:=SettingAddress.User, Caption:="Query",
|
||||||
|
ToolTip:="Query string. Don't change this field when creating a user! Change it only for the same request.")>
|
||||||
|
Friend Property QueryString As String Implements IPSite.QueryString
|
||||||
|
Friend Sub New()
|
||||||
|
DisableBase()
|
||||||
|
End Sub
|
||||||
|
Friend Sub New(ByVal u As UserDataBase)
|
||||||
|
MyBase.New(u)
|
||||||
|
DisableBase()
|
||||||
|
If TypeOf u Is IPSite Then QueryString = DirectCast(u, IPSite).QueryString
|
||||||
|
End Sub
|
||||||
|
Friend Sub New(ByVal s As SiteSettingsBase)
|
||||||
|
MyBase.New(s)
|
||||||
|
DisableBase()
|
||||||
|
End Sub
|
||||||
|
Friend Overridable Sub Apply(ByRef u As IPSite)
|
||||||
|
ApplyBase(u)
|
||||||
|
u.QueryString = QueryString
|
||||||
|
End Sub
|
||||||
|
Protected Overridable Sub DisableBase()
|
||||||
|
_ApplyBase_Name = False
|
||||||
|
_ApplyBase_Text = False
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
@@ -1723,6 +1723,7 @@ BlockNullPicture:
|
|||||||
Dim vsf As Boolean = SeparateVideoFolderF
|
Dim vsf As Boolean = SeparateVideoFolderF
|
||||||
Dim __isVideo As Boolean
|
Dim __isVideo As Boolean
|
||||||
Dim __interrupt As Boolean
|
Dim __interrupt As Boolean
|
||||||
|
Dim postProcessWebp As Boolean
|
||||||
Dim f As SFile, fTxt As SFile
|
Dim f As SFile, fTxt As SFile
|
||||||
Dim v As UserMedia
|
Dim v As UserMedia
|
||||||
Dim __fileDeleted As Boolean
|
Dim __fileDeleted As Boolean
|
||||||
@@ -1782,6 +1783,7 @@ BlockNullPicture:
|
|||||||
If v.URL_BASE.IsEmptyString Then v.URL_BASE = v.URL
|
If v.URL_BASE.IsEmptyString Then v.URL_BASE = v.URL
|
||||||
|
|
||||||
__fileDeleted = False
|
__fileDeleted = False
|
||||||
|
postProcessWebp = False
|
||||||
|
|
||||||
If (v.Type = UTypes.Text And DownloadText) Or (Not f.IsEmptyString And Not v.URL.IsEmptyString) Then
|
If (v.Type = UTypes.Text And DownloadText) Or (Not f.IsEmptyString And Not v.URL.IsEmptyString) Then
|
||||||
Try
|
Try
|
||||||
@@ -1794,8 +1796,9 @@ BlockNullPicture:
|
|||||||
Case UTypes.Video, UTypes.m3u8 : f.Extension = "mp4"
|
Case UTypes.Video, UTypes.m3u8 : f.Extension = "mp4"
|
||||||
Case UTypes.GIF : f.Extension = "gif"
|
Case UTypes.GIF : f.Extension = "gif"
|
||||||
End Select
|
End Select
|
||||||
ElseIf f.Extension = "webp" And Settings.DownloadNativeImageFormat Then
|
ElseIf f.Extension = UserImage.ExtWebp And Settings.DownloadNativeImageFormat And Settings.FfmpegFile.Exists Then
|
||||||
f.Extension = "jpg"
|
'f.Extension = "jpg"
|
||||||
|
postProcessWebp = True
|
||||||
End If
|
End If
|
||||||
|
|
||||||
If Not v.SpecialFolder.IsEmptyString Then
|
If Not v.SpecialFolder.IsEmptyString Then
|
||||||
@@ -1830,7 +1833,7 @@ BlockNullPicture:
|
|||||||
|
|
||||||
updateDownCount(False)
|
updateDownCount(False)
|
||||||
|
|
||||||
v.File = ChangeFileNameByProvider(f, v)
|
v.File = DownloadContentDefault_ConvertWebp(ChangeFileNameByProvider(f, v), postProcessWebp)
|
||||||
v.State = UStates.Downloaded
|
v.State = UStates.Downloaded
|
||||||
DownloadContentDefault_PostProcessing(v, f, Token)
|
DownloadContentDefault_PostProcessing(v, f, Token)
|
||||||
If UseMD5Comparison And (v.Type = UTypes.GIF Or v.Type = UTypes.Picture) Then
|
If UseMD5Comparison And (v.Type = UTypes.GIF Or v.Type = UTypes.Picture) Then
|
||||||
@@ -1930,6 +1933,22 @@ stxt:
|
|||||||
End Function
|
End Function
|
||||||
Protected Overridable Sub DownloadContentDefault_PostProcessing(ByRef m As UserMedia, ByVal File As SFile, ByVal Token As CancellationToken)
|
Protected Overridable Sub DownloadContentDefault_PostProcessing(ByRef m As UserMedia, ByVal File As SFile, ByVal Token As CancellationToken)
|
||||||
End Sub
|
End Sub
|
||||||
|
Protected Overridable Function DownloadContentDefault_ConvertWebp(ByVal WebpFile As SFile, ByVal Process As Boolean) As SFile
|
||||||
|
Dim f As SFile = WebpFile
|
||||||
|
If Process AndAlso f.Exists Then
|
||||||
|
f.Path = $"{f.PathWithSeparator}Sources"
|
||||||
|
f.Exists(SFO.Path)
|
||||||
|
If WebpFile.Copy(f) Then
|
||||||
|
Dim newFile As SFile = WebpFile
|
||||||
|
newFile.Extension = UserImage.ExtJpg
|
||||||
|
f = UserImage.ConvertWebp(f, newFile)
|
||||||
|
If f.Exists Then WebpFile.Delete(SFO.File, SFODelete.DeletePermanently, EDP.ReturnValue)
|
||||||
|
Else
|
||||||
|
f = WebpFile
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Return f
|
||||||
|
End Function
|
||||||
Protected Overridable Function DownloadContentDefault_ProcessDownloadException() As Boolean
|
Protected Overridable Function DownloadContentDefault_ProcessDownloadException() As Boolean
|
||||||
Return True
|
Return True
|
||||||
End Function
|
End Function
|
||||||
@@ -2288,6 +2307,7 @@ stxt:
|
|||||||
End Function
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Errors functions"
|
#Region "Errors functions"
|
||||||
|
''' <summary>ToStringForLog(): Message</summary>
|
||||||
Protected Sub LogError(ByVal ex As Exception, ByVal Message As String, Optional ByVal e As ErrorsDescriber = Nothing)
|
Protected Sub LogError(ByVal ex As Exception, ByVal Message As String, Optional ByVal e As ErrorsDescriber = Nothing)
|
||||||
ErrorsDescriber.Execute(If(e.Exists, e, New ErrorsDescriber(EDP.SendToLog)), ex, $"{ToStringForLog()}: {Message}")
|
ErrorsDescriber.Execute(If(e.Exists, e, New ErrorsDescriber(EDP.SendToLog)), ex, $"{ToStringForLog()}: {Message}")
|
||||||
End Sub
|
End Sub
|
||||||
|
|||||||
@@ -412,6 +412,7 @@ Namespace API.Instagram
|
|||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
HasError = False
|
HasError = False
|
||||||
Dim dt As Func(Of Boolean) = Function() (CBool(MySiteSettings.DownloadTimeline.Value) And GetTimeline) Or IsSavedPosts
|
Dim dt As Func(Of Boolean) = Function() (CBool(MySiteSettings.DownloadTimeline.Value) And GetTimeline) Or IsSavedPosts
|
||||||
|
If FirstLoadingDone Then LastCursor = String.Empty
|
||||||
If dt.Invoke And Not LastCursor.IsEmptyString Then
|
If dt.Invoke And Not LastCursor.IsEmptyString Then
|
||||||
s = IIf(IsSavedPosts, Sections.SavedPosts, Sections.Timeline)
|
s = IIf(IsSavedPosts, Sections.SavedPosts, Sections.Timeline)
|
||||||
upClaimRequest.Invoke
|
upClaimRequest.Invoke
|
||||||
@@ -1151,12 +1152,30 @@ NextPageBlock:
|
|||||||
If TryExtractImage Then
|
If TryExtractImage Then
|
||||||
t = 1
|
t = 1
|
||||||
abstractDecision = True
|
abstractDecision = True
|
||||||
If Not SpecialFolder.IsEmptyString AndAlso PutImageVideoFolder Then
|
Dim endsAbs As Boolean
|
||||||
Dim endsAbs As Boolean = SpecialFolder.EndsWith("*")
|
Dim newFolderName$
|
||||||
If endsAbs Then SpecialFolder = SpecialFolder.TrimEnd("*")
|
If PutImageVideoFolder Then
|
||||||
If Not SpecialFolder.IsEmptyString Then SpecialFolder = $"{SpecialFolder.TrimEnd("\")}\{VideoFolderName}{IIf(Not endsAbs, "*", String.Empty)}"
|
If SpecialFolder.IsEmptyString Then
|
||||||
If endsAbs Then SpecialFolder &= "*"
|
newFolderName = $"{VideoFolderName}\*"
|
||||||
|
Else
|
||||||
|
endsAbs = SpecialFolder.EndsWith("*")
|
||||||
|
SpecialFolder = SpecialFolder.TrimEnd({CChar("\"), CChar("*")})
|
||||||
|
If Not endsAbs Then SpecialFolder = $"{SpecialFolder}\{VideoFolderName}"
|
||||||
|
newFolderName = $"{SpecialFolder}*"
|
||||||
|
End If
|
||||||
|
'Dim endsAbs As Boolean = SpecialFolder.EndsWith("*")
|
||||||
|
'If endsAbs Then SpecialFolder = SpecialFolder.TrimEnd("*")
|
||||||
|
'If Not SpecialFolder.IsEmptyString Then SpecialFolder = $"{SpecialFolder.TrimEnd("\")}\{VideoFolderName}{IIf(Not endsAbs, "*", String.Empty)}"
|
||||||
|
'If endsAbs Then SpecialFolder &= "*"
|
||||||
|
ElseIf Not SpecialFolder.IsEmptyString Then
|
||||||
|
endsAbs = SpecialFolder.EndsWith("*")
|
||||||
|
SpecialFolder = SpecialFolder.TrimEnd({CChar("\"), CChar("*")})
|
||||||
|
If endsAbs Then SpecialFolder = $"{SpecialFolder}\Photos"
|
||||||
|
newFolderName = $"{SpecialFolder}*"
|
||||||
|
Else
|
||||||
|
newFolderName = SpecialFolder
|
||||||
End If
|
End If
|
||||||
|
SpecialFolder = newFolderName
|
||||||
ElseIf t = -1 And InitialType = 8 And ObtainMedia_AllowAbstract Then
|
ElseIf t = -1 And InitialType = 8 And ObtainMedia_AllowAbstract Then
|
||||||
If n.Contains(vid) Then
|
If n.Contains(vid) Then
|
||||||
t = 2
|
t = 2
|
||||||
|
|||||||
@@ -431,7 +431,7 @@ Namespace API.OnlyFans
|
|||||||
Result = False
|
Result = False
|
||||||
With n("media")
|
With n("media")
|
||||||
If .ListExists Then
|
If .ListExists Then
|
||||||
For Each m In .Self
|
For Each m As EContainer In .Self
|
||||||
postUrl = GetMediaURL(m)
|
postUrl = GetMediaURL(m)
|
||||||
'If IsHL Then
|
'If IsHL Then
|
||||||
' 'postUrl = m.Value({"files", "source"}, "url")
|
' 'postUrl = m.Value({"files", "source"}, "url")
|
||||||
@@ -440,32 +440,34 @@ Namespace API.OnlyFans
|
|||||||
' 'postUrl = m.Value({"source"}, "source").IfNullOrEmpty(m.Value("full"))
|
' 'postUrl = m.Value({"source"}, "source").IfNullOrEmpty(m.Value("full"))
|
||||||
' postUrl = GetMediaURL(m)
|
' postUrl = GetMediaURL(m)
|
||||||
'End If
|
'End If
|
||||||
postUrlBase = String.Empty
|
If m.Value("canView").FromXML(Of Boolean)(True) Then
|
||||||
Select Case m.Value("type")
|
postUrlBase = String.Empty
|
||||||
Case "photo" : t = UTypes.Picture : ext = "jpg"
|
Select Case m.Value("type")
|
||||||
Case "video"
|
Case "photo" : t = UTypes.Picture : ext = "jpg"
|
||||||
t = UTypes.Video
|
Case "video", "gif"
|
||||||
ext = "mp4"
|
t = UTypes.Video
|
||||||
If postUrl.IsEmptyString And Not IsHL And TryUseOFS Then
|
ext = "mp4"
|
||||||
t = UTypes.VideoPre
|
If postUrl.IsEmptyString And Not IsHL And TryUseOFS Then
|
||||||
_AbsMediaIndex += 1
|
t = UTypes.VideoPre
|
||||||
If Not PostUserID.IsEmptyString And IsSingleObjectDownload Then _
|
_AbsMediaIndex += 1
|
||||||
postUrlBase = String.Format(SiteSettings.UserPostPattern, PostID, $"u{PostUserID}")
|
If Not PostUserID.IsEmptyString And IsSingleObjectDownload Then _
|
||||||
End If
|
postUrlBase = String.Format(SiteSettings.UserPostPattern, PostID, $"u{PostUserID}")
|
||||||
Case Else : t = UTypes.Undefined : ext = String.Empty
|
End If
|
||||||
End Select
|
Case Else : t = UTypes.Undefined : ext = String.Empty
|
||||||
If Not t = UTypes.Undefined And (Not postUrl.IsEmptyString Or t = UTypes.VideoPre) Then
|
End Select
|
||||||
Dim media As New UserMedia(postUrl.IfNullOrEmpty(IIf(t = UTypes.VideoPre, $"{t}{_AbsMediaIndex}", String.Empty)), t) With {
|
If Not t = UTypes.Undefined And (Not postUrl.IsEmptyString Or t = UTypes.VideoPre) Then
|
||||||
.Post = New UserPost(PostID, AConvert(Of Date)(PostDate, DateProvider, Nothing)),
|
Dim media As New UserMedia(postUrl.IfNullOrEmpty(IIf(t = UTypes.VideoPre, $"{t}{_AbsMediaIndex}", String.Empty)), t) With {
|
||||||
.SpecialFolder = SpecFolder,
|
.Post = New UserPost(PostID, AConvert(Of Date)(PostDate, DateProvider, Nothing)),
|
||||||
.PostText = PostText,
|
.SpecialFolder = SpecFolder,
|
||||||
.PostTextFileSpecialFolder = DownloadTextSpecialFolder
|
.PostText = PostText,
|
||||||
}
|
.PostTextFileSpecialFolder = DownloadTextSpecialFolder
|
||||||
If postUrlBase.IsEmptyString And Not IsSingleObjectDownload Then postUrlBase = GetPostUrl(Me, media)
|
}
|
||||||
If Not postUrlBase.IsEmptyString Then media.URL_BASE = postUrlBase
|
If postUrlBase.IsEmptyString And Not IsSingleObjectDownload Then postUrlBase = GetPostUrl(Me, media)
|
||||||
media.File.Extension = ext
|
If Not postUrlBase.IsEmptyString Then media.URL_BASE = postUrlBase
|
||||||
Result = True
|
media.File.Extension = ext
|
||||||
mList.Add(media)
|
Result = True
|
||||||
|
mList.Add(media)
|
||||||
|
End If
|
||||||
End If
|
End If
|
||||||
Next
|
Next
|
||||||
End If
|
End If
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ Imports PersonalUtilities.Tools.Web.Clients
|
|||||||
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
|
||||||
Namespace API.PornHub
|
Namespace API.PornHub
|
||||||
Friend Class UserData : Inherits UserDataBase
|
Friend Class UserData : Inherits UserDataBase : Implements IPSite
|
||||||
Private Const UrlPattern As String = "https://www.pornhub.com/{0}"
|
Private Const UrlPattern As String = "https://www.pornhub.com/{0}"
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
#Region "XML names"
|
#Region "XML names"
|
||||||
@@ -140,7 +140,7 @@ Namespace API.PornHub
|
|||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
Friend Property SiteMode As SiteModes = SiteModes.User
|
Friend Property SiteMode As SiteModes = SiteModes.User
|
||||||
Friend Property QueryString As String
|
Friend Property QueryString As String Implements IPSite.QueryString
|
||||||
Get
|
Get
|
||||||
If IsUser Then
|
If IsUser Then
|
||||||
Return String.Empty
|
Return String.Empty
|
||||||
@@ -163,17 +163,7 @@ Namespace API.PornHub
|
|||||||
Return New UserExchangeOptions(Me)
|
Return New UserExchangeOptions(Me)
|
||||||
End Function
|
End Function
|
||||||
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
||||||
If Not Obj Is Nothing AndAlso TypeOf Obj Is UserExchangeOptions Then
|
If Not Obj Is Nothing AndAlso TypeOf Obj Is UserExchangeOptions Then DirectCast(Obj, UserExchangeOptions).Apply(Me)
|
||||||
With DirectCast(Obj, UserExchangeOptions)
|
|
||||||
DownloadUHD = .DownloadUHD
|
|
||||||
DownloadUploaded = .DownloadUploaded
|
|
||||||
DownloadTagged = .DownloadTagged
|
|
||||||
DownloadPrivate = .DownloadPrivate
|
|
||||||
DownloadFavorite = .DownloadFavorite
|
|
||||||
DownloadGifs = .DownloadGifs
|
|
||||||
QueryString = .QueryString
|
|
||||||
End With
|
|
||||||
End If
|
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
Private ReadOnly Property MySettings As SiteSettings
|
Private ReadOnly Property MySettings As SiteSettings
|
||||||
|
|||||||
@@ -6,9 +6,10 @@
|
|||||||
'
|
'
|
||||||
' This program is distributed in the hope that it will be useful,
|
' This program is distributed in the hope that it will be useful,
|
||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports SCrawler.API.Base
|
||||||
Imports SCrawler.Plugin.Attributes
|
Imports SCrawler.Plugin.Attributes
|
||||||
Namespace API.PornHub
|
Namespace API.PornHub
|
||||||
Friend Class UserExchangeOptions : Inherits Xhamster.UserExchangeOptions
|
Friend Class UserExchangeOptions : Inherits EditorExchangeOptionsBase_P
|
||||||
<PSetting(NameOf(SiteSettings.DownloadUHD), NameOf(MySettings))>
|
<PSetting(NameOf(SiteSettings.DownloadUHD), NameOf(MySettings))>
|
||||||
Friend Property DownloadUHD As Boolean
|
Friend Property DownloadUHD As Boolean
|
||||||
<PSetting(NameOf(SiteSettings.DownloadUploaded), NameOf(MySettings))>
|
<PSetting(NameOf(SiteSettings.DownloadUploaded), NameOf(MySettings))>
|
||||||
@@ -23,16 +24,17 @@ Namespace API.PornHub
|
|||||||
Friend Property DownloadGifs As Boolean
|
Friend Property DownloadGifs As Boolean
|
||||||
Private ReadOnly Property MySettings As SiteSettings
|
Private ReadOnly Property MySettings As SiteSettings
|
||||||
Friend Sub New(ByVal u As UserData)
|
Friend Sub New(ByVal u As UserData)
|
||||||
|
MyBase.New(u)
|
||||||
DownloadUHD = u.DownloadUHD
|
DownloadUHD = u.DownloadUHD
|
||||||
DownloadUploaded = u.DownloadUploaded
|
DownloadUploaded = u.DownloadUploaded
|
||||||
DownloadTagged = u.DownloadTagged
|
DownloadTagged = u.DownloadTagged
|
||||||
DownloadPrivate = u.DownloadPrivate
|
DownloadPrivate = u.DownloadPrivate
|
||||||
DownloadFavorite = u.DownloadFavorite
|
DownloadFavorite = u.DownloadFavorite
|
||||||
DownloadGifs = u.DownloadGifs
|
DownloadGifs = u.DownloadGifs
|
||||||
QueryString = u.QueryString
|
|
||||||
MySettings = u.HOST.Source
|
MySettings = u.HOST.Source
|
||||||
End Sub
|
End Sub
|
||||||
Friend Sub New(ByVal s As SiteSettings)
|
Friend Sub New(ByVal s As SiteSettings)
|
||||||
|
MyBase.New(s)
|
||||||
Dim v As CheckState = CInt(s.DownloadGifs.Value)
|
Dim v As CheckState = CInt(s.DownloadGifs.Value)
|
||||||
DownloadUHD = s.DownloadUHD.Value
|
DownloadUHD = s.DownloadUHD.Value
|
||||||
DownloadUploaded = s.DownloadUploaded.Value
|
DownloadUploaded = s.DownloadUploaded.Value
|
||||||
@@ -42,5 +44,16 @@ Namespace API.PornHub
|
|||||||
DownloadGifs = Not v = CheckState.Unchecked
|
DownloadGifs = Not v = CheckState.Unchecked
|
||||||
MySettings = s
|
MySettings = s
|
||||||
End Sub
|
End Sub
|
||||||
|
Friend Overrides Sub Apply(ByRef u As IPSite)
|
||||||
|
MyBase.Apply(u)
|
||||||
|
With DirectCast(u, UserData)
|
||||||
|
.DownloadUHD = DownloadUHD
|
||||||
|
.DownloadUploaded = DownloadUploaded
|
||||||
|
.DownloadTagged = DownloadTagged
|
||||||
|
.DownloadPrivate = DownloadPrivate
|
||||||
|
.DownloadFavorite = DownloadFavorite
|
||||||
|
.DownloadGifs = DownloadGifs
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -9,26 +9,38 @@
|
|||||||
Imports SCrawler.API.Base
|
Imports SCrawler.API.Base
|
||||||
Imports SCrawler.Plugin
|
Imports SCrawler.Plugin
|
||||||
Imports SCrawler.Plugin.Attributes
|
Imports SCrawler.Plugin.Attributes
|
||||||
|
Imports System.Reflection
|
||||||
Imports PersonalUtilities.Tools.Web.Clients
|
Imports PersonalUtilities.Tools.Web.Clients
|
||||||
Imports PersonalUtilities.Tools.Web.Clients.Base
|
Imports PersonalUtilities.Tools.Web.Clients.Base
|
||||||
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||||
Imports PersonalUtilities.Functions.XML
|
Imports PersonalUtilities.Functions.XML
|
||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
|
Imports DN = SCrawler.API.Base.DeclaredNames
|
||||||
Imports DownDetector = SCrawler.API.Base.DownDetector
|
Imports DownDetector = SCrawler.API.Base.DownDetector
|
||||||
Imports Download = SCrawler.Plugin.ISiteSettings.Download
|
Imports Download = SCrawler.Plugin.ISiteSettings.Download
|
||||||
Namespace API.Reddit
|
Namespace API.Reddit
|
||||||
<Manifest(RedditSiteKey), SavedPosts, SpecialForm(False), UseDownDetector>
|
<Manifest(RedditSiteKey), SavedPosts, SeparatedTasks, SpecialForm(False), UseDownDetector>
|
||||||
Friend Class SiteSettings : Inherits SiteSettingsBase : Implements DownDetector.IDownDetector
|
Friend Class SiteSettings : Inherits SiteSettingsBase : Implements DownDetector.IDownDetector
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
#Region "Authorization"
|
#Region "Authorization"
|
||||||
|
Private Const ApiClientID_Default As String = "dYctRA-SIJxyykHe27lGZg"
|
||||||
|
Private Const ApiClientSecret_Default As String = "_5D6KzplRPDga-es1YlpzDIe9hiFlg"
|
||||||
<PropertyOption(ControlText:="Login", ControlToolTip:="Your authorization username", IsAuth:=True), PXML, PClonable(Clone:=False)>
|
<PropertyOption(ControlText:="Login", ControlToolTip:="Your authorization username", IsAuth:=True), PXML, PClonable(Clone:=False)>
|
||||||
Friend ReadOnly Property AuthUserName As PropertyValue
|
Friend ReadOnly Property AuthUserName As PropertyValue
|
||||||
<PropertyOption(ControlText:="Password", ControlToolTip:="Your authorization password", IsAuth:=True), PXML, PClonable(Clone:=False)>
|
<PropertyOption(ControlText:="Password", ControlToolTip:="Your authorization password", IsAuth:=True), PXML, PClonable(Clone:=False)>
|
||||||
Friend ReadOnly Property AuthPassword As PropertyValue
|
Friend ReadOnly Property AuthPassword As PropertyValue
|
||||||
<PropertyOption(ControlText:="Client ID", ControlToolTip:="Your registered app client ID", IsAuth:=True), PXML, PClonable(Clone:=False)>
|
<PropertyOption(ControlText:="Client ID", ControlToolTip:="Your registered app client ID", IsAuth:=True), PXML, PClonable(Clone:=False)>
|
||||||
Friend ReadOnly Property ApiClientID As PropertyValue
|
Friend ReadOnly Property ApiClientID As PropertyValue
|
||||||
|
<PropertyUpdater(NameOf(ApiClientID))> Private Function ApiClientID_SetDefault() As Boolean
|
||||||
|
ApiClientID.Value = ApiClientID_Default
|
||||||
|
Return True
|
||||||
|
End Function
|
||||||
<PropertyOption(ControlText:="Client Secret", ControlToolTip:="Your registered app client secret", IsAuth:=True), PXML, PClonable(Clone:=False)>
|
<PropertyOption(ControlText:="Client Secret", ControlToolTip:="Your registered app client secret", IsAuth:=True), PXML, PClonable(Clone:=False)>
|
||||||
Friend ReadOnly Property ApiClientSecret As PropertyValue
|
Friend ReadOnly Property ApiClientSecret As PropertyValue
|
||||||
|
<PropertyUpdater(NameOf(ApiClientSecret))> Private Function ApiClientSecret_SetDefault() As Boolean
|
||||||
|
ApiClientSecret.Value = ApiClientSecret_Default
|
||||||
|
Return True
|
||||||
|
End Function
|
||||||
<PropertyOption(ControlText:="Bearer token",
|
<PropertyOption(ControlText:="Bearer token",
|
||||||
ControlToolTip:="Bearer token (can be null)." & vbCr &
|
ControlToolTip:="Bearer token (can be null)." & vbCr &
|
||||||
"If you are using cookies to download the timeline, it is highly recommended that you add a token." & vbCr &
|
"If you are using cookies to download the timeline, it is highly recommended that you add a token." & vbCr &
|
||||||
@@ -58,14 +70,59 @@ Namespace API.Reddit
|
|||||||
Return {AuthUserName.Value, AuthPassword.Value, ApiClientID.Value, ApiClientSecret.Value}.All(Function(v$) Not v.IsEmptyString)
|
Return {AuthUserName.Value, AuthPassword.Value, ApiClientID.Value, ApiClientSecret.Value}.All(Function(v$) Not v.IsEmptyString)
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
|
<PropertiesDataChecker({NameOf(AuthUserName), NameOf(AuthPassword), NameOf(ApiClientID), NameOf(ApiClientSecret),
|
||||||
|
NameOf(UseTokenForTimelines), NameOf(UseCookiesForTimelines)})>
|
||||||
|
Private Function OAuthCredentialsChecker(ByVal p As IEnumerable(Of PropertyData)) As Boolean
|
||||||
|
Const msgTitle$ = "OAuth credentials"
|
||||||
|
If p.ListExists Then
|
||||||
|
Dim useToken As Boolean = False, useCookies As Boolean = False
|
||||||
|
Dim d$ = String.Empty
|
||||||
|
Dim dCount As Byte = 0
|
||||||
|
Dim members As IEnumerable(Of MemberInfo) = GetObjectMembers(Me)
|
||||||
|
Dim getPropText As Func(Of String, String) = Function(name) members.First(Function(m) m.Name = name).GetCustomAttribute(Of PropertyOption).ControlText
|
||||||
|
Dim dataStr As Action(Of String, String) = Sub(dd, name) If dd.IsEmptyString Then d.StringAppendLine(getPropText(name)) : dCount += 1
|
||||||
|
For Each pp As PropertyData In p
|
||||||
|
Select Case pp.Name
|
||||||
|
Case NameOf(AuthUserName) : dataStr(pp.Value, NameOf(AuthUserName))
|
||||||
|
Case NameOf(AuthPassword) : dataStr(pp.Value, NameOf(AuthPassword))
|
||||||
|
Case NameOf(ApiClientID) : dataStr(pp.Value, NameOf(ApiClientID))
|
||||||
|
Case NameOf(ApiClientSecret) : dataStr(pp.Value, NameOf(ApiClientSecret))
|
||||||
|
Case NameOf(UseTokenForTimelines) : useToken = pp.Value
|
||||||
|
Case NameOf(UseCookiesForTimelines) : useCookies = pp.Value
|
||||||
|
Case Else : Throw New ArgumentException($"Property name '{pp.Name}' is not implemented", "Property Name")
|
||||||
|
End Select
|
||||||
|
Next
|
||||||
|
If d.IsEmptyString Then
|
||||||
|
If useToken And useCookies Then
|
||||||
|
Return True
|
||||||
|
Else
|
||||||
|
If Not useToken Then d.StringAppendLine(getPropText(NameOf(UseTokenForTimelines)))
|
||||||
|
If Not useCookies Then d.StringAppendLine(getPropText(NameOf(UseCookiesForTimelines)))
|
||||||
|
MsgBoxE({$"You need to check the following options:{vbCr}{d}", msgTitle}, vbCritical)
|
||||||
|
Return False
|
||||||
|
End If
|
||||||
|
ElseIf dCount = 4 Then
|
||||||
|
Return MsgBoxE({$"You haven't configured OAuth. It's highly recommended to use OAuth.{vbCr}Do you still want to continue?", msgTitle},
|
||||||
|
vbExclamation,,, {"Process", "Cancel"}) = 0
|
||||||
|
Else
|
||||||
|
MsgBoxE({$"You haven't filled in the following fields:{vbCr}{d}.{vbCr}{vbCr}" &
|
||||||
|
"To use OAuth authorization, you must fill in all authorization fields.", msgTitle}, vbCritical)
|
||||||
|
Return False
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Return True
|
||||||
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Other"
|
#Region "Other"
|
||||||
<PropertyOption(ControlText:="Use M3U8", ControlToolTip:="Use M3U8 or mp4 for Reddit videos", IsAuth:=False), PXML, PClonable>
|
<PropertyOption(ControlText:="Use M3U8", ControlToolTip:="Use M3U8 or mp4 for Reddit videos"), PXML, PClonable, HiddenControl>
|
||||||
Friend ReadOnly Property UseM3U8 As PropertyValue
|
Friend ReadOnly Property UseM3U8 As PropertyValue
|
||||||
<PropertyOption(ControlText:="Check image", ControlToolTip:="Check the image if it exists before downloading (it makes downloading very slow)", IsAuth:=False), PXML, PClonable>
|
<PropertyOption(ControlText:="Check image", ControlToolTip:="Check the image if it exists before downloading (it makes downloading very slow)"), PXML, PClonable, HiddenControl>
|
||||||
Friend ReadOnly Property CheckImage As PropertyValue
|
Friend ReadOnly Property CheckImage As PropertyValue
|
||||||
<PropertyOption(ControlText:="Check image: get original", ControlToolTip:="Get the original image if it exists", IsAuth:=False), PXML, PClonable>
|
<PropertyOption(ControlText:="Check image: get original", ControlToolTip:="Get the original image if it exists"), PXML, PClonable, HiddenControl>
|
||||||
Friend ReadOnly Property CheckImageReturnOrig As PropertyValue
|
Friend ReadOnly Property CheckImageReturnOrig As PropertyValue
|
||||||
|
<PropertyOption(ControlText:=DN.ConcurrentDownloadsCaption,
|
||||||
|
ControlToolTip:=DN.ConcurrentDownloadsToolTip, AllowNull:=False), PXML, TaskCounter, PClonable>
|
||||||
|
Friend ReadOnly Property ConcurrentDownloads As PropertyValue
|
||||||
#End Region
|
#End Region
|
||||||
#Region "IDownDetector Support"
|
#Region "IDownDetector Support"
|
||||||
Private ReadOnly Property IDownDetector_Value As Integer Implements DownDetector.IDownDetector.Value
|
Private ReadOnly Property IDownDetector_Value As Integer Implements DownDetector.IDownDetector.Value
|
||||||
@@ -117,6 +174,7 @@ Namespace API.Reddit
|
|||||||
UseM3U8 = New PropertyValue(True)
|
UseM3U8 = New PropertyValue(True)
|
||||||
CheckImage = New PropertyValue(False)
|
CheckImage = New PropertyValue(False)
|
||||||
CheckImageReturnOrig = New PropertyValue(True)
|
CheckImageReturnOrig = New PropertyValue(True)
|
||||||
|
ConcurrentDownloads = New PropertyValue(1)
|
||||||
|
|
||||||
MDD = New MyDownDetector(Me)
|
MDD = New MyDownDetector(Me)
|
||||||
|
|
||||||
@@ -124,10 +182,13 @@ Namespace API.Reddit
|
|||||||
ImageVideoContains = "reddit.com"
|
ImageVideoContains = "reddit.com"
|
||||||
UserRegex = RParams.DM("[htps:/]{7,8}.*?reddit.com/([user]{1,4})/([^/\?&]+)", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
|
UserRegex = RParams.DM("[htps:/]{7,8}.*?reddit.com/([user]{1,4})/([^/\?&]+)", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
|
||||||
End Sub
|
End Sub
|
||||||
Private Const SettingsVersionCurrent As Integer = 2
|
Private Const SettingsVersionCurrent As Integer = 3
|
||||||
Friend Overrides Sub EndInit()
|
Friend Overrides Sub EndInit()
|
||||||
If CInt(SettingsVersion.Value) < SettingsVersionCurrent Then
|
If CInt(SettingsVersion.Value) < SettingsVersionCurrent Then
|
||||||
SettingsVersion.Value = SettingsVersionCurrent
|
SettingsVersion.Value = SettingsVersionCurrent
|
||||||
|
UseM3U8.Value = True
|
||||||
|
CheckImage.Value = False
|
||||||
|
CheckImageReturnOrig.Value = True
|
||||||
BearerTokenUseCurl.Value = False
|
BearerTokenUseCurl.Value = False
|
||||||
End If
|
End If
|
||||||
MyBase.EndInit()
|
MyBase.EndInit()
|
||||||
@@ -165,6 +226,7 @@ Namespace API.Reddit
|
|||||||
End Sub
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
Friend Property SessionInterrupted As Boolean = False
|
Friend Property SessionInterrupted As Boolean = False
|
||||||
|
Friend Property RequestCount As Integer = 0
|
||||||
Friend Overrides Function ReadyToDownload(ByVal What As Download) As Boolean
|
Friend Overrides Function ReadyToDownload(ByVal What As Download) As Boolean
|
||||||
If What = Download.Main Then
|
If What = Download.Main Then
|
||||||
Return Not SessionInterrupted
|
Return Not SessionInterrupted
|
||||||
@@ -180,6 +242,7 @@ Namespace API.Reddit
|
|||||||
End Function
|
End Function
|
||||||
Friend Overrides Sub DownloadDone(ByVal What As Download)
|
Friend Overrides Sub DownloadDone(ByVal What As Download)
|
||||||
SessionInterrupted = False
|
SessionInterrupted = False
|
||||||
|
RequestCount = 0
|
||||||
MDD.Reset()
|
MDD.Reset()
|
||||||
MyBase.DownloadDone(What)
|
MyBase.DownloadDone(What)
|
||||||
End Sub
|
End Sub
|
||||||
@@ -233,23 +296,6 @@ Namespace API.Reddit
|
|||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Token"
|
#Region "Token"
|
||||||
<PropertiesDataChecker({NameOf(AuthUserName), NameOf(AuthPassword), NameOf(ApiClientID), NameOf(ApiClientSecret)})>
|
|
||||||
Private Function TokenPropertiesChecker(ByVal p As IEnumerable(Of PropertyData)) As Boolean
|
|
||||||
If p.ListExists Then
|
|
||||||
Dim wrong As New List(Of String)
|
|
||||||
For i% = 0 To p.Count - 1
|
|
||||||
If CStr(p(i).Value).IsEmptyString Then wrong.Add(p(i).Name)
|
|
||||||
Next
|
|
||||||
If wrong.Count > 0 And wrong.Count <> 4 Then
|
|
||||||
MsgBoxE({$"You have not completed the following fields: {wrong.ListToString}." & vbCr &
|
|
||||||
"To use OAuth authorization, all authorization fields must be filled in.", "Validate token fields"}, vbCritical)
|
|
||||||
Return False
|
|
||||||
Else
|
|
||||||
Return True
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
Return False
|
|
||||||
End Function
|
|
||||||
Private Function UpdateTokenIfRequired() As Boolean
|
Private Function UpdateTokenIfRequired() As Boolean
|
||||||
UpdateRedGifsToken()
|
UpdateRedGifsToken()
|
||||||
If (CBool(UseTokenForTimelines.Value) Or CBool(UseTokenForSavedPosts.Value)) AndAlso CredentialsExists Then
|
If (CBool(UseTokenForTimelines.Value) Or CBool(UseTokenForSavedPosts.Value)) AndAlso CredentialsExists Then
|
||||||
|
|||||||
@@ -8,19 +8,20 @@
|
|||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
Imports System.Net
|
Imports System.Net
|
||||||
Imports System.Threading
|
Imports System.Threading
|
||||||
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
|
Imports PersonalUtilities.Functions.XML
|
||||||
|
Imports PersonalUtilities.Tools.ImageRenderer
|
||||||
|
Imports PersonalUtilities.Tools.Web.Clients
|
||||||
|
Imports PersonalUtilities.Tools.Web.Clients.Base
|
||||||
|
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||||
Imports SCrawler.API.Base
|
Imports SCrawler.API.Base
|
||||||
Imports SCrawler.API.Reddit.RedditViewExchange
|
Imports SCrawler.API.Reddit.RedditViewExchange
|
||||||
Imports SCrawler.API.YouTube.Objects
|
Imports SCrawler.API.YouTube.Objects
|
||||||
Imports SCrawler.Plugin.Hosts
|
Imports SCrawler.Plugin.Hosts
|
||||||
Imports PersonalUtilities.Functions.XML
|
Imports CPeriod = SCrawler.API.Reddit.IRedditView.Period
|
||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
Imports CView = SCrawler.API.Reddit.IRedditView.View
|
||||||
Imports PersonalUtilities.Tools.ImageRenderer
|
|
||||||
Imports PersonalUtilities.Tools.Web.Clients
|
|
||||||
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
|
||||||
Imports UStates = SCrawler.API.Base.UserMedia.States
|
Imports UStates = SCrawler.API.Base.UserMedia.States
|
||||||
Imports UTypes = SCrawler.API.Base.UserMedia.Types
|
Imports UTypes = SCrawler.API.Base.UserMedia.Types
|
||||||
Imports CView = SCrawler.API.Reddit.IRedditView.View
|
|
||||||
Imports CPeriod = SCrawler.API.Reddit.IRedditView.Period
|
|
||||||
Namespace API.Reddit
|
Namespace API.Reddit
|
||||||
Friend Class UserData : Inherits UserDataBase : Implements IChannelLimits, IRedditView
|
Friend Class UserData : Inherits UserDataBase : Implements IChannelLimits, IRedditView
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
@@ -135,6 +136,7 @@ Namespace API.Reddit
|
|||||||
DownloadTextSpecialFolder = .DownloadTextSpecialFolder
|
DownloadTextSpecialFolder = .DownloadTextSpecialFolder
|
||||||
RedGifsAccount = .RedGifsAccount
|
RedGifsAccount = .RedGifsAccount
|
||||||
RedditAccount = .RedditAccount
|
RedditAccount = .RedditAccount
|
||||||
|
If TypeOf Options Is RedditViewExchange Then DirectCast(Options, RedditViewExchange).ApplyBase(Me)
|
||||||
End With
|
End With
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
@@ -268,6 +270,8 @@ Namespace API.Reddit
|
|||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
|
|
||||||
|
Responser.ProcessExceptionDecision = AddressOf Err429Process
|
||||||
|
|
||||||
_TotalPostsDownloaded = 0
|
_TotalPostsDownloaded = 0
|
||||||
If IsSavedPosts Then
|
If IsSavedPosts Then
|
||||||
Responser.DecodersError = EDP.ReturnValue
|
Responser.DecodersError = EDP.ReturnValue
|
||||||
@@ -303,6 +307,7 @@ Namespace API.Reddit
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "Download Functions (User, Channel)"
|
#Region "Download Functions (User, Channel)"
|
||||||
Private Err429Count As Integer = 0
|
Private Err429Count As Integer = 0
|
||||||
|
Private Err429TryAgain As Boolean = False
|
||||||
Private _TotalPostsDownloaded As Integer = 0
|
Private _TotalPostsDownloaded As Integer = 0
|
||||||
Private ReadOnly _CrossPosts As List(Of String)
|
Private ReadOnly _CrossPosts As List(Of String)
|
||||||
Private Const SiteGfycatKey As String = "gfycat"
|
Private Const SiteGfycatKey As String = "gfycat"
|
||||||
@@ -310,6 +315,28 @@ Namespace API.Reddit
|
|||||||
Private Const Node_CrosspostRootId As String = "crosspostRootId"
|
Private Const Node_CrosspostRootId As String = "crosspostRootId"
|
||||||
Private Const Node_CrosspostParentId As String = "crosspostParentId"
|
Private Const Node_CrosspostParentId As String = "crosspostParentId"
|
||||||
Private Const Node_CrosspostParent As String = "crosspost_parent"
|
Private Const Node_CrosspostParent As String = "crosspost_parent"
|
||||||
|
Private Sub Wait429()
|
||||||
|
With MySiteSettings
|
||||||
|
If Not Err429TryAgain Then .RequestCount += 1
|
||||||
|
Err429TryAgain = False
|
||||||
|
If (.RequestCount Mod 100) = 0 Then Thread.Sleep(60100)
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
|
Private Function Err429Process(ByVal Status As IResponserStatus, ByVal NullArg As Object, ByVal CurrErr As ErrorsDescriber) As ErrorsDescriber
|
||||||
|
If Not Status Is Nothing AndAlso Status.StatusCode = 429 Then
|
||||||
|
If Err429Count = 0 Then
|
||||||
|
Err429Count += 1
|
||||||
|
MySiteSettings.RequestCount = 100
|
||||||
|
Err429TryAgain = True
|
||||||
|
Return EDP.ReturnValue
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Return CurrErr
|
||||||
|
End Function
|
||||||
|
Private Sub Err429Reset()
|
||||||
|
Err429Count = 0
|
||||||
|
Err429TryAgain = False
|
||||||
|
End Sub
|
||||||
Private Sub DownloadDataUser(ByVal POST As String, ByVal Token As CancellationToken)
|
Private Sub DownloadDataUser(ByVal POST As String, ByVal Token As CancellationToken)
|
||||||
Dim eObj% = 0
|
Dim eObj% = 0
|
||||||
Dim round% = 0
|
Dim round% = 0
|
||||||
@@ -330,8 +357,10 @@ Namespace API.Reddit
|
|||||||
'URL = $"https://gateway.reddit.com/desktopapi/v1/user/{NameTrue}/posts?rtj=only&allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort={View}&t={Period}&layout=classic"
|
'URL = $"https://gateway.reddit.com/desktopapi/v1/user/{NameTrue}/posts?rtj=only&allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort={View}&t={Period}&layout=classic"
|
||||||
URL = $"https://oauth.reddit.com/user/{NameTrue}/submitted.json?rtj=only&allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort={View}&t={Period}&layout=classic"
|
URL = $"https://oauth.reddit.com/user/{NameTrue}/submitted.json?rtj=only&allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort={View}&t={Period}&layout=classic"
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
|
Wait429()
|
||||||
Dim r$ = Responser.GetResponse(URL)
|
Dim r$ = Responser.GetResponse(URL)
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
|
Err429Reset()
|
||||||
Using w As EContainer = JsonDocument.Parse(r).XmlIfNothing
|
Using w As EContainer = JsonDocument.Parse(r).XmlIfNothing
|
||||||
If w.Count > 0 Then
|
If w.Count > 0 Then
|
||||||
'n = w.GetNode(JsonNodesJson)
|
'n = w.GetNode(JsonNodesJson)
|
||||||
@@ -346,6 +375,7 @@ Namespace API.Reddit
|
|||||||
If CheckNode(.Self) Then
|
If CheckNode(.Self) Then
|
||||||
|
|
||||||
'Obtain post ID
|
'Obtain post ID
|
||||||
|
PostID = String.Empty
|
||||||
PostTmp = .Value("name") '.Name
|
PostTmp = .Value("name") '.Name
|
||||||
If PostTmp.IsEmptyString Then PostTmp = .Value("id")
|
If PostTmp.IsEmptyString Then PostTmp = .Value("id")
|
||||||
If PostTmp.IsEmptyString Then Continue For
|
If PostTmp.IsEmptyString Then Continue For
|
||||||
@@ -353,8 +383,9 @@ Namespace API.Reddit
|
|||||||
If IsCrossPost(.Self) Then
|
If IsCrossPost(.Self) Then
|
||||||
_CrossPosts.ListAddList({ .Value(Node_CrosspostRootId),
|
_CrossPosts.ListAddList({ .Value(Node_CrosspostRootId),
|
||||||
.Value(Node_CrosspostParentId),
|
.Value(Node_CrosspostParentId),
|
||||||
.Value(Node_CrosspostParent)}, LNC)
|
.Value(Node_CrosspostParent),
|
||||||
Continue For
|
PostTmp}, LNC)
|
||||||
|
If ParseUserMediaOnly Then Continue For
|
||||||
Else
|
Else
|
||||||
If Not _CrossPosts.Contains(PostTmp) Then PostID = PostTmp : PostTmp = String.Empty
|
If Not _CrossPosts.Contains(PostTmp) Then PostID = PostTmp : PostTmp = String.Empty
|
||||||
End If
|
End If
|
||||||
@@ -383,6 +414,8 @@ Namespace API.Reddit
|
|||||||
End Using
|
End Using
|
||||||
If POST.IsEmptyString And ExistsDetected Then Exit Sub
|
If POST.IsEmptyString And ExistsDetected Then Exit Sub
|
||||||
If Not _PostID().IsEmptyString And NewPostDetected Then DownloadDataUser(_PostID(), Token)
|
If Not _PostID().IsEmptyString And NewPostDetected Then DownloadDataUser(_PostID(), Token)
|
||||||
|
ElseIf Err429TryAgain Then
|
||||||
|
Continue Do
|
||||||
End If
|
End If
|
||||||
_completed = True
|
_completed = True
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
@@ -419,9 +452,11 @@ Namespace API.Reddit
|
|||||||
End If
|
End If
|
||||||
|
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
|
Wait429()
|
||||||
Dim r$ = Responser.GetResponse(URL)
|
Dim r$ = Responser.GetResponse(URL)
|
||||||
If IsSavedPosts Then Err429Count = 0
|
'If IsSavedPosts Then Err429Count = 0
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
|
Err429Reset()
|
||||||
Using w As EContainer = JsonDocument.Parse(r).XmlIfNothing
|
Using w As EContainer = JsonDocument.Parse(r).XmlIfNothing
|
||||||
If w.Count > 0 Then
|
If w.Count > 0 Then
|
||||||
n = w.GetNode(ChannelJsonNodes)
|
n = w.GetNode(ChannelJsonNodes)
|
||||||
@@ -478,6 +513,8 @@ Namespace API.Reddit
|
|||||||
End Using
|
End Using
|
||||||
If POST.IsEmptyString And ExistsDetected Then Exit Sub
|
If POST.IsEmptyString And ExistsDetected Then Exit Sub
|
||||||
If Not PostID.IsEmptyString And NewPostDetected Then DownloadDataChannel(PostID, Token)
|
If Not PostID.IsEmptyString And NewPostDetected Then DownloadDataChannel(PostID, Token)
|
||||||
|
ElseIf Err429TryAgain Then
|
||||||
|
Continue Do
|
||||||
End If
|
End If
|
||||||
_completed = True
|
_completed = True
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
@@ -495,11 +532,13 @@ Namespace API.Reddit
|
|||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "GetUserInfo"
|
#Region "GetUserInfo"
|
||||||
Private Sub GetUserInfo()
|
Private Sub GetUserInfo(Optional ByVal Round As Integer = 0)
|
||||||
Try
|
Try
|
||||||
If Not IsSavedPosts And ChannelInfo Is Nothing Then
|
If Not IsSavedPosts And ChannelInfo Is Nothing Then
|
||||||
|
Wait429()
|
||||||
Dim r$ = Responser.GetResponse($"https://reddit.com/{IIf(IsChannel, "r", "user")}/{NameTrue}/about.json",, EDP.ReturnValue)
|
Dim r$ = Responser.GetResponse($"https://reddit.com/{IIf(IsChannel, "r", "user")}/{NameTrue}/about.json",, EDP.ReturnValue)
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
|
Err429Reset()
|
||||||
Using j As EContainer = JsonDocument.Parse(r)
|
Using j As EContainer = JsonDocument.Parse(r)
|
||||||
If Not j Is Nothing AndAlso j.Contains({"data", "subreddit"}) Then
|
If Not j Is Nothing AndAlso j.Contains({"data", "subreddit"}) Then
|
||||||
If ID.IsEmptyString Then ID = j.Value({"data"}, "id")
|
If ID.IsEmptyString Then ID = j.Value({"data"}, "id")
|
||||||
@@ -515,6 +554,8 @@ Namespace API.Reddit
|
|||||||
End With
|
End With
|
||||||
End If
|
End If
|
||||||
End Using
|
End Using
|
||||||
|
ElseIf Err429TryAgain And Round < 2 Then
|
||||||
|
GetUserInfo(Round + 1)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
@@ -630,16 +671,21 @@ Namespace API.Reddit
|
|||||||
Else
|
Else
|
||||||
Dim tPostId$ = e.Value(Node_CrosspostParent).IfNullOrEmpty(e.Value(Node_CrosspostParentId)).IfNullOrEmpty(e.Value(Node_CrosspostRootId))
|
Dim tPostId$ = e.Value(Node_CrosspostParent).IfNullOrEmpty(e.Value(Node_CrosspostParentId)).IfNullOrEmpty(e.Value(Node_CrosspostRootId))
|
||||||
If Not PostID.IsEmptyString Then
|
If Not PostID.IsEmptyString Then
|
||||||
Dim r$ = Responser.GetResponse($"https://www.reddit.com/comments/{tPostId.Split("_").LastOrDefault}/.json",, EDP.ReturnValue)
|
For ri% = 0 To 1
|
||||||
If Not r.IsEmptyString Then
|
Wait429()
|
||||||
Using j As EContainer = JsonDocument.Parse(r, EDP.ReturnValue)
|
Dim r$ = Responser.GetResponse($"https://www.reddit.com/comments/{tPostId.Split("_").LastOrDefault}/.json",, EDP.ReturnValue)
|
||||||
If j.ListExists Then
|
If Not r.IsEmptyString Then
|
||||||
With j.ItemF({0, "data", "children", 0, "data"})
|
Err429Reset()
|
||||||
If .ListExists Then added = ParseContainer(.Self, PostID, PostDate, UserID, False, PostText)
|
Using j As EContainer = JsonDocument.Parse(r, EDP.ReturnValue)
|
||||||
End With
|
If j.ListExists Then
|
||||||
End If
|
With j.ItemF({0, "data", "children", 0, "data"})
|
||||||
End Using
|
If .ListExists Then added = ParseContainer(.Self, PostID, PostDate, UserID, False, PostText)
|
||||||
End If
|
End With
|
||||||
|
End If
|
||||||
|
End Using
|
||||||
|
Exit For
|
||||||
|
End If
|
||||||
|
Next
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
@@ -905,7 +951,10 @@ Namespace API.Reddit
|
|||||||
End If
|
End If
|
||||||
Continue For
|
Continue For
|
||||||
Else
|
Else
|
||||||
|
Wait429()
|
||||||
r = Responser.GetResponse(m.URL,, e)
|
r = Responser.GetResponse(m.URL,, e)
|
||||||
|
If r.IsEmptyString And Err429TryAgain Then _repeatForRedgifs = True
|
||||||
|
If Not r.IsEmptyString Then Err429Reset()
|
||||||
End If
|
End If
|
||||||
Loop While _repeatForRedgifs
|
Loop While _repeatForRedgifs
|
||||||
Else
|
Else
|
||||||
@@ -943,11 +992,13 @@ Namespace API.Reddit
|
|||||||
RedGifsResponser = RedGifsHost.Responser.Copy
|
RedGifsResponser = RedGifsHost.Responser.Copy
|
||||||
Dim respNoHeaders As Responser = Responser.Copy
|
Dim respNoHeaders As Responser = Responser.Copy
|
||||||
Dim m As UserMedia, m2 As UserMedia
|
Dim m As UserMedia, m2 As UserMedia
|
||||||
Dim r$, url$
|
Dim r$ = String.Empty, url$
|
||||||
|
Dim ri As Byte
|
||||||
Dim j As EContainer
|
Dim j As EContainer
|
||||||
Dim lastCount%, li%
|
Dim lastCount%, li%
|
||||||
Dim rv As New ErrorsDescriber(EDP.ReturnValue)
|
Dim rv As New ErrorsDescriber(EDP.ReturnValue)
|
||||||
respNoHeaders.Headers.Clear()
|
respNoHeaders.Headers.Clear()
|
||||||
|
respNoHeaders.ProcessExceptionDecision = AddressOf Err429Process
|
||||||
ProgressPre.ChangeMax(_ContentList.Count)
|
ProgressPre.ChangeMax(_ContentList.Count)
|
||||||
For i% = 0 To _ContentList.Count - 1
|
For i% = 0 To _ContentList.Count - 1
|
||||||
m = _ContentList(i)
|
m = _ContentList(i)
|
||||||
@@ -955,9 +1006,14 @@ Namespace API.Reddit
|
|||||||
If m.State = UStates.Missing AndAlso Not m.Post.ID.IsEmptyString Then
|
If m.State = UStates.Missing AndAlso Not m.Post.ID.IsEmptyString Then
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
url = $"https://www.reddit.com/comments/{m.Post.ID.Split("_").LastOrDefault}/.json"
|
url = $"https://www.reddit.com/comments/{m.Post.ID.Split("_").LastOrDefault}/.json"
|
||||||
r = Responser.GetResponse(url,, rv)
|
For ri = 0 To 1
|
||||||
If r.IsEmptyString Then r = respNoHeaders.GetResponse(url,, rv)
|
Wait429()
|
||||||
|
r = Responser.GetResponse(url,, rv)
|
||||||
|
If r.IsEmptyString Then Wait429() : r = respNoHeaders.GetResponse(url,, rv)
|
||||||
|
If Not (r.IsEmptyString And Err429TryAgain) Then Exit For
|
||||||
|
Next
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
|
Err429Reset()
|
||||||
j = JsonDocument.Parse(r, rv)
|
j = JsonDocument.Parse(r, rv)
|
||||||
If Not j Is Nothing Then
|
If Not j Is Nothing Then
|
||||||
If j.Count > 0 Then
|
If j.Count > 0 Then
|
||||||
@@ -1089,25 +1145,37 @@ Namespace API.Reddit
|
|||||||
ElseIf .StatusCode = HttpStatusCode.Forbidden Then '403
|
ElseIf .StatusCode = HttpStatusCode.Forbidden Then '403
|
||||||
UserSuspended = True
|
UserSuspended = True
|
||||||
ElseIf .StatusCode = HttpStatusCode.BadGateway Or .StatusCode = HttpStatusCode.ServiceUnavailable Then '502, 503
|
ElseIf .StatusCode = HttpStatusCode.BadGateway Or .StatusCode = HttpStatusCode.ServiceUnavailable Then '502, 503
|
||||||
MyMainLOG = $"{ToStringForLog()}: [{CInt(Responser.StatusCode)}] Reddit is currently unavailable"
|
LogError(Nothing, $"[{CInt(Responser.StatusCode)}] Reddit is currently unavailable")
|
||||||
Throw New Plugin.ExitException With {.Silent = True}
|
Throw New Plugin.ExitException With {.Silent = True}
|
||||||
ElseIf .StatusCode = HttpStatusCode.GatewayTimeout Then '504
|
ElseIf .StatusCode = HttpStatusCode.GatewayTimeout Then '504
|
||||||
Return 1
|
Return 1
|
||||||
ElseIf .StatusCode = HttpStatusCode.Unauthorized Then '401
|
ElseIf .StatusCode = HttpStatusCode.Unauthorized Then '401
|
||||||
MyMainLOG = $"{ToStringForLog()}: [{CInt(Responser.StatusCode)}] Reddit credentials expired"
|
LogError(Nothing, $"[{CInt(Responser.StatusCode)}] Reddit credentials expired")
|
||||||
MySiteSettings.SessionInterrupted = True
|
MySiteSettings.SessionInterrupted = True
|
||||||
Throw New Plugin.ExitException With {.Silent = True}
|
Throw New Plugin.ExitException With {.Silent = True}
|
||||||
ElseIf .StatusCode = HttpStatusCode.InternalServerError Then '500
|
ElseIf .StatusCode = HttpStatusCode.InternalServerError Then '500
|
||||||
If Not IsNothing(EObj) AndAlso IsNumeric(EObj) AndAlso CInt(EObj) = HttpStatusCode.InternalServerError Then Return 1
|
If Not IsNothing(EObj) AndAlso IsNumeric(EObj) AndAlso CInt(EObj) = HttpStatusCode.InternalServerError Then Return 1
|
||||||
Return HttpStatusCode.InternalServerError
|
Return HttpStatusCode.InternalServerError
|
||||||
ElseIf .StatusCode = 429 And IsSavedPosts And Err429Count = 0 Then
|
'ElseIf .StatusCode = 429 And IsSavedPosts And Err429Count = 0 Then '429 (saved)
|
||||||
Err429Count += 1
|
' Err429Count += 1
|
||||||
Return 429
|
' Return 429
|
||||||
ElseIf .StatusCode = 429 AndAlso
|
ElseIf .StatusCode = 429 Then '429 (all)
|
||||||
((Not IsSavedPosts And CBool(MySiteSettings.UseTokenForTimelines.Value)) Or (IsSavedPosts And CBool(MySiteSettings.UseTokenForSavedPosts.Value))) AndAlso
|
'If ((Not IsSavedPosts And CBool(MySiteSettings.UseTokenForTimelines.Value)) Or (IsSavedPosts And CBool(MySiteSettings.UseTokenForSavedPosts.Value))) AndAlso
|
||||||
Not MySiteSettings.CredentialsExists Then '429
|
' Not MySiteSettings.CredentialsExists Then
|
||||||
MyMainLOG = $"{ToStringForLog()}: [{CInt(Responser.StatusCode)}] You should use OAuth authorization or disable " &
|
' LogError(Nothing, "[429] You should use OAuth authorization or disable " &
|
||||||
IIf(IsSavedPosts, "token usage for downloading saved posts", "the use of token and cookies for downloading timelines")
|
' IIf(IsSavedPosts, "token usage for downloading saved posts", "the use of token and cookies for downloading timelines"))
|
||||||
|
'Else
|
||||||
|
' LogError(Nothing, "Too many requests (429). Try again later!")
|
||||||
|
'End If
|
||||||
|
'MySiteSettings.SessionInterrupted = True
|
||||||
|
'Throw New Plugin.ExitException With {.Silent = True}
|
||||||
|
If ((Not IsSavedPosts And CBool(MySiteSettings.UseTokenForTimelines.Value)) Or (IsSavedPosts And CBool(MySiteSettings.UseTokenForSavedPosts.Value))) AndAlso
|
||||||
|
Not MySiteSettings.CredentialsExists Then
|
||||||
|
LogError(Nothing, "[429] You should use OAuth authorization or disable " &
|
||||||
|
IIf(IsSavedPosts, "token usage for downloading saved posts", "the use of token and cookies for downloading timelines"))
|
||||||
|
Else
|
||||||
|
LogError(Nothing, "Too many requests (429). Try again later!")
|
||||||
|
End If
|
||||||
MySiteSettings.SessionInterrupted = True
|
MySiteSettings.SessionInterrupted = True
|
||||||
Throw New Plugin.ExitException With {.Silent = True}
|
Throw New Plugin.ExitException With {.Silent = True}
|
||||||
Else
|
Else
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ Namespace API.RedGifs
|
|||||||
Friend ReadOnly Property Token As PropertyValue
|
Friend ReadOnly Property Token As PropertyValue
|
||||||
<PropertyOption, ControlNumber(2), PClonable, HiddenControl>
|
<PropertyOption, ControlNumber(2), PClonable, HiddenControl>
|
||||||
Private ReadOnly Property UserAgent As PropertyValue
|
Private ReadOnly Property UserAgent As PropertyValue
|
||||||
|
<PXML> Friend ReadOnly Property UseCookies As PropertyValue
|
||||||
<PXML> Friend ReadOnly Property TokenLastDateUpdated As PropertyValue
|
<PXML> Friend ReadOnly Property TokenLastDateUpdated As PropertyValue
|
||||||
Private Const TokenName As String = "authorization"
|
Private Const TokenName As String = "authorization"
|
||||||
#Region "TokenUpdateInterval"
|
#Region "TokenUpdateInterval"
|
||||||
@@ -47,6 +48,7 @@ Namespace API.RedGifs
|
|||||||
End With
|
End With
|
||||||
Token = New PropertyValue(t, GetType(String), Sub(v) UpdateResponse(NameOf(Token), v))
|
Token = New PropertyValue(t, GetType(String), Sub(v) UpdateResponse(NameOf(Token), v))
|
||||||
UserAgent = New PropertyValue(If(Responser.UserAgentExists, Responser.UserAgent, String.Empty), GetType(String), Sub(v) UpdateResponse(NameOf(UserAgent), v))
|
UserAgent = New PropertyValue(If(Responser.UserAgentExists, Responser.UserAgent, String.Empty), GetType(String), Sub(v) UpdateResponse(NameOf(UserAgent), v))
|
||||||
|
UseCookies = New PropertyValue(False)
|
||||||
TokenLastDateUpdated = New PropertyValue(Now.AddYears(-1), GetType(Date))
|
TokenLastDateUpdated = New PropertyValue(Now.AddYears(-1), GetType(Date))
|
||||||
TokenUpdateInterval = New PropertyValue(60 * 12, GetType(Integer))
|
TokenUpdateInterval = New PropertyValue(60 * 12, GetType(Integer))
|
||||||
TokenUpdateIntervalProvider = New TokenRefreshIntervalProvider
|
TokenUpdateIntervalProvider = New TokenRefreshIntervalProvider
|
||||||
@@ -62,11 +64,16 @@ Namespace API.RedGifs
|
|||||||
Case NameOf(Token) : Responser.Headers.Add(TokenName, Value)
|
Case NameOf(Token) : Responser.Headers.Add(TokenName, Value)
|
||||||
Case NameOf(UserAgent) : Responser.UserAgent = Value
|
Case NameOf(UserAgent) : Responser.UserAgent = Value
|
||||||
End Select
|
End Select
|
||||||
Responser.SaveSettings()
|
Responser.SaveSettings(, New ErrorsDescriber(EDP.ReturnValue + If(_TokenUpdating, EDP.None, EDP.SendToLog)))
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Token updaters"
|
#Region "Token updaters"
|
||||||
|
Private _TokenUpdating As Boolean = False
|
||||||
Friend Function UpdateTokenIfRequired() As Boolean
|
Friend Function UpdateTokenIfRequired() As Boolean
|
||||||
|
While _TokenUpdating : Threading.Thread.Sleep(100) : End While
|
||||||
|
Return UpdateTokenIfRequired_Impl()
|
||||||
|
End Function
|
||||||
|
Private Function UpdateTokenIfRequired_Impl() As Boolean
|
||||||
Dim d As Date? = AConvert(Of Date)(TokenLastDateUpdated.Value, AModes.Var, Nothing)
|
Dim d As Date? = AConvert(Of Date)(TokenLastDateUpdated.Value, AModes.Var, Nothing)
|
||||||
If Not d.HasValue OrElse d.Value < Now.AddMinutes(-CInt(TokenUpdateInterval.Value)) Then
|
If Not d.HasValue OrElse d.Value < Now.AddMinutes(-CInt(TokenUpdateInterval.Value)) Then
|
||||||
Return UpdateToken()
|
Return UpdateToken()
|
||||||
@@ -76,7 +83,12 @@ Namespace API.RedGifs
|
|||||||
End Function
|
End Function
|
||||||
<PropertyUpdater(NameOf(Token))>
|
<PropertyUpdater(NameOf(Token))>
|
||||||
Friend Function UpdateToken() As Boolean
|
Friend Function UpdateToken() As Boolean
|
||||||
|
While _TokenUpdating : Threading.Thread.Sleep(100) : End While
|
||||||
|
Return UpdateToken_Impl()
|
||||||
|
End Function
|
||||||
|
Private Function UpdateToken_Impl() As Boolean
|
||||||
Try
|
Try
|
||||||
|
_TokenUpdating = True
|
||||||
Dim r$
|
Dim r$
|
||||||
Dim NewToken$ = String.Empty, NewAgent$ = String.Empty
|
Dim NewToken$ = String.Empty, NewAgent$ = String.Empty
|
||||||
Using resp As New Responser : r = resp.GetResponse("https://api.redgifs.com/v2/auth/temporary",, EDP.ThrowException) : End Using
|
Using resp As New Responser : r = resp.GetResponse("https://api.redgifs.com/v2/auth/temporary",, EDP.ThrowException) : End Using
|
||||||
@@ -98,6 +110,8 @@ Namespace API.RedGifs
|
|||||||
End If
|
End If
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
Return ErrorsDescriber.Execute(EDP.SendToLog, ex, "[API.RedGifs.SiteSettings.UpdateToken]", False)
|
Return ErrorsDescriber.Execute(EDP.SendToLog, ex, "[API.RedGifs.SiteSettings.UpdateToken]", False)
|
||||||
|
Finally
|
||||||
|
_TokenUpdating = False
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ Namespace API.RedGifs
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "Download functions"
|
#Region "Download functions"
|
||||||
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
||||||
|
If Not MySettings.UseCookies.Value Then Responser.Cookies.Clear()
|
||||||
DownloadData(1, Token)
|
DownloadData(1, Token)
|
||||||
End Sub
|
End Sub
|
||||||
Private Overloads Sub DownloadData(ByVal Page As Integer, ByVal Token As CancellationToken)
|
Private Overloads Sub DownloadData(ByVal Page As Integer, ByVal Token As CancellationToken)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Imports PersonalUtilities.Functions.RegularExpressions
|
|||||||
Imports PersonalUtilities.Tools
|
Imports PersonalUtilities.Tools
|
||||||
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||||
Namespace API.ThisVid
|
Namespace API.ThisVid
|
||||||
Friend Class UserData : Inherits UserDataBase
|
Friend Class UserData : Inherits UserDataBase : Implements IPSite
|
||||||
#Region "XML names"
|
#Region "XML names"
|
||||||
Private Const Name_DownloadPublic As String = "DownloadPublic"
|
Private Const Name_DownloadPublic As String = "DownloadPublic"
|
||||||
Private Const Name_DownloadPrivate As String = "DownloadPrivate"
|
Private Const Name_DownloadPrivate As String = "DownloadPrivate"
|
||||||
@@ -51,7 +51,7 @@ Namespace API.ThisVid
|
|||||||
Return {SearchRequestLabelName}
|
Return {SearchRequestLabelName}
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
Friend Property QueryString As String
|
Friend Property QueryString As String Implements IPSite.QueryString
|
||||||
Get
|
Get
|
||||||
If SiteMode = SiteModes.User Then
|
If SiteMode = SiteModes.User Then
|
||||||
Return String.Empty
|
Return String.Empty
|
||||||
@@ -161,15 +161,7 @@ Namespace API.ThisVid
|
|||||||
Return New UserExchangeOptions(Me)
|
Return New UserExchangeOptions(Me)
|
||||||
End Function
|
End Function
|
||||||
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
||||||
If Not Obj Is Nothing AndAlso TypeOf Obj Is UserExchangeOptions Then
|
If Not Obj Is Nothing AndAlso TypeOf Obj Is UserExchangeOptions Then DirectCast(Obj, UserExchangeOptions).Apply(Me)
|
||||||
With DirectCast(Obj, UserExchangeOptions)
|
|
||||||
DownloadPublic = .DownloadPublic
|
|
||||||
DownloadPrivate = .DownloadPrivate
|
|
||||||
DownloadFavourite = .DownloadFavourite
|
|
||||||
DifferentFolders = .DifferentFolders
|
|
||||||
QueryString = .QueryString
|
|
||||||
End With
|
|
||||||
End If
|
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
|
|||||||
@@ -6,9 +6,10 @@
|
|||||||
'
|
'
|
||||||
' This program is distributed in the hope that it will be useful,
|
' This program is distributed in the hope that it will be useful,
|
||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports SCrawler.API.Base
|
||||||
Imports SCrawler.Plugin.Attributes
|
Imports SCrawler.Plugin.Attributes
|
||||||
Namespace API.ThisVid
|
Namespace API.ThisVid
|
||||||
Friend Class UserExchangeOptions : Inherits Xhamster.UserExchangeOptions
|
Friend Class UserExchangeOptions : Inherits EditorExchangeOptionsBase_P
|
||||||
<PSetting(Caption:="Download public videos")>
|
<PSetting(Caption:="Download public videos")>
|
||||||
Friend Property DownloadPublic As Boolean = True
|
Friend Property DownloadPublic As Boolean = True
|
||||||
<PSetting(Caption:="Download private videos")>
|
<PSetting(Caption:="Download private videos")>
|
||||||
@@ -19,6 +20,7 @@ Namespace API.ThisVid
|
|||||||
Friend Property DifferentFolders As Boolean = True
|
Friend Property DifferentFolders As Boolean = True
|
||||||
Private ReadOnly Property MySettings As SiteSettings
|
Private ReadOnly Property MySettings As SiteSettings
|
||||||
Friend Sub New(ByVal s As SiteSettings)
|
Friend Sub New(ByVal s As SiteSettings)
|
||||||
|
MyBase.New(s)
|
||||||
DownloadPublic = s.DownloadPublic.Value
|
DownloadPublic = s.DownloadPublic.Value
|
||||||
DownloadPrivate = s.DownloadPrivate.Value
|
DownloadPrivate = s.DownloadPrivate.Value
|
||||||
DownloadFavourite = s.DownloadFavourite.Value
|
DownloadFavourite = s.DownloadFavourite.Value
|
||||||
@@ -26,12 +28,21 @@ Namespace API.ThisVid
|
|||||||
MySettings = s
|
MySettings = s
|
||||||
End Sub
|
End Sub
|
||||||
Friend Sub New(ByVal u As UserData)
|
Friend Sub New(ByVal u As UserData)
|
||||||
|
MyBase.New(u)
|
||||||
DownloadPublic = u.DownloadPublic
|
DownloadPublic = u.DownloadPublic
|
||||||
DownloadPrivate = u.DownloadPrivate
|
DownloadPrivate = u.DownloadPrivate
|
||||||
DownloadFavourite = u.DownloadFavourite
|
DownloadFavourite = u.DownloadFavourite
|
||||||
DifferentFolders = u.DifferentFolders
|
DifferentFolders = u.DifferentFolders
|
||||||
QueryString = u.QueryString
|
|
||||||
MySettings = u.HOST.Source
|
MySettings = u.HOST.Source
|
||||||
End Sub
|
End Sub
|
||||||
|
Friend Overrides Sub Apply(ByRef u As IPSite)
|
||||||
|
MyBase.Apply(u)
|
||||||
|
With DirectCast(u, UserData)
|
||||||
|
.DownloadPublic = DownloadPublic
|
||||||
|
.DownloadPrivate = DownloadPrivate
|
||||||
|
.DownloadFavourite = DownloadFavourite
|
||||||
|
.DifferentFolders = DifferentFolders
|
||||||
|
End With
|
||||||
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -422,7 +422,11 @@ Namespace API.TikTok
|
|||||||
End If
|
End If
|
||||||
If DateBefore.HasValue Then command &= $"--datebefore {DateBefore.Value.AddDays(1).ToStringDate(SimpleDateConverter)} "
|
If DateBefore.HasValue Then command &= $"--datebefore {DateBefore.Value.AddDays(1).ToStringDate(SimpleDateConverter)} "
|
||||||
If DateAfter.HasValue Then command &= $"--dateafter {DateAfter.Value.AddDays(-1).ToStringDate(SimpleDateConverter)} "
|
If DateAfter.HasValue Then command &= $"--dateafter {DateAfter.Value.AddDays(-1).ToStringDate(SimpleDateConverter)} "
|
||||||
If Not CBool(If(IsSingleObjectDownload, MySettings.UseParsedVideoDateSTD, MySettings.UseParsedVideoDate).Value) Then command &= "--no-mtime "
|
If Not CBool(If(IsSingleObjectDownload, MySettings.UseParsedVideoDateSTD, MySettings.UseParsedVideoDate).Value) Then
|
||||||
|
command &= "--no-mtime "
|
||||||
|
Else
|
||||||
|
command &= "--mtime "
|
||||||
|
End If
|
||||||
If MySettings.CookiesNetscapeFile.Exists Then command &= $"--no-cookies-from-browser --cookies ""{MySettings.CookiesNetscapeFile}"" "
|
If MySettings.CookiesNetscapeFile.Exists Then command &= $"--no-cookies-from-browser --cookies ""{MySettings.CookiesNetscapeFile}"" "
|
||||||
command &= $"{URL} "
|
command &= $"{URL} "
|
||||||
If SupportOutput Then
|
If SupportOutput Then
|
||||||
|
|||||||
@@ -50,6 +50,10 @@ Namespace API.Twitter
|
|||||||
Caption:="Force apply",
|
Caption:="Force apply",
|
||||||
ToolTip:="Force overrides the default parameters for the first download." & vbCr & "Applies to first download only.", LeftOffset:=DefaultOffset)>
|
ToolTip:="Force overrides the default parameters for the first download." & vbCr & "Applies to first download only.", LeftOffset:=DefaultOffset)>
|
||||||
Friend Overridable Property DownloadModelForceApply As Boolean = False
|
Friend Overridable Property DownloadModelForceApply As Boolean = False
|
||||||
|
<PSetting(Address:=SettingAddress.User,
|
||||||
|
Caption:="Large profile",
|
||||||
|
ToolTip:="This setting is only used on the first download and is intended to temporarily override the default site settings if they are incompatible with downloading large profiles. After the first download is complete, this option will be disabled and cannot be enabled again.")>
|
||||||
|
Friend Overridable Property LargeProfile As Boolean = False
|
||||||
Private ReadOnly Property MySettings As Object
|
Private ReadOnly Property MySettings As Object
|
||||||
Friend Sub New(ByVal s As SiteSettings)
|
Friend Sub New(ByVal s As SiteSettings)
|
||||||
MyBase.New(s)
|
MyBase.New(s)
|
||||||
@@ -76,6 +80,7 @@ Namespace API.Twitter
|
|||||||
UseMD5Comparison = u.UseMD5Comparison
|
UseMD5Comparison = u.UseMD5Comparison
|
||||||
RemoveExistingDuplicates = u.RemoveExistingDuplicates
|
RemoveExistingDuplicates = u.RemoveExistingDuplicates
|
||||||
MediaModelAllowNonUserTweets = u.MediaModelAllowNonUserTweets
|
MediaModelAllowNonUserTweets = u.MediaModelAllowNonUserTweets
|
||||||
|
LargeProfile = u.LargeProfile
|
||||||
If Not TypeOf u Is Mastodon.UserData Then
|
If Not TypeOf u Is Mastodon.UserData Then
|
||||||
DownloadModelForceApply = u.DownloadModelForceApply
|
DownloadModelForceApply = u.DownloadModelForceApply
|
||||||
DownloadBroadcasts = u.DownloadBroadcasts
|
DownloadBroadcasts = u.DownloadBroadcasts
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ Namespace API.Twitter
|
|||||||
Private Const CAT_DOWN As String = "Downloading"
|
Private Const CAT_DOWN As String = "Downloading"
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Auth"
|
#Region "Auth"
|
||||||
|
Friend Property CookiesUpdateForce As Boolean = False
|
||||||
<PropertyOption(ControlText:="Update cookies", ControlToolTip:="Update cookies during requests", IsAuth:=True), PXML, PClonable, HiddenControl>
|
<PropertyOption(ControlText:="Update cookies", ControlToolTip:="Update cookies during requests", IsAuth:=True), PXML, PClonable, HiddenControl>
|
||||||
Friend ReadOnly Property CookiesUpdate As PropertyValue
|
Friend ReadOnly Property CookiesUpdate As PropertyValue
|
||||||
<PropertyOption(ControlText:="Use UserAgent", ControlToolTip:="Use UserAgent in requests", IsAuth:=True), PXML, PClonable>
|
<PropertyOption(ControlText:="Use UserAgent", ControlToolTip:="Use UserAgent in requests", IsAuth:=True), PXML, PClonable>
|
||||||
@@ -45,9 +46,9 @@ Namespace API.Twitter
|
|||||||
<PropertyOption(ControlText:="UserAgent", IsAuth:=True, AllowNull:=True, InheritanceName:=SettingsCLS.HEADER_DEF_UserAgent),
|
<PropertyOption(ControlText:="UserAgent", IsAuth:=True, AllowNull:=True, InheritanceName:=SettingsCLS.HEADER_DEF_UserAgent),
|
||||||
PXML("UserAgent", OnlyForChecked:=True), PClonable>
|
PXML("UserAgent", OnlyForChecked:=True), PClonable>
|
||||||
Private ReadOnly Property UserAgentXML As PropertyValue
|
Private ReadOnly Property UserAgentXML As PropertyValue
|
||||||
Friend ReadOnly Property UserAgent As String
|
Friend ReadOnly Property UserAgent(Optional ByVal Force As Boolean = False) As String
|
||||||
Get
|
Get
|
||||||
If CBool(UserAgentUse.Value) AndAlso Not CStr(UserAgentXML.Value).IsEmptyString Then
|
If (CBool(UserAgentUse.Value) Or Force) AndAlso Not CStr(UserAgentXML.Value).IsEmptyString Then
|
||||||
Return UserAgentXML.Value
|
Return UserAgentXML.Value
|
||||||
Else
|
Else
|
||||||
Return String.Empty
|
Return String.Empty
|
||||||
@@ -73,6 +74,7 @@ Namespace API.Twitter
|
|||||||
#Region "Limits"
|
#Region "Limits"
|
||||||
Friend Const TimerDisabled As Integer = -1
|
Friend Const TimerDisabled As Integer = -1
|
||||||
Friend Const TimerFirstUseTheSame As Integer = -2
|
Friend Const TimerFirstUseTheSame As Integer = -2
|
||||||
|
Friend Const TimerDefault As Integer = 20
|
||||||
<PropertyOption(ControlText:="Abort on limit", ControlToolTip:="Abort twitter downloading when limit is reached", Category:=CAT_DOWN), PXML, PClonable>
|
<PropertyOption(ControlText:="Abort on limit", ControlToolTip:="Abort twitter downloading when limit is reached", Category:=CAT_DOWN), PXML, PClonable>
|
||||||
Friend Property AbortOnLimit As PropertyValue
|
Friend Property AbortOnLimit As PropertyValue
|
||||||
<PropertyOption(ControlText:="Download already parsed", ControlToolTip:="Download already parsed content on abort", Category:=CAT_DOWN), PXML, PClonable>
|
<PropertyOption(ControlText:="Download already parsed", ControlToolTip:="Download already parsed content on abort", Category:=CAT_DOWN), PXML, PClonable>
|
||||||
@@ -143,6 +145,7 @@ Namespace API.Twitter
|
|||||||
End Property
|
End Property
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
|
Private Const SettingsVersionCurrent As Integer = 1
|
||||||
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
|
||||||
MyBase.New(TwitterSite, "x.com", AccName, Temp, My.Resources.SiteResources.TwitterIcon_32, My.Resources.SiteResources.TwitterIcon_32.ToBitmap)
|
MyBase.New(TwitterSite, "x.com", AccName, Temp, My.Resources.SiteResources.TwitterIcon_32, My.Resources.SiteResources.TwitterIcon_32.ToBitmap)
|
||||||
|
|
||||||
@@ -153,7 +156,7 @@ Namespace API.Twitter
|
|||||||
.Cookies.Changed = False
|
.Cookies.Changed = False
|
||||||
End With
|
End With
|
||||||
|
|
||||||
UseNewIconXML = New PropertyValue(False)
|
UseNewIconXML = New PropertyValue(True)
|
||||||
|
|
||||||
CookiesUpdate = New PropertyValue(False)
|
CookiesUpdate = New PropertyValue(False)
|
||||||
UserAgentUse = New PropertyValue(True)
|
UserAgentUse = New PropertyValue(True)
|
||||||
@@ -192,6 +195,10 @@ Namespace API.Twitter
|
|||||||
UseNetscapeCookies = True
|
UseNetscapeCookies = True
|
||||||
End Sub
|
End Sub
|
||||||
Friend Overrides Sub EndInit()
|
Friend Overrides Sub EndInit()
|
||||||
|
If Not SettingsVersion.Value = SettingsVersionCurrent Then
|
||||||
|
UseNewIconXML.Value = True
|
||||||
|
SettingsVersion.Value = SettingsVersionCurrent
|
||||||
|
End If
|
||||||
UpdateIcon()
|
UpdateIcon()
|
||||||
MyBase.EndInit()
|
MyBase.EndInit()
|
||||||
End Sub
|
End Sub
|
||||||
@@ -223,7 +230,7 @@ Namespace API.Twitter
|
|||||||
End Sub
|
End Sub
|
||||||
Friend Overrides Sub DownloadDone(ByVal What As ISiteSettings.Download)
|
Friend Overrides Sub DownloadDone(ByVal What As ISiteSettings.Download)
|
||||||
If UserNumber > 0 Then
|
If UserNumber > 0 Then
|
||||||
If CBool(CookiesUpdate.Value) Then
|
If CBool(CookiesUpdate.Value) Or CookiesUpdateForce Then
|
||||||
With CookieKeeper.ParseNetscapeText(CookiesNetscapeFile.GetText(EDP.ReturnValue), EDP.ReturnValue)
|
With CookieKeeper.ParseNetscapeText(CookiesNetscapeFile.GetText(EDP.ReturnValue), EDP.ReturnValue)
|
||||||
If .ListExists Then
|
If .ListExists Then
|
||||||
Responser.Cookies.Clear()
|
Responser.Cookies.Clear()
|
||||||
@@ -250,6 +257,7 @@ Namespace API.Twitter
|
|||||||
End With
|
End With
|
||||||
End If
|
End If
|
||||||
LIMIT_ABORT = False
|
LIMIT_ABORT = False
|
||||||
|
CookiesUpdateForce = False
|
||||||
MyBase.DownloadDone(What)
|
MyBase.DownloadDone(What)
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ Namespace API.Twitter
|
|||||||
Private Const Name_GifsSpecialFolder As String = "GifsSpecialFolder"
|
Private Const Name_GifsSpecialFolder As String = "GifsSpecialFolder"
|
||||||
Private Const Name_GifsPrefix As String = "GifsPrefix"
|
Private Const Name_GifsPrefix As String = "GifsPrefix"
|
||||||
Private Const Name_IsCommunity As String = "IsCommunity"
|
Private Const Name_IsCommunity As String = "IsCommunity"
|
||||||
|
Private Const Name_LargeProfile As String = "LargeProfile"
|
||||||
Private Const Name_DownloadModelChanged As String = "DownloadModelChanged"
|
Private Const Name_DownloadModelChanged As String = "DownloadModelChanged"
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
@@ -62,6 +63,47 @@ Namespace API.Twitter
|
|||||||
Friend Property GifsSpecialFolder As String = String.Empty
|
Friend Property GifsSpecialFolder As String = String.Empty
|
||||||
Friend Property GifsPrefix As String = String.Empty
|
Friend Property GifsPrefix As String = String.Empty
|
||||||
Friend Property IsCommunity As Boolean = False
|
Friend Property IsCommunity As Boolean = False
|
||||||
|
#Region "LargeProfile"
|
||||||
|
Friend Property LargeProfile As Boolean = False
|
||||||
|
Private ReadOnly Property LargeProfileOverride As Boolean
|
||||||
|
Get
|
||||||
|
Return LargeProfile And Not FirstDownloadComplete
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Private ReadOnly Property CookiesUpdate As Boolean
|
||||||
|
Get
|
||||||
|
If LargeProfileOverride Then
|
||||||
|
MySettings.CookiesUpdateForce = True
|
||||||
|
Return True
|
||||||
|
Else
|
||||||
|
Return MySettings.CookiesUpdate.Value
|
||||||
|
End If
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Private ReadOnly Property UserAgent As String
|
||||||
|
Get
|
||||||
|
If LargeProfileOverride Then
|
||||||
|
Return MySettings.UserAgent(True).IfNullOrEmpty(Settings.UserAgent)
|
||||||
|
Else
|
||||||
|
Return MySettings.UserAgent
|
||||||
|
End If
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Private ReadOnly Property SleepTimerBeforeFirst As Integer
|
||||||
|
Get
|
||||||
|
Dim v% = MySettings.SleepTimerBeforeFirst.Value
|
||||||
|
If LargeProfileOverride And v <= 0 And v <> SiteSettings.TimerFirstUseTheSame Then v = SiteSettings.TimerFirstUseTheSame
|
||||||
|
Return v
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
Private ReadOnly Property SleepTimer As Integer
|
||||||
|
Get
|
||||||
|
Dim v% = MySettings.SleepTimer.Value
|
||||||
|
If LargeProfileOverride And v <= 0 Then v = SiteSettings.TimerDefault
|
||||||
|
Return v
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
#End Region
|
||||||
Private ReadOnly LikesPosts As List(Of String)
|
Private ReadOnly LikesPosts As List(Of String)
|
||||||
Private ReadOnly PostsKV As List(Of PKV)
|
Private ReadOnly PostsKV As List(Of PKV)
|
||||||
Private ReadOnly _DataNames As List(Of String)
|
Private ReadOnly _DataNames As List(Of String)
|
||||||
@@ -100,6 +142,7 @@ Namespace API.Twitter
|
|||||||
DownloadModelForceApply = .DownloadModelForceApply
|
DownloadModelForceApply = .DownloadModelForceApply
|
||||||
MediaModelAllowNonUserTweets = .MediaModelAllowNonUserTweets
|
MediaModelAllowNonUserTweets = .MediaModelAllowNonUserTweets
|
||||||
DownloadBroadcasts = .DownloadBroadcasts
|
DownloadBroadcasts = .DownloadBroadcasts
|
||||||
|
LargeProfile = .LargeProfile
|
||||||
Dim dModel As DownloadModels = DownloadModel
|
Dim dModel As DownloadModels = DownloadModel
|
||||||
If .DownloadModelMedia Then DownloadModel += DownloadModels.Media
|
If .DownloadModelMedia Then DownloadModel += DownloadModels.Media
|
||||||
If .DownloadModelProfile Or .DownloadBroadcasts Then DownloadModel += DownloadModels.Profile
|
If .DownloadModelProfile Or .DownloadBroadcasts Then DownloadModel += DownloadModels.Profile
|
||||||
@@ -155,6 +198,7 @@ Namespace API.Twitter
|
|||||||
StartMD5Checked = .Value(Name_StartMD5Checked).FromXML(Of Boolean)(False)
|
StartMD5Checked = .Value(Name_StartMD5Checked).FromXML(Of Boolean)(False)
|
||||||
MediaModelAllowNonUserTweets = .Value(Name_MediaModelAllowNonUserTweets).FromXML(Of Boolean)(False)
|
MediaModelAllowNonUserTweets = .Value(Name_MediaModelAllowNonUserTweets).FromXML(Of Boolean)(False)
|
||||||
IsCommunity = .Value(Name_IsCommunity).FromXML(Of Boolean)(False)
|
IsCommunity = .Value(Name_IsCommunity).FromXML(Of Boolean)(False)
|
||||||
|
LargeProfile = .Value(Name_LargeProfile).FromXML(Of Boolean)(False)
|
||||||
Else
|
Else
|
||||||
If Name.Contains("@") And Not IsCommunity Then
|
If Name.Contains("@") And Not IsCommunity Then
|
||||||
IsCommunity = True
|
IsCommunity = True
|
||||||
@@ -180,6 +224,7 @@ Namespace API.Twitter
|
|||||||
.Add(Name_StartMD5Checked, StartMD5Checked.BoolToInteger)
|
.Add(Name_StartMD5Checked, StartMD5Checked.BoolToInteger)
|
||||||
.Add(Name_MediaModelAllowNonUserTweets, MediaModelAllowNonUserTweets.BoolToInteger)
|
.Add(Name_MediaModelAllowNonUserTweets, MediaModelAllowNonUserTweets.BoolToInteger)
|
||||||
.Add(Name_IsCommunity, IsCommunity.BoolToInteger)
|
.Add(Name_IsCommunity, IsCommunity.BoolToInteger)
|
||||||
|
.Add(Name_LargeProfile, LargeProfile.BoolToInteger)
|
||||||
.Add(Name_TrueName, NameTrue(True))
|
.Add(Name_TrueName, NameTrue(True))
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
@@ -615,6 +660,7 @@ nextpIndx:
|
|||||||
End If
|
End If
|
||||||
DownloadModelForceApply = False
|
DownloadModelForceApply = False
|
||||||
FirstDownloadComplete = True
|
FirstDownloadComplete = True
|
||||||
|
LargeProfile = False
|
||||||
Catch jsonNull_ex As JsonDocumentException When jsonNull_ex.State = WebDocumentEventArgs.States.Error
|
Catch jsonNull_ex As JsonDocumentException When jsonNull_ex.State = WebDocumentEventArgs.States.Error
|
||||||
Throw New Plugin.ExitException("No deserialized data found")
|
Throw New Plugin.ExitException("No deserialized data found")
|
||||||
Catch limit_ex As TwitterLimitException
|
Catch limit_ex As TwitterLimitException
|
||||||
@@ -839,8 +885,8 @@ nextpIndx:
|
|||||||
End Class
|
End Class
|
||||||
Private ReadOnly Property SleepTimerValue(ByVal First As Boolean) As Integer
|
Private ReadOnly Property SleepTimerValue(ByVal First As Boolean) As Integer
|
||||||
Get
|
Get
|
||||||
Dim fTimer% = If(First, MySettings.SleepTimerBeforeFirst, MySettings.SleepTimer).Value
|
Dim fTimer% = If(First, SleepTimerBeforeFirst, SleepTimer)
|
||||||
If First And fTimer = SiteSettings.TimerFirstUseTheSame Then fTimer = MySettings.SleepTimer.Value
|
If First And fTimer = SiteSettings.TimerFirstUseTheSame Then fTimer = SleepTimer
|
||||||
Return fTimer
|
Return fTimer
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
@@ -1060,10 +1106,10 @@ nextpIndx:
|
|||||||
Private Function GdlCreateConf(ByVal Path As SFile) As SFile
|
Private Function GdlCreateConf(ByVal Path As SFile) As SFile
|
||||||
Try
|
Try
|
||||||
Dim conf As SFile = $"{Path.PathWithSeparator}TwitterGdlConfig.conf"
|
Dim conf As SFile = $"{Path.PathWithSeparator}TwitterGdlConfig.conf"
|
||||||
Dim __userAgent$ = MySettings.UserAgent
|
Dim __userAgent$ = UserAgent
|
||||||
If Not __userAgent.IsEmptyString Then __userAgent = $"""user-agent"": ""{__userAgent}"","
|
If Not __userAgent.IsEmptyString Then __userAgent = $"""user-agent"": ""{__userAgent}"","
|
||||||
Dim confText$ = "{""extractor"":{""cookies"": """ & MySettings.CookiesNetscapeFile.ToString.Replace("\", "/") &
|
Dim confText$ = "{""extractor"":{""cookies"": """ & MySettings.CookiesNetscapeFile.ToString.Replace("\", "/") &
|
||||||
$""",""cookies-update"": {IIf(CBool(MySettings.CookiesUpdate.Value), "true", "false")}," & __userAgent &
|
$""",""cookies-update"": {IIf(CookiesUpdate, "true", "false")}," & __userAgent &
|
||||||
"""twitter"":{""tweet-endpoint"": ""detail"",""cards"": false,""conversations"": true,""pinned"": false,""quoted"": false,""replies"": true,""retweets"": true,""strategy"": null,""text-tweets"": false,""twitpic"": false,""unique"": true,""users"": ""timeline"",""videos"": true}}}"
|
"""twitter"":{""tweet-endpoint"": ""detail"",""cards"": false,""conversations"": true,""pinned"": false,""quoted"": false,""replies"": true,""retweets"": true,""strategy"": null,""text-tweets"": false,""twitpic"": false,""unique"": true,""users"": ""timeline"",""videos"": true}}}"
|
||||||
If conf.Exists(SFO.Path, True, EDP.ThrowException) Then TextSaver.SaveTextToFile(confText, conf)
|
If conf.Exists(SFO.Path, True, EDP.ThrowException) Then TextSaver.SaveTextToFile(confText, conf)
|
||||||
If Not conf.Exists Then Throw New IO.FileNotFoundException("Can't find Twitter GDL config file", conf)
|
If Not conf.Exists Then Throw New IO.FileNotFoundException("Can't find Twitter GDL config file", conf)
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ Namespace API.XVIDEOS
|
|||||||
|
|
||||||
_SubscriptionsAllowed = True
|
_SubscriptionsAllowed = True
|
||||||
UrlPatternUser = "https://xvideos.com/{0}"
|
UrlPatternUser = "https://xvideos.com/{0}"
|
||||||
|
UserOptionsType = GetType(EditorExchangeOptionsBase_P)
|
||||||
End Sub
|
End Sub
|
||||||
Friend Overrides Sub EndInit()
|
Friend Overrides Sub EndInit()
|
||||||
Domains.PopulateInitialDomains(SiteDomains.Value)
|
Domains.PopulateInitialDomains(SiteDomains.Value)
|
||||||
@@ -152,14 +153,6 @@ Namespace API.XVIDEOS
|
|||||||
Return Nothing
|
Return Nothing
|
||||||
End Function
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
#Region "UserOptions"
|
|
||||||
Friend Overrides Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean)
|
|
||||||
If Options Is Nothing OrElse Not TypeOf Options Is UserExchangeOptions Then Options = New UserExchangeOptions
|
|
||||||
If OpenForm Then
|
|
||||||
Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using
|
|
||||||
End If
|
|
||||||
End Sub
|
|
||||||
#End Region
|
|
||||||
#Region "IDisposable Support"
|
#Region "IDisposable Support"
|
||||||
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
|
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
|
||||||
If Not disposedValue And disposing Then _Domains.Dispose()
|
If Not disposedValue And disposing Then _Domains.Dispose()
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ Imports PersonalUtilities.Tools.Web.Clients
|
|||||||
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
|
||||||
Namespace API.XVIDEOS
|
Namespace API.XVIDEOS
|
||||||
Friend Class UserData : Inherits UserDataBase
|
Friend Class UserData : Inherits UserDataBase : Implements IPSite
|
||||||
#Region "XML names"
|
#Region "XML names"
|
||||||
Private Const Name_PersonType As String = "PersonType"
|
Private Const Name_PersonType As String = "PersonType"
|
||||||
#End Region
|
#End Region
|
||||||
@@ -62,7 +62,7 @@ Namespace API.XVIDEOS
|
|||||||
Return {SearchRequestLabelName}
|
Return {SearchRequestLabelName}
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
Friend Property QueryString As String
|
Friend Property QueryString As String Implements IPSite.QueryString
|
||||||
Get
|
Get
|
||||||
If SiteMode = SiteModes.User Then
|
If SiteMode = SiteModes.User Then
|
||||||
Return String.Empty
|
Return String.Empty
|
||||||
@@ -82,10 +82,10 @@ Namespace API.XVIDEOS
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "Load"
|
#Region "Load"
|
||||||
Friend Overrides Function ExchangeOptionsGet() As Object
|
Friend Overrides Function ExchangeOptionsGet() As Object
|
||||||
Return New UserExchangeOptions(Me)
|
Return New EditorExchangeOptionsBase_P(Me)
|
||||||
End Function
|
End Function
|
||||||
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
||||||
If Not Obj Is Nothing AndAlso TypeOf Obj Is UserExchangeOptions Then QueryString = DirectCast(Obj, UserExchangeOptions).QueryString
|
If Not Obj Is Nothing AndAlso TypeOf Obj Is EditorExchangeOptionsBase_P Then DirectCast(Obj, EditorExchangeOptionsBase_P).Apply(Me)
|
||||||
End Sub
|
End Sub
|
||||||
Private Function UpdateUserOptions(Optional ByVal Force As Boolean = False, Optional ByVal NewUrl As String = Nothing) As Boolean
|
Private Function UpdateUserOptions(Optional ByVal Force As Boolean = False, Optional ByVal NewUrl As String = Nothing) As Boolean
|
||||||
If Not Force OrElse (Not SiteMode = SiteModes.User AndAlso Not NewUrl.IsEmptyString AndAlso MyFileSettings.Exists) Then
|
If Not Force OrElse (Not SiteMode = SiteModes.User AndAlso Not NewUrl.IsEmptyString AndAlso MyFileSettings.Exists) Then
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
' Copyright (C) 2023 Andy https://github.com/AAndyProgram
|
|
||||||
' This program is free software: you can redistribute it and/or modify
|
|
||||||
' it under the terms of the GNU General Public License as published by
|
|
||||||
' the Free Software Foundation, either version 3 of the License, or
|
|
||||||
' (at your option) any later version.
|
|
||||||
'
|
|
||||||
' This program is distributed in the hope that it will be useful,
|
|
||||||
' but WITHOUT ANY WARRANTY
|
|
||||||
Namespace API.XVIDEOS
|
|
||||||
Friend Class UserExchangeOptions : Inherits Xhamster.UserExchangeOptions
|
|
||||||
Friend Sub New()
|
|
||||||
End Sub
|
|
||||||
Friend Sub New(ByVal u As UserData)
|
|
||||||
QueryString = u.QueryString
|
|
||||||
End Sub
|
|
||||||
End Class
|
|
||||||
End Namespace
|
|
||||||
@@ -51,6 +51,7 @@ Namespace API.Xhamster
|
|||||||
UrlPatternUser = "https://xhamster.com/{0}/{1}"
|
UrlPatternUser = "https://xhamster.com/{0}/{1}"
|
||||||
UserRegex = RParams.DMS($"/({UserOption}|{ChannelOption}|{P_Creators})/([^/]+)(\Z|.*)", 0, RegexReturn.ListByMatch)
|
UserRegex = RParams.DMS($"/({UserOption}|{ChannelOption}|{P_Creators})/([^/]+)(\Z|.*)", 0, RegexReturn.ListByMatch)
|
||||||
ImageVideoContains = "xhamster"
|
ImageVideoContains = "xhamster"
|
||||||
|
UserOptionsType = GetType(UserExchangeOptions)
|
||||||
End Sub
|
End Sub
|
||||||
Friend Overrides Sub EndInit()
|
Friend Overrides Sub EndInit()
|
||||||
Domains.PopulateInitialDomains(SiteDomains.Value)
|
Domains.PopulateInitialDomains(SiteDomains.Value)
|
||||||
@@ -163,14 +164,6 @@ Namespace API.Xhamster
|
|||||||
Return Nothing
|
Return Nothing
|
||||||
End Function
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
#Region "UserOptions"
|
|
||||||
Friend Overrides Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean)
|
|
||||||
If Options Is Nothing OrElse Not TypeOf Options Is UserExchangeOptions Then Options = New UserExchangeOptions
|
|
||||||
If OpenForm Then
|
|
||||||
Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using
|
|
||||||
End If
|
|
||||||
End Sub
|
|
||||||
#End Region
|
|
||||||
#Region "IDisposable Support"
|
#Region "IDisposable Support"
|
||||||
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
|
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
|
||||||
If Not disposedValue And disposing Then _Domains.Dispose()
|
If Not disposedValue And disposing Then _Domains.Dispose()
|
||||||
|
|||||||
@@ -16,10 +16,11 @@ Imports PersonalUtilities.Tools.Web.Clients
|
|||||||
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
|
||||||
Namespace API.Xhamster
|
Namespace API.Xhamster
|
||||||
Friend Class UserData : Inherits UserDataBase
|
Friend Class UserData : Inherits UserDataBase : Implements IPSite
|
||||||
#Region "XML names"
|
#Region "XML names"
|
||||||
Private Const Name_Gender As String = "Gender"
|
Private Const Name_Gender As String = "Gender"
|
||||||
Private Const Name_IsCreator As String = "IsCreator"
|
Private Const Name_IsCreator As String = "IsCreator"
|
||||||
|
Private Const Name_GetMoments As String = "GetMoments"
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
Friend Overrides ReadOnly Property FeedIsUser As Boolean
|
Friend Overrides ReadOnly Property FeedIsUser As Boolean
|
||||||
@@ -29,6 +30,7 @@ Namespace API.Xhamster
|
|||||||
End Property
|
End Property
|
||||||
Friend Property IsChannel As Boolean = False
|
Friend Property IsChannel As Boolean = False
|
||||||
Friend Property IsCreator As Boolean = False
|
Friend Property IsCreator As Boolean = False
|
||||||
|
Friend Property GetMoments As Boolean = False
|
||||||
Friend Property Gender As String = String.Empty
|
Friend Property Gender As String = String.Empty
|
||||||
Friend Property SiteMode As SiteModes = SiteModes.User
|
Friend Property SiteMode As SiteModes = SiteModes.User
|
||||||
Friend Property Arguments As String = String.Empty
|
Friend Property Arguments As String = String.Empty
|
||||||
@@ -47,7 +49,7 @@ Namespace API.Xhamster
|
|||||||
Return {SearchRequestLabelName}
|
Return {SearchRequestLabelName}
|
||||||
End Get
|
End Get
|
||||||
End Property
|
End Property
|
||||||
Friend Property QueryString As String
|
Friend Property QueryString As String Implements IPSite.QueryString
|
||||||
Get
|
Get
|
||||||
If SiteMode = SiteModes.User Then
|
If SiteMode = SiteModes.User Then
|
||||||
Return String.Empty
|
Return String.Empty
|
||||||
@@ -143,6 +145,7 @@ Namespace API.Xhamster
|
|||||||
If Loading Then
|
If Loading Then
|
||||||
IsChannel = .Value(Name_IsChannel).FromXML(Of Boolean)(False)
|
IsChannel = .Value(Name_IsChannel).FromXML(Of Boolean)(False)
|
||||||
IsCreator = .Value(Name_IsCreator).FromXML(Of Boolean)(False)
|
IsCreator = .Value(Name_IsCreator).FromXML(Of Boolean)(False)
|
||||||
|
GetMoments = .Value(Name_GetMoments).FromXML(Of Boolean)(False)
|
||||||
Gender = .Value(Name_Gender)
|
Gender = .Value(Name_Gender)
|
||||||
SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User)
|
SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User)
|
||||||
Arguments = .Value(Name_Arguments)
|
Arguments = .Value(Name_Arguments)
|
||||||
@@ -155,6 +158,7 @@ Namespace API.Xhamster
|
|||||||
End If
|
End If
|
||||||
.Add(Name_IsChannel, IsChannel.BoolToInteger)
|
.Add(Name_IsChannel, IsChannel.BoolToInteger)
|
||||||
.Add(Name_IsCreator, IsCreator.BoolToInteger)
|
.Add(Name_IsCreator, IsCreator.BoolToInteger)
|
||||||
|
.Add(Name_GetMoments, GetMoments.BoolToInteger)
|
||||||
.Add(Name_TrueName, NameTrue(True))
|
.Add(Name_TrueName, NameTrue(True))
|
||||||
.Add(Name_Gender, Gender)
|
.Add(Name_Gender, Gender)
|
||||||
.Add(Name_SiteMode, CInt(SiteMode))
|
.Add(Name_SiteMode, CInt(SiteMode))
|
||||||
@@ -169,7 +173,7 @@ Namespace API.Xhamster
|
|||||||
Return New UserExchangeOptions(Me)
|
Return New UserExchangeOptions(Me)
|
||||||
End Function
|
End Function
|
||||||
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
|
||||||
If Not Obj Is Nothing AndAlso TypeOf Obj Is UserExchangeOptions Then QueryString = DirectCast(Obj, UserExchangeOptions).QueryString
|
If Not Obj Is Nothing AndAlso TypeOf Obj Is UserExchangeOptions Then DirectCast(Obj, UserExchangeOptions).Apply(Me)
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializer"
|
#Region "Initializer"
|
||||||
@@ -237,21 +241,23 @@ Namespace API.Xhamster
|
|||||||
_PageVideosRepeat = 0
|
_PageVideosRepeat = 0
|
||||||
SessionPosts.Clear()
|
SessionPosts.Clear()
|
||||||
Responser.CookiesAsHeader = True
|
Responser.CookiesAsHeader = True
|
||||||
If DownloadVideos Then DownloadData(1, True, Token)
|
If DownloadVideos Then DownloadData(1, True, False, Token)
|
||||||
|
If GetMoments Then DownloadData(1, True, True, Token)
|
||||||
If Not IsChannel And Not IsCreator And DownloadImages And Not IsSubscription Then
|
If Not IsChannel And Not IsCreator And DownloadImages And Not IsSubscription Then
|
||||||
DownloadData(1, False, Token)
|
DownloadData(1, False, False, Token)
|
||||||
ReparsePhoto(Token)
|
ReparsePhoto(Token)
|
||||||
End If
|
End If
|
||||||
Finally
|
Finally
|
||||||
Responser.CookiesAsHeader = False
|
Responser.CookiesAsHeader = False
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
Private Overloads Sub DownloadData(ByVal Page As Integer, ByVal IsVideo As Boolean, ByVal Token As CancellationToken)
|
Private Overloads Sub DownloadData(ByVal Page As Integer, ByVal IsVideo As Boolean, ByVal GetMoments As Boolean, ByVal Token As CancellationToken)
|
||||||
Dim URL$ = String.Empty
|
Dim URL$ = String.Empty
|
||||||
Try
|
Try
|
||||||
Dim MaxPage% = -1
|
Dim MaxPage% = -1
|
||||||
Dim Type As UTypes = IIf(IsVideo, UTypes.VideoPre, UTypes.Picture)
|
Dim Type As UTypes = IIf(IsVideo, UTypes.VideoPre, UTypes.Picture)
|
||||||
Dim mPages$ = IIf(IsVideo, "maxVideoPages", "maxPhotoPages")
|
Dim mPages$ = IIf(IsVideo, "maxVideoPages", "maxPhotoPages")
|
||||||
|
Dim specFolder$ = IIf(GetMoments, "Moments*", String.Empty)
|
||||||
Dim listNode$()
|
Dim listNode$()
|
||||||
Dim containerNodes As New List(Of String())
|
Dim containerNodes As New List(Of String())
|
||||||
Dim skipped As Boolean = False
|
Dim skipped As Boolean = False
|
||||||
@@ -271,6 +277,7 @@ Namespace API.Xhamster
|
|||||||
End If
|
End If
|
||||||
ElseIf Not SiteMode = SiteModes.Search Then
|
ElseIf Not SiteMode = SiteModes.Search Then
|
||||||
If IsVideo Then
|
If IsVideo Then
|
||||||
|
If GetMoments Then containerNodes.Add({"momentListComponent", "videoThumbProps"})
|
||||||
containerNodes.Add({"trendingVideoListComponent", "models"})
|
containerNodes.Add({"trendingVideoListComponent", "models"})
|
||||||
containerNodes.Add({"pagesCategoryComponent", "trendingVideoListProps", "models"})
|
containerNodes.Add({"pagesCategoryComponent", "trendingVideoListProps", "models"})
|
||||||
containerNodes.Add({"trendingVideoSectionComponent", "videoModels"})
|
containerNodes.Add({"trendingVideoSectionComponent", "videoModels"})
|
||||||
@@ -294,7 +301,7 @@ Namespace API.Xhamster
|
|||||||
ElseIf IsCreator Or SiteMode = SiteModes.Tags Or SiteMode = SiteModes.Categories Or SiteMode = SiteModes.Pornstars Then
|
ElseIf IsCreator Or SiteMode = SiteModes.Tags Or SiteMode = SiteModes.Categories Or SiteMode = SiteModes.Pornstars Then
|
||||||
URL = GetNonUserUrl(Page)
|
URL = GetNonUserUrl(Page)
|
||||||
Else
|
Else
|
||||||
URL = $"https://xhamster.com/users/{NameTrue}/{IIf(IsVideo, "videos", "photos")}{IIf(Page = 1, String.Empty, $"/{Page}")}"
|
URL = $"https://xhamster.com/users/{NameTrue}/{If(GetMoments, "moments", IIf(IsVideo, "videos", "photos"))}{IIf(Page = 1, String.Empty, $"/{Page}")}"
|
||||||
End If
|
End If
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
|
|
||||||
@@ -314,7 +321,7 @@ Namespace API.Xhamster
|
|||||||
ProgressPre.ChangeMax(.Count)
|
ProgressPre.ChangeMax(.Count)
|
||||||
For Each e As EContainer In .Self
|
For Each e As EContainer In .Self
|
||||||
ProgressPre.Perform()
|
ProgressPre.Perform()
|
||||||
m = ExtractMedia(e, Type)
|
m = ExtractMedia(e, Type,,,, specFolder)
|
||||||
If Not m.URL.IsEmptyString Then
|
If Not m.URL.IsEmptyString Then
|
||||||
pids.ListAddValue(m.Post.ID, LNC)
|
pids.ListAddValue(m.Post.ID, LNC)
|
||||||
If m.File.IsEmptyString Then Continue For
|
If m.File.IsEmptyString Then Continue For
|
||||||
@@ -374,7 +381,7 @@ Namespace API.Xhamster
|
|||||||
(MaxPage = -1 Or Page < MaxPage) And
|
(MaxPage = -1 Or Page < MaxPage) And
|
||||||
((Not _TempMediaList.Count = cBefore Or skipped) And (IsUser Or Page < 1000))
|
((Not _TempMediaList.Count = cBefore Or skipped) And (IsUser Or Page < 1000))
|
||||||
) Or
|
) Or
|
||||||
(IsChannel Or (Not IsUser And Page < 1000 And prevPostsFound And Not newPostsFound))) Then DownloadData(Page + 1, IsVideo, Token)
|
(IsChannel Or (Not IsUser And Page < 1000 And prevPostsFound And Not newPostsFound))) Then DownloadData(Page + 1, IsVideo, GetMoments, Token)
|
||||||
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
|
||||||
@@ -396,7 +403,7 @@ Namespace API.Xhamster
|
|||||||
If Not m.URL_BASE.IsEmptyString Then
|
If Not m.URL_BASE.IsEmptyString Then
|
||||||
m2 = Nothing
|
m2 = Nothing
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
If GetM3U8(m2, m.URL_BASE) Then
|
If GetM3U8(m2, m.URL_BASE, m.SpecialFolder) Then
|
||||||
m2.URL_BASE = m.URL_BASE
|
m2.URL_BASE = m.URL_BASE
|
||||||
_TempMediaList(i) = m2
|
_TempMediaList(i) = m2
|
||||||
Else
|
Else
|
||||||
@@ -426,7 +433,7 @@ Namespace API.Xhamster
|
|||||||
If Not m.URL_BASE.IsEmptyString Then
|
If Not m.URL_BASE.IsEmptyString Then
|
||||||
m2 = Nothing
|
m2 = Nothing
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
If GetM3U8(m2, m.URL_BASE) Then
|
If GetM3U8(m2, m.URL_BASE, String.Empty) Then
|
||||||
m2.URL_BASE = m.URL_BASE
|
m2.URL_BASE = m.URL_BASE
|
||||||
_TempMediaList(i) = m2
|
_TempMediaList(i) = m2
|
||||||
c += 1
|
c += 1
|
||||||
@@ -507,7 +514,7 @@ Namespace API.Xhamster
|
|||||||
If m.State = UserMedia.States.Missing AndAlso Not m.URL_BASE.IsEmptyString Then
|
If m.State = UserMedia.States.Missing AndAlso Not m.URL_BASE.IsEmptyString Then
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
m2 = Nothing
|
m2 = Nothing
|
||||||
If GetM3U8(m2, m.URL_BASE) Then
|
If GetM3U8(m2, m.URL_BASE, m.SpecialFolder) Then
|
||||||
m2.URL_BASE = m.URL_BASE
|
m2.URL_BASE = m.URL_BASE
|
||||||
m2.State = UserMedia.States.Missing
|
m2.State = UserMedia.States.Missing
|
||||||
m2.Attempts = m.Attempts
|
m2.Attempts = m.Attempts
|
||||||
@@ -528,7 +535,7 @@ Namespace API.Xhamster
|
|||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "GetM3U8"
|
#Region "GetM3U8"
|
||||||
Private Overloads Function GetM3U8(ByRef m As UserMedia, ByVal URL As String) As Boolean
|
Private Overloads Function GetM3U8(ByRef m As UserMedia, ByVal URL As String, ByVal SpecFolder As String) As Boolean
|
||||||
Try
|
Try
|
||||||
If Not URL.IsEmptyString Then
|
If Not URL.IsEmptyString Then
|
||||||
Dim r$ = Responser.GetResponse(URL)
|
Dim r$ = Responser.GetResponse(URL)
|
||||||
@@ -536,7 +543,7 @@ Namespace API.Xhamster
|
|||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
Using j As EContainer = JsonDocument.Parse(r)
|
Using j As EContainer = JsonDocument.Parse(r)
|
||||||
If j.ListExists Then
|
If j.ListExists Then
|
||||||
m = ExtractMedia(j("videoModel"), UTypes.VideoPre)
|
m = ExtractMedia(j("videoModel"), UTypes.VideoPre,,,, SpecFolder)
|
||||||
m.URL_BASE = URL
|
m.URL_BASE = URL
|
||||||
If IsSubscription Then
|
If IsSubscription Then
|
||||||
With j("videoModel")
|
With j("videoModel")
|
||||||
@@ -546,7 +553,7 @@ Namespace API.Xhamster
|
|||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
Else
|
Else
|
||||||
Return GetM3U8(m, j)
|
Return GetM3U8(m, j, SpecFolder)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End Using
|
End Using
|
||||||
@@ -557,7 +564,7 @@ Namespace API.Xhamster
|
|||||||
Return ErrorsDescriber.Execute(EDP.ReturnValue, ex, $"[{ToStringForLog()}]: API.Xhamster.GetM3U8({URL})", False)
|
Return ErrorsDescriber.Execute(EDP.ReturnValue, ex, $"[{ToStringForLog()}]: API.Xhamster.GetM3U8({URL})", False)
|
||||||
End Try
|
End Try
|
||||||
End Function
|
End Function
|
||||||
Private Overloads Function GetM3U8(ByRef m As UserMedia, ByVal j As EContainer) As Boolean
|
Private Overloads Function GetM3U8(ByRef m As UserMedia, ByVal j As EContainer, ByVal SpecFolder As String) As Boolean
|
||||||
Dim node As EContainer = j({"xplayerSettings", "sources", "hls"})
|
Dim node As EContainer = j({"xplayerSettings", "sources", "hls"})
|
||||||
If node.ListExists Then
|
If node.ListExists Then
|
||||||
Dim url$ = node.GetNode({New NodeParams("url", True, True, True, True, 2)}).XmlIfNothingValue
|
Dim url$ = node.GetNode({New NodeParams("url", True, True, True, True, 2)}).XmlIfNothingValue
|
||||||
@@ -583,7 +590,8 @@ Namespace API.Xhamster
|
|||||||
#End Region
|
#End Region
|
||||||
#Region "Create media"
|
#Region "Create media"
|
||||||
Private Function ExtractMedia(ByVal j As EContainer, ByVal t As UTypes, Optional ByVal UrlNode As String = "pageURL",
|
Private Function ExtractMedia(ByVal j As EContainer, ByVal t As UTypes, Optional ByVal UrlNode As String = "pageURL",
|
||||||
Optional ByVal DetectGalery As Boolean = True, Optional ByVal PostDate As Date? = Nothing) As UserMedia
|
Optional ByVal DetectGalery As Boolean = True, Optional ByVal PostDate As Date? = Nothing,
|
||||||
|
Optional ByVal SpecFolder As String = Nothing) As UserMedia
|
||||||
If Not j Is Nothing Then
|
If Not j Is Nothing Then
|
||||||
Dim m As New UserMedia(j.Value(UrlNode).Replace("\", String.Empty), t) With {
|
Dim m As New UserMedia(j.Value(UrlNode).Replace("\", String.Empty), t) With {
|
||||||
.Post = New UserPost With {
|
.Post = New UserPost With {
|
||||||
@@ -626,6 +634,8 @@ Namespace API.Xhamster
|
|||||||
End If
|
End If
|
||||||
m.File.Separator = "\"
|
m.File.Separator = "\"
|
||||||
End If
|
End If
|
||||||
|
If Not SpecFolder.IsEmptyString Then _
|
||||||
|
m.SpecialFolder = $"{m.SpecialFolder.StringTrimEnd("\")}{IIf(m.SpecialFolder.IsEmptyString, String.Empty, "\")}{SpecFolder}"
|
||||||
Return m
|
Return m
|
||||||
Else
|
Else
|
||||||
Return Nothing
|
Return Nothing
|
||||||
|
|||||||
@@ -6,16 +6,22 @@
|
|||||||
'
|
'
|
||||||
' This program is distributed in the hope that it will be useful,
|
' This program is distributed in the hope that it will be useful,
|
||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports SCrawler.API.Base
|
||||||
Imports SCrawler.Plugin.Attributes
|
Imports SCrawler.Plugin.Attributes
|
||||||
Namespace API.Xhamster
|
Namespace API.Xhamster
|
||||||
Friend Class UserExchangeOptions
|
Friend NotInheritable Class UserExchangeOptions : Inherits API.Base.EditorExchangeOptionsBase_P
|
||||||
<PSetting(Address:=SettingAddress.User, Caption:="Query",
|
<PSetting(Address:=SettingAddress.User, Caption:="Get moments")>
|
||||||
ToolTip:="Query string. Don't change this field when creating a user! Change it only for the same request.")>
|
Friend Property GetMoments As Boolean = False
|
||||||
Friend Property QueryString As String
|
|
||||||
Friend Sub New()
|
Friend Sub New()
|
||||||
|
MyBase.New
|
||||||
End Sub
|
End Sub
|
||||||
Friend Sub New(ByVal u As UserData)
|
Friend Sub New(ByVal u As IPSite)
|
||||||
QueryString = u.QueryString
|
MyBase.New(DirectCast(u, UserData))
|
||||||
|
GetMoments = DirectCast(u, UserData).GetMoments
|
||||||
|
End Sub
|
||||||
|
Friend Overrides Sub Apply(ByRef u As IPSite)
|
||||||
|
MyBase.Apply(u)
|
||||||
|
DirectCast(u, UserData).GetMoments = GetMoments
|
||||||
End Sub
|
End Sub
|
||||||
End Class
|
End Class
|
||||||
End Namespace
|
End Namespace
|
||||||
@@ -7,9 +7,10 @@
|
|||||||
' This program is distributed in the hope that it will be useful,
|
' This program is distributed in the hope that it will be useful,
|
||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
Imports System.ComponentModel
|
Imports System.ComponentModel
|
||||||
Imports SCrawler.API.Base
|
Imports System.IO
|
||||||
Imports PersonalUtilities.Forms
|
Imports PersonalUtilities.Forms
|
||||||
Imports PersonalUtilities.Tools
|
Imports PersonalUtilities.Tools
|
||||||
|
Imports SCrawler.API.Base
|
||||||
Imports UserMediaD = SCrawler.DownloadObjects.TDownloader.UserMediaD
|
Imports UserMediaD = SCrawler.DownloadObjects.TDownloader.UserMediaD
|
||||||
Namespace DownloadObjects
|
Namespace DownloadObjects
|
||||||
<ToolboxItem(False), DesignTimeVisible(False)>
|
<ToolboxItem(False), DesignTimeVisible(False)>
|
||||||
@@ -137,28 +138,18 @@ Namespace DownloadObjects
|
|||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Converter"
|
#Region "Converter"
|
||||||
Private Const ExtWebp As String = "webp"
|
Private Const ExtWebp As String = UserImage.ExtWebp
|
||||||
Private Const ExtJpg As String = "jpg"
|
Private Const ExtJpg As String = UserImage.ExtJpg
|
||||||
Private Function ConvertWebp(ByVal file As SFile, Optional ByVal NewCacheDir As Boolean = False) As SFile
|
Private Function ConvertOptional(ByVal file As SFile, ByVal GetError As Boolean, ByRef IsWebP As Boolean) As ImageRenderer
|
||||||
If file.Extension = ExtWebp Then
|
Dim ir As ImageRenderer2 = Nothing
|
||||||
If Settings.FfmpegFile.Exists Then
|
Try
|
||||||
Dim dir As SFile
|
ir = New ImageRenderer2(file, EDP.ThrowException)
|
||||||
If NewCacheDir Then dir = Settings.Cache.NewPath Else dir = Settings.Cache
|
If ir.HasError Then Throw If(ir.ImgErr, New Exception) Else Return ir
|
||||||
Dim f As SFile = file
|
Catch ex As Exception
|
||||||
f.Path = dir.Path
|
IsWebP = ir?.NativeFormat.IfNullOrEmpty(ExtJpg) = ExtWebp
|
||||||
f.Extension = ExtJpg
|
ir.DisposeIfReady
|
||||||
Using imgBatch As New BatchExecutor
|
If GetError Then Throw ex Else Return Nothing
|
||||||
With imgBatch
|
End Try
|
||||||
.ChangeDirectory(dir)
|
|
||||||
.Execute($"""{Settings.FfmpegFile}"" -i ""{file}"" ""{f}""")
|
|
||||||
End With
|
|
||||||
End Using
|
|
||||||
If f.Exists Then Return f
|
|
||||||
End If
|
|
||||||
Else
|
|
||||||
Return file
|
|
||||||
End If
|
|
||||||
Return Nothing
|
|
||||||
End Function
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Initializers"
|
#Region "Initializers"
|
||||||
@@ -174,6 +165,42 @@ Namespace DownloadObjects
|
|||||||
Public Sub New()
|
Public Sub New()
|
||||||
InitializeComponent()
|
InitializeComponent()
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Class ImageRenderer2 : Inherits ImageRenderer
|
||||||
|
Friend NativeFormat As String = Nothing
|
||||||
|
Friend ImgErr As Exception = Nothing
|
||||||
|
Friend Sub New(ByVal ImgPath As SFile, Optional ByVal e As ErrorsDescriber = Nothing)
|
||||||
|
MyBase.New()
|
||||||
|
Try
|
||||||
|
If ImgPath.Exists(SFO.File, False) Then
|
||||||
|
OriginalImageBytes = SFile.GetBytes(ImgPath, EDP.ThrowException)
|
||||||
|
Try
|
||||||
|
OriginalImage = GetImage(OriginalImageBytes)
|
||||||
|
Catch exInternal As Exception
|
||||||
|
HasError = True
|
||||||
|
ImgErr = exInternal
|
||||||
|
NativeFormat = GetTrueFormat(OriginalImageBytes, EDP.ReturnValue)
|
||||||
|
End Try
|
||||||
|
End If
|
||||||
|
Address = ImgPath
|
||||||
|
Catch ex As Exception
|
||||||
|
HasError = True
|
||||||
|
NativeFormat = GetTrueFormat(OriginalImageBytes, EDP.ReturnValue)
|
||||||
|
If Not e.Exists Then e = EDP.ThrowException
|
||||||
|
ErrorsDescriber.Execute(e, ex, $"ImageRenderer2.New({ImgPath})")
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
Friend Shared Function GetTrueFormat(ByVal Img() As Byte, Optional ByVal e As ErrorsDescriber = Nothing) As String
|
||||||
|
Try
|
||||||
|
Using ms As New MemoryStream(Img, 0, Img.Length)
|
||||||
|
Return System.Windows.Media.Imaging.BitmapDecoder.Create(ms, Windows.Media.Imaging.BitmapCreateOptions.PreservePixelFormat,
|
||||||
|
Windows.Media.Imaging.BitmapCacheOption.OnLoad).Metadata.Format
|
||||||
|
End Using
|
||||||
|
Catch ex As Exception
|
||||||
|
If Not e.Exists Then e = EDP.ThrowException
|
||||||
|
Return ErrorsDescriber.Execute(e, ex, "[ImageRenderer2.GetTrueFormat()]")
|
||||||
|
End Try
|
||||||
|
End Function
|
||||||
|
End Class
|
||||||
Friend Sub New(ByVal Media As UserMediaD, ByVal Width As Integer, ByVal Height As Integer, ByVal IsSession As Boolean, ByVal ExtractText As Boolean)
|
Friend Sub New(ByVal Media As UserMediaD, ByVal Width As Integer, ByVal Height As Integer, ByVal IsSession As Boolean, ByVal ExtractText As Boolean)
|
||||||
Try
|
Try
|
||||||
InitializeComponent()
|
InitializeComponent()
|
||||||
@@ -211,7 +238,7 @@ Namespace DownloadObjects
|
|||||||
End With
|
End With
|
||||||
If Not imgFile.Exists Then
|
If Not imgFile.Exists Then
|
||||||
Settings.Cache.Validate()
|
Settings.Cache.Validate()
|
||||||
If GetWebFile(Media.Data.URL, imgFile, EDP.None) AndAlso imgFile.Exists Then File = ConvertWebp(imgFile)
|
If GetWebFile(Media.Data.URL, imgFile, EDP.None) AndAlso imgFile.Exists Then File = UserImage.ConvertWebp(imgFile, Nothing)
|
||||||
Else
|
Else
|
||||||
File = imgFile
|
File = imgFile
|
||||||
End If
|
End If
|
||||||
@@ -260,10 +287,17 @@ Namespace DownloadObjects
|
|||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
tmpMediaFile = ConvertWebp(tmpMediaFile, True)
|
Dim webpConverted As Boolean = False
|
||||||
|
Dim isWebp As Boolean = False
|
||||||
|
tmpMediaFile = UserImage.ConvertWebp(tmpMediaFile, Nothing,,, webpConverted)
|
||||||
If tmpMediaFile.IsEmptyString Then Throw New ArgumentNullException With {.HelpLink = 1}
|
If tmpMediaFile.IsEmptyString Then Throw New ArgumentNullException With {.HelpLink = 1}
|
||||||
Try
|
Try
|
||||||
MyImage = New ImageRenderer(tmpMediaFile, EDP.ThrowException)
|
For kConv As Byte = 0 To 1
|
||||||
|
If kConv = 1 Then tmpMediaFile = UserImage.ConvertWebp(tmpMediaFile, Nothing, True, isWebp, webpConverted)
|
||||||
|
If Not tmpMediaFile.IsEmptyString Then MyImage = ConvertOptional(tmpMediaFile, kConv = 1 Or webpConverted, isWebp)
|
||||||
|
If Not MyImage Is Nothing Then Exit For
|
||||||
|
Next
|
||||||
|
If MyImage Is Nothing Then Throw New Exception
|
||||||
Catch
|
Catch
|
||||||
MyImage.DisposeIfReady
|
MyImage.DisposeIfReady
|
||||||
MyImage = New ImageRenderer(New Bitmap(10, 10))
|
MyImage = New ImageRenderer(New Bitmap(10, 10))
|
||||||
|
|||||||
@@ -187,24 +187,24 @@ Namespace Editors
|
|||||||
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
|
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
|
||||||
If MyDefs.MyFieldsChecker.AllParamsOK Then
|
If MyDefs.MyFieldsChecker.AllParamsOK Then
|
||||||
With Settings
|
With Settings
|
||||||
Dim a As Func(Of String, Object, Integer) =
|
Dim a As Func(Of String, Integer, Object, Integer) =
|
||||||
Function(t, v) MsgBoxE({$"You are set up higher than default count of along {t} downloading tasks." & vbNewLine &
|
Function(t, vc, v) MsgBoxE({$"You are set up higher than default count of along {t} downloading tasks." & vbNewLine &
|
||||||
$"Default: {SettingsCLS.DefaultMaxDownloadingTasks}" & vbNewLine &
|
$"Default: {vc}" & vbNewLine &
|
||||||
$"Your value: {CInt(v)}" & vbNewLine &
|
$"Your value: {CInt(v)}" & vbNewLine &
|
||||||
"Increasing this value may lead to higher CPU usage." & vbNewLine &
|
"Increasing this value may lead to higher CPU usage." & vbNewLine &
|
||||||
"Do you really want to continue?",
|
"Do you really want to continue?",
|
||||||
"Increasing download tasks"},
|
"Increasing download tasks"},
|
||||||
vbExclamation,,, {"Confirm", $"Set to default ({SettingsCLS.DefaultMaxDownloadingTasks})", "Cancel"})
|
vbExclamation,,, {"Confirm", $"Set to default ({vc})", "Cancel"})
|
||||||
|
|
||||||
If CInt(TXT_MAX_JOBS_USERS.Value) > SettingsCLS.DefaultMaxDownloadingTasks Then
|
If CInt(TXT_MAX_JOBS_USERS.Value) > SettingsCLS.DefaultMaxDownloadingTasks Then
|
||||||
Select Case a.Invoke("users", TXT_MAX_JOBS_USERS.Value)
|
Select Case a.Invoke("users", SettingsCLS.DefaultMaxDownloadingTasks, TXT_MAX_JOBS_USERS.Value)
|
||||||
Case 1 : TXT_MAX_JOBS_USERS.Value = SettingsCLS.DefaultMaxDownloadingTasks
|
Case 1 : TXT_MAX_JOBS_USERS.Value = SettingsCLS.DefaultMaxDownloadingTasks
|
||||||
Case 2 : Exit Sub
|
Case 2 : Exit Sub
|
||||||
End Select
|
End Select
|
||||||
End If
|
End If
|
||||||
If CInt(TXT_MAX_JOBS_CHANNELS.Value) > SettingsCLS.DefaultMaxDownloadingTasks Then
|
If CInt(TXT_MAX_JOBS_CHANNELS.Value) > SettingsCLS.DefaultMaxDownloadingTasks_Channels Then
|
||||||
Select Case a.Invoke("channels", TXT_MAX_JOBS_CHANNELS.Value)
|
Select Case a.Invoke("channels", SettingsCLS.DefaultMaxDownloadingTasks_Channels, TXT_MAX_JOBS_CHANNELS.Value)
|
||||||
Case 1 : TXT_MAX_JOBS_CHANNELS.Value = SettingsCLS.DefaultMaxDownloadingTasks
|
Case 1 : TXT_MAX_JOBS_CHANNELS.Value = SettingsCLS.DefaultMaxDownloadingTasks_Channels
|
||||||
Case 2 : Exit Sub
|
Case 2 : Exit Sub
|
||||||
End Select
|
End Select
|
||||||
End If
|
End If
|
||||||
@@ -407,7 +407,7 @@ Namespace Editors
|
|||||||
If Sender.DefaultButton = ADB.Refresh Then TXT_MAX_JOBS_USERS.Value = SettingsCLS.DefaultMaxDownloadingTasks
|
If Sender.DefaultButton = ADB.Refresh Then TXT_MAX_JOBS_USERS.Value = SettingsCLS.DefaultMaxDownloadingTasks
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub TXT_MAX_JOBS_CHANNELS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles TXT_MAX_JOBS_CHANNELS.ActionOnButtonClick
|
Private Sub TXT_MAX_JOBS_CHANNELS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles TXT_MAX_JOBS_CHANNELS.ActionOnButtonClick
|
||||||
If Sender.DefaultButton = ADB.Refresh Then TXT_MAX_JOBS_CHANNELS.Value = SettingsCLS.DefaultMaxDownloadingTasks
|
If Sender.DefaultButton = ADB.Refresh Then TXT_MAX_JOBS_CHANNELS.Value = SettingsCLS.DefaultMaxDownloadingTasks_Channels
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub ChangePositionControlsEnabling() Handles OPT_FILE_NAME_REPLACE.CheckedChanged, OPT_FILE_NAME_ADD_DATE.CheckedChanged
|
Private Sub ChangePositionControlsEnabling() Handles OPT_FILE_NAME_REPLACE.CheckedChanged, OPT_FILE_NAME_ADD_DATE.CheckedChanged
|
||||||
Dim b As Boolean = OPT_FILE_NAME_ADD_DATE.Checked And OPT_FILE_NAME_ADD_DATE.Enabled
|
Dim b As Boolean = OPT_FILE_NAME_ADD_DATE.Checked And OPT_FILE_NAME_ADD_DATE.Enabled
|
||||||
|
|||||||
@@ -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("2025.6.12.0")>
|
<Assembly: AssemblyVersion("2025.8.30.0")>
|
||||||
<Assembly: AssemblyFileVersion("2025.6.12.0")>
|
<Assembly: AssemblyFileVersion("2025.8.30.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("en")>
|
<Assembly: NeutralResourcesLanguage("en")>
|
||||||
|
|||||||
@@ -128,6 +128,7 @@
|
|||||||
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop, Version=1.0.168.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop, Version=1.0.168.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
|
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="PresentationCore" />
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Deployment" />
|
<Reference Include="System.Deployment" />
|
||||||
@@ -142,6 +143,7 @@
|
|||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
|
<Reference Include="WindowsBase" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Import Include="Microsoft.VisualBasic" />
|
<Import Include="Microsoft.VisualBasic" />
|
||||||
@@ -169,6 +171,7 @@
|
|||||||
<Compile Include="API\Base\DeclaredNames.vb" />
|
<Compile Include="API\Base\DeclaredNames.vb" />
|
||||||
<Compile Include="API\Base\DownDetector.vb" />
|
<Compile Include="API\Base\DownDetector.vb" />
|
||||||
<Compile Include="API\Base\EditorExchangeOptionsBase.vb" />
|
<Compile Include="API\Base\EditorExchangeOptionsBase.vb" />
|
||||||
|
<Compile Include="API\Base\EditorExchangeOptionsBase_P.vb" />
|
||||||
<Compile Include="API\Base\GDL.vb" />
|
<Compile Include="API\Base\GDL.vb" />
|
||||||
<Compile Include="API\Base\IUserData.vb" />
|
<Compile Include="API\Base\IUserData.vb" />
|
||||||
<Compile Include="API\Base\M3U8Base.vb" />
|
<Compile Include="API\Base\M3U8Base.vb" />
|
||||||
@@ -268,7 +271,6 @@
|
|||||||
<Compile Include="API\XVIDEOS\M3U8.vb" />
|
<Compile Include="API\XVIDEOS\M3U8.vb" />
|
||||||
<Compile Include="API\XVIDEOS\SiteSettings.vb" />
|
<Compile Include="API\XVIDEOS\SiteSettings.vb" />
|
||||||
<Compile Include="API\XVIDEOS\UserData.vb" />
|
<Compile Include="API\XVIDEOS\UserData.vb" />
|
||||||
<Compile Include="API\XVIDEOS\UserExchangeOptions.vb" />
|
|
||||||
<Compile Include="API\YouTube\SiteSettings.vb" />
|
<Compile Include="API\YouTube\SiteSettings.vb" />
|
||||||
<Compile Include="API\YouTube\UserData.vb" />
|
<Compile Include="API\YouTube\UserData.vb" />
|
||||||
<Compile Include="API\YouTube\UserExchangeOptions.vb" />
|
<Compile Include="API\YouTube\UserExchangeOptions.vb" />
|
||||||
@@ -713,6 +715,10 @@
|
|||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\MyUtilities\PersonalUtilities.Images\PersonalUtilities.Images.vbproj">
|
||||||
|
<Project>{b7ef76a9-96f3-4c53-b252-0ab5f79b67b3}</Project>
|
||||||
|
<Name>PersonalUtilities.Images</Name>
|
||||||
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\..\..\MyUtilities\PersonalUtilities.Notifications\PersonalUtilities.Notifications.vbproj">
|
<ProjectReference Include="..\..\..\MyUtilities\PersonalUtilities.Notifications\PersonalUtilities.Notifications.vbproj">
|
||||||
<Project>{fc532253-1ab3-4def-a28a-dfdd9a481eb2}</Project>
|
<Project>{fc532253-1ab3-4def-a28a-dfdd9a481eb2}</Project>
|
||||||
<Name>PersonalUtilities.Notifications</Name>
|
<Name>PersonalUtilities.Notifications</Name>
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ Imports DoubleClickBehavior = SCrawler.DownloadObjects.STDownloader.DoubleClickB
|
|||||||
Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
||||||
#Region "Constants: defaults"
|
#Region "Constants: defaults"
|
||||||
Friend Const DefaultMaxDownloadingTasks As Integer = 5
|
Friend Const DefaultMaxDownloadingTasks As Integer = 5
|
||||||
|
Friend Const DefaultMaxDownloadingTasks_Channels As Integer = 1
|
||||||
Friend Const TaskStackNamePornSite As String = "Porn sites"
|
Friend Const TaskStackNamePornSite As String = "Porn sites"
|
||||||
Friend Const Name_Node_Sites As String = "Sites"
|
Friend Const Name_Node_Sites As String = "Sites"
|
||||||
Private Const SitesValuesSeparator As String = ","
|
Private Const SitesValuesSeparator As String = ","
|
||||||
@@ -194,7 +195,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
|||||||
Private ReadOnly BlackListFile As SFile = $"{SettingsFolderName}\BlackList.txt"
|
Private ReadOnly BlackListFile As SFile = $"{SettingsFolderName}\BlackList.txt"
|
||||||
Private ReadOnly UsersSettingsFile As SFile = $"{SettingsFolderName}\Users.xml"
|
Private ReadOnly UsersSettingsFile As SFile = $"{SettingsFolderName}\Users.xml"
|
||||||
Private ReadOnly Property SettingsVersion As XMLValue(Of Integer)
|
Private ReadOnly Property SettingsVersion As XMLValue(Of Integer)
|
||||||
Private Const SettingsVersionCurrent As Integer = 2
|
Private Const SettingsVersionCurrent As Integer = 3
|
||||||
Friend ShortcutOpenFeed As New ButtonKey(Keys.F, True)
|
Friend ShortcutOpenFeed As New ButtonKey(Keys.F, True)
|
||||||
Friend ShortcutOpenSearch As New ButtonKey(Keys.F,, True)
|
Friend ShortcutOpenSearch As New ButtonKey(Keys.F,, True)
|
||||||
Private Sub ChangeFeedOpenMode()
|
Private Sub ChangeFeedOpenMode()
|
||||||
@@ -366,9 +367,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
|||||||
ReparseMissingInTheRoutine = New XMLValue(Of Boolean)("ReparseMissingInTheRoutine", False, MyXML, n)
|
ReparseMissingInTheRoutine = New XMLValue(Of Boolean)("ReparseMissingInTheRoutine", False, MyXML, n)
|
||||||
UseDefaultAccountIfMissing = New XMLValue(Of Boolean)("UseDefaultAccountIfMissing", True, MyXML, n)
|
UseDefaultAccountIfMissing = New XMLValue(Of Boolean)("UseDefaultAccountIfMissing", True, MyXML, n)
|
||||||
AutomationBrushUndownloadedPlansMinutes = New XMLValue(Of Integer)("AutomationBrushUndownloadedPlansMinutes", 10080, MyXML, n)
|
AutomationBrushUndownloadedPlansMinutes = New XMLValue(Of Integer)("AutomationBrushUndownloadedPlansMinutes", 10080, MyXML, n)
|
||||||
DownDetectorEnabled = New XMLValue(Of Boolean)("DownDetectorEnabled", True, MyXML, n)
|
DownDetectorEnabled = New XMLValue(Of Boolean)("DownDetectorEnabled", False, MyXML, n)
|
||||||
'TODELETE: DownDetectorEnabled change
|
|
||||||
If SettingsVersion.Value < SettingsVersionCurrent Then DownDetectorEnabled.Value = False 'SettingsVersionCurrent = 2
|
|
||||||
|
|
||||||
'Downloading: file naming
|
'Downloading: file naming
|
||||||
n = {"Downloading", "FileName"}
|
n = {"Downloading", "FileName"}
|
||||||
@@ -392,7 +391,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
|||||||
ChannelsDefaultReadyForDownload = New XMLValue(Of Boolean)("ChannelsDefaultReadyForDownload", False, MyXML, n)
|
ChannelsDefaultReadyForDownload = New XMLValue(Of Boolean)("ChannelsDefaultReadyForDownload", False, MyXML, n)
|
||||||
ChannelsDefaultTemporary = New XMLValue(Of Boolean)("ChannelsDefaultTemporary", True, MyXML, n)
|
ChannelsDefaultTemporary = New XMLValue(Of Boolean)("ChannelsDefaultTemporary", True, MyXML, n)
|
||||||
ChannelsHideExistsUser = New XMLValue(Of Boolean)("HideExistsUser", True, MyXML, n)
|
ChannelsHideExistsUser = New XMLValue(Of Boolean)("HideExistsUser", True, MyXML, n)
|
||||||
ChannelsMaxJobsCount = New XMLValue(Of Integer)("MaxJobsCount", DefaultMaxDownloadingTasks, MyXML, n)
|
ChannelsMaxJobsCount = New XMLValue(Of Integer)("MaxJobsCount", DefaultMaxDownloadingTasks_Channels, MyXML, n)
|
||||||
n = {Name_Node_Sites, "Channels", "Users"}
|
n = {Name_Node_Sites, "Channels", "Users"}
|
||||||
FromChannelDownloadTop = New XMLValue(Of Integer)("FromChannelDownloadTop", 10, MyXML, n)
|
FromChannelDownloadTop = New XMLValue(Of Integer)("FromChannelDownloadTop", 10, MyXML, n)
|
||||||
FromChannelDownloadTopUse = New XMLValue(Of Boolean)("FromChannelDownloadTopUse", False, MyXML, n)
|
FromChannelDownloadTopUse = New XMLValue(Of Boolean)("FromChannelDownloadTopUse", False, MyXML, n)
|
||||||
@@ -497,6 +496,8 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
|
|||||||
AdvancedFilter.IsViewFilter = True
|
AdvancedFilter.IsViewFilter = True
|
||||||
Labels.AddRange({AdvancedFilter}.GetGroupsLabels, False)
|
Labels.AddRange({AdvancedFilter}.GetGroupsLabels, False)
|
||||||
|
|
||||||
|
'TODELETE: DefaultMaxDownloadingTasks_Channels
|
||||||
|
If Not SettingsVersion = SettingsVersionCurrent Then ChannelsMaxJobsCount.Value = DefaultMaxDownloadingTasks_Channels 'SettingsVersionCurrent = 3
|
||||||
SettingsVersion.Value = SettingsVersionCurrent
|
SettingsVersion.Value = SettingsVersionCurrent
|
||||||
|
|
||||||
MyXML.EndUpdate()
|
MyXML.EndUpdate()
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
'
|
'
|
||||||
' This program is distributed in the hope that it will be useful,
|
' This program is distributed in the hope that it will be useful,
|
||||||
' but WITHOUT ANY WARRANTY
|
' but WITHOUT ANY WARRANTY
|
||||||
|
Imports System.IO
|
||||||
Imports PersonalUtilities.Tools
|
Imports PersonalUtilities.Tools
|
||||||
Friend Class UserImage : Inherits ImageRenderer
|
Friend Class UserImage : Inherits ImageRenderer
|
||||||
Friend Const ImagePrefix As String = "UserPicture"
|
Friend Const ImagePrefix As String = "UserPicture"
|
||||||
@@ -97,4 +98,56 @@ Friend Class UserImage : Inherits ImageRenderer
|
|||||||
Friend Overloads Shared Function CreateImageFromText(ByVal Text As String, ByVal File As SFile) As Boolean
|
Friend Overloads Shared Function CreateImageFromText(ByVal Text As String, ByVal File As SFile) As Boolean
|
||||||
Return CreateImageFromText(Text, FormFont, Color.Black, TextImageWidth, File, Color.White,, EDP.ThrowException)
|
Return CreateImageFromText(Text, FormFont, Color.Black, TextImageWidth, File, Color.White,, EDP.ThrowException)
|
||||||
End Function
|
End Function
|
||||||
|
Friend Const ExtWebp As String = "webp"
|
||||||
|
Friend Const ExtJpg As String = "jpg"
|
||||||
|
Friend Shared Function ConvertWebp(ByVal InitFile As SFile, ByVal DestFile As SFile,
|
||||||
|
Optional ByVal Force As Boolean = False, Optional ByVal ToWebP As Boolean = False,
|
||||||
|
Optional ByRef Result As Boolean = False) As SFile
|
||||||
|
Result = False
|
||||||
|
If InitFile.Extension = ExtWebp Or Force Then
|
||||||
|
If Settings.FfmpegFile.Exists Or ToWebP Then
|
||||||
|
Dim dir As SFile
|
||||||
|
Dim postfix$ = String.Empty
|
||||||
|
If DestFile.IsEmptyString Then
|
||||||
|
dir = $"{Settings.Cache.RootDirectory.PathWithSeparator}ConvWebp\"
|
||||||
|
Settings.Cache.AddPath(dir)
|
||||||
|
postfix = $"_{InitFile.GetHashCode}"
|
||||||
|
Else
|
||||||
|
dir = New SFile With {.Path = DestFile.Path}
|
||||||
|
End If
|
||||||
|
dir.Exists(SFO.Path)
|
||||||
|
Dim f As SFile = DestFile.IfNullOrEmpty(InitFile)
|
||||||
|
f.Path = dir.PathNoSeparator
|
||||||
|
If Not postfix.IsEmptyString Then f.Name &= postfix
|
||||||
|
f.Extension = IIf(ToWebP, ExtWebp, ExtJpg)
|
||||||
|
|
||||||
|
If DestFile.IsEmptyString AndAlso f.Exists AndAlso Not f.Extension = ExtWebp Then Return f
|
||||||
|
|
||||||
|
If ToWebP Then
|
||||||
|
If Not f.Exists Then InitFile.Copy(f)
|
||||||
|
If f.Exists Then
|
||||||
|
InitFile = f
|
||||||
|
f.Extension = ExtJpg
|
||||||
|
Else
|
||||||
|
Throw New ArgumentNullException With {.HelpLink = 1}
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
If Not ConvertWebpTryImageMagick(InitFile, f) Then
|
||||||
|
Using imgBatch As New BatchExecutor
|
||||||
|
With imgBatch
|
||||||
|
.ChangeDirectory(dir)
|
||||||
|
.Execute($"""{Settings.FfmpegFile}"" -i ""{InitFile}"" ""{f}""")
|
||||||
|
End With
|
||||||
|
End Using
|
||||||
|
End If
|
||||||
|
If f.Exists Then Result = True : Return f
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
Return InitFile
|
||||||
|
End If
|
||||||
|
Return Nothing
|
||||||
|
End Function
|
||||||
|
Private Shared Function ConvertWebpTryImageMagick(ByVal InitFile As SFile, ByVal DestFile As SFile) As Boolean
|
||||||
|
Return ImageRendererExt.ConvertWebp(InitFile, DestFile, EDP.SendToLog + EDP.ReturnValue)
|
||||||
|
End Function
|
||||||
End Class
|
End Class
|
||||||
Reference in New Issue
Block a user