Compare commits

..

7 Commits

Author SHA1 Message Date
Andy
7a33c02497 2023.12.15.0
Fix 'GetCurrentMaxVer' bug
2023-12-14 23:51:35 +03:00
Andy
5bd79ff3c2 2023.12.14.1
API.Twitter: add additional nodes
2023-12-14 23:06:55 +03:00
Andy
3268bca0d3 2023.12.14.0
YT
YouTubeSettings: add 'CreateThumbnails_Video' and 'CreateThumbnails_Music' properties
VideoListForm: add 'BTT_SELECT_ALL' and 'BTT_SELECT_NONE'
YouTubeMediaContainerBase: update thumbnails downloading
2023-12-14 14:19:20 +03:00
Andy
1455a31879 2023.12.13.0
YT
Structures: add 'YouTubeChannelTab' enum
YouTubeFunctions: add 'StandardizeURL_Channel' function; update 'Info_GetUrlType', 'Parse' and 'Parse_Internal' functions (YouTubeChannelTab)
YouTubeSettings: add 'ChannelsDownload' property and 'YouTubeChannelTabConverter' converter for grid
Add 'ChannelTabsChooserForm'
VideoListForm: remove buttons 'BTT_ADD_NO_SHORTS' and 'BTT_ADD_SHORTS_ONLY'; update 'BTT_ADD_KeyClick' function

SCrawler
API.M3U8Base: add 'M3U8URL' structure; update 'Download' function with 'OnlyDownload' arg
API.ProfileSaved: add sorting of feed files
API.Xhamster: update M3U8 parser and 'Download' function for additional downloading ways; add 'ReencodeVideos' property (to the 'SiteSettings')
API.YouTube: update to updated 'Parse' function
2023-12-13 19:48:50 +03:00
Andy
64d6e6b28c 2023.12.10.0
YT: move updater functions into the app
SCrawler.API.Twitter: update parsing function to new GDL (1.26.4-dev)
2023-12-10 10:16:58 +03:00
Andy
da7cddc720 Update README.md 2023-12-07 14:08:32 +03:00
Andy
72be6b09ff Update README.md 2023-12-07 11:33:52 +03:00
29 changed files with 1009 additions and 354 deletions

View File

@@ -1,3 +1,40 @@
# 2023.12.15.0
*2023-12-15*
- Fixed
- Twitter: some twitter profiles don't download completely
- Minor bugs
# 2023.12.14.0
*2023-12-14*
- Added
- YouTube: options `Create thumbnail files (video)` and `Create thumbnail files (music)`
- YouTube: `Select all` and `Select none` buttons
# 2023.12.13.0
*2023-12-13*
- Added
- YouTube (standalone app): additional options for downloading channels
- Updated
- gallery-dl up to version 1.26.4
- Fixed
- Feed: saved posts are added to the end of the feed
- xHamster: some videos won't download
# 2023.12.10.0
*2023-12-10*
- Updated
- gallery-dl up to version 1.26.4-dev
- Fixed
- Twitter: data is not downloading
# 2023.12.7.0 # 2023.12.7.0
*2023-12-07* *2023-12-07*

View File

@@ -1,6 +1,6 @@
<!-- # :rainbow_flag: Happy LGBT Pride Month :tada: <!-- # :rainbow_flag: Happy LGBT Pride Month :tada:
--> -->
# :rainbow_flag: Social networks crawler :rainbow_flag: # 🏳️‍🌈 Social networks crawler 🏳️‍🌈
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/AAndyProgram/SCrawler)](https://github.com/AAndyProgram/SCrawler/releases/latest) [![GitHub release (latest by date)](https://img.shields.io/github/v/release/AAndyProgram/SCrawler)](https://github.com/AAndyProgram/SCrawler/releases/latest)
[![GitHub license](https://img.shields.io/github/license/AAndyProgram/SCrawler)](https://github.com/AAndyProgram/SCrawler/blob/main/LICENSE) [![GitHub license](https://img.shields.io/github/license/AAndyProgram/SCrawler)](https://github.com/AAndyProgram/SCrawler/blob/main/LICENSE)
@@ -39,7 +39,7 @@ A program to download photo and video from [any site](#supported-sites) (e.g. Yo
- Mastodon images and videos, saved (bookmarked) posts; - Mastodon images and videos, saved (bookmarked) posts;
- Instagram images and videos, tagged posts, stories, saved posts; - Instagram images and videos, tagged posts, stories, saved posts;
- Threads images and videos; - Threads images and videos;
- Facebook images and videos, saved posts; - Facebook images and videos, stories, saved posts;
- TikTok videos; - TikTok videos;
- Pinterest boards, users, saved posts; - Pinterest boards, users, saved posts;
- Imgur images, galleries and videos; - Imgur images, galleries and videos;

View File

@@ -23,7 +23,7 @@ Namespace [Shared]
Next Next
End If End If
End With End With
If versions.Count > 0 Then Return versions.LastOrDefault If versions.Count > 0 Then Return versions.Max
End If End If
Catch Catch
End Try End Try

View File

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

View File

@@ -62,6 +62,14 @@ Namespace API.YouTube.Base
Channel = 2 Channel = 2
PlayList = 3 PlayList = 3
End Enum End Enum
<Editor(GetType(EnumDropDownEditor), GetType(UITypeEditor)), Flags>
Public Enum YouTubeChannelTab As Integer
<EnumValue(IsNullValue:=True)>
All = 0
Videos = 1
Shorts = 3
Playlists = 10
End Enum
<Editor(GetType(EnumDropDownEditor), GetType(UITypeEditor))> <Editor(GetType(EnumDropDownEditor), GetType(UITypeEditor))>
Public Enum Protocols As Integer Public Enum Protocols As Integer
<EnumValue(ExcludeFromList:=True)> <EnumValue(ExcludeFromList:=True)>

View File

@@ -43,11 +43,35 @@ Namespace API.YouTube.Base
Return URL Return URL
End Try End Try
End Function End Function
Public Shared Function StandardizeURL_Channel(ByVal URL As String, Optional ByVal Process As Boolean = True) As String
Try
Dim ct As YouTubeChannelTab = YouTubeChannelTab.All
Dim isMusic As Boolean = False
If Process AndAlso Info_GetUrlType(URL, isMusic,,,, ct) = YouTubeMediaType.Channel AndAlso Not isMusic Then
If Not ct = YouTubeChannelTab.All Then
Dim rValue$ = String.Empty
Select Case ct
Case YouTubeChannelTab.Videos : rValue = "/videos"
Case YouTubeChannelTab.Shorts : rValue = "/shorts"
Case YouTubeChannelTab.Playlists : rValue = "/playlists"
End Select
If Not rValue.IsEmptyString Then
Dim startIndx% = InStr(URL, rValue)
If startIndx > 0 Then URL = URL.Remove(startIndx - 1)
End If
End If
End If
Return URL
Catch ex As Exception
Return URL
End Try
End Function
Public Shared Function IsMyUrl(ByVal URL As String) As Boolean Public Shared Function IsMyUrl(ByVal URL As String) As Boolean
Return Not Info_GetUrlType(URL) = YouTubeMediaType.Undefined Return Not Info_GetUrlType(URL) = YouTubeMediaType.Undefined
End Function End Function
Public Shared Function Info_GetUrlType(ByVal URL As String, Optional ByRef IsMusic As Boolean = False, Optional ByRef IsShorts As Boolean = False, Public Shared Function Info_GetUrlType(ByVal URL As String, Optional ByRef IsMusic As Boolean = False, Optional ByRef IsShorts As Boolean = False,
Optional ByRef IsChannelUser As Boolean = False, Optional ByRef Id As String = Nothing) As YouTubeMediaType Optional ByRef IsChannelUser As Boolean = False, Optional ByRef Id As String = Nothing,
Optional ByRef ChannelOptions As YouTubeChannelTab = YouTubeChannelTab.All) As YouTubeMediaType
If Not URL.IsEmptyString Then If Not URL.IsEmptyString Then
IsMusic = URL.Contains("music.youtube.com") IsMusic = URL.Contains("music.youtube.com")
IsChannelUser = False IsChannelUser = False
@@ -60,7 +84,17 @@ Namespace API.YouTube.Base
Case "watch" : Return YouTubeMediaType.Single Case "watch" : Return YouTubeMediaType.Single
Case "shorts" : IsShorts = True : Return YouTubeMediaType.Single Case "shorts" : IsShorts = True : Return YouTubeMediaType.Single
Case "playlist" : Return YouTubeMediaType.PlayList Case "playlist" : Return YouTubeMediaType.PlayList
Case UserChannelOption, "@" : IsChannelUser = data(2).ToLower = UserChannelOption : Return YouTubeMediaType.Channel Case UserChannelOption, "@"
IsChannelUser = data(2).ToLower = UserChannelOption
If data.Count > 6 Then
Select Case data(6).StringToLower.StringTrimStart("/")
Case "videos" : ChannelOptions = YouTubeChannelTab.Videos
Case "shorts" : ChannelOptions = YouTubeChannelTab.Shorts
Case "playlists" : ChannelOptions = YouTubeChannelTab.Playlists
Case Else : ChannelOptions = YouTubeChannelTab.All
End Select
End If
Return YouTubeMediaType.Channel
End Select End Select
End If End If
End If End If
@@ -82,27 +116,25 @@ Namespace API.YouTube.Base
''' <exception cref="InvalidOperationException"></exception> ''' <exception cref="InvalidOperationException"></exception>
Public Shared Function Parse(ByVal URL As String, Optional ByVal UseCookies As Boolean? = Nothing, Public Shared Function Parse(ByVal URL As String, Optional ByVal UseCookies As Boolean? = Nothing,
Optional ByVal Token As Threading.CancellationToken = Nothing, Optional ByVal Progress As IMyProgress = Nothing, Optional ByVal Token As Threading.CancellationToken = Nothing, Optional ByVal Progress As IMyProgress = Nothing,
Optional ByVal GetDefault As Boolean? = Nothing, Optional ByVal GetShorts As Boolean? = Nothing, Optional ByVal DateAfter As Date? = Nothing, Optional ByVal DateBefore As Date? = Nothing,
Optional ByVal DateAfter As Date? = Nothing, Optional ByVal DateBefore As Date? = Nothing) As IYouTubeMediaContainer Optional ByVal ChannelOption As YouTubeChannelTab? = Nothing, Optional ByVal UrlAsIs As Boolean = False) As IYouTubeMediaContainer
If URL.IsEmptyString Then Throw New ArgumentNullException("URL", "URL cannot be null") If URL.IsEmptyString Then Throw New ArgumentNullException("URL", "URL cannot be null")
If Not MyYouTubeSettings.YTDLP.Value.Exists Then Throw New IO.FileNotFoundException("Path to 'yt-dlp.exe' not set or program not found at destination", MyYouTubeSettings.YTDLP.Value.ToString) If Not MyYouTubeSettings.YTDLP.Value.Exists Then Throw New IO.FileNotFoundException("Path to 'yt-dlp.exe' not set or program not found at destination", MyYouTubeSettings.YTDLP.Value.ToString)
Dim urlOrig$ = URL Dim urlOrig$ = URL
URL = RegexReplace(URL, TrueUrlRegEx) URL = RegexReplace(URL, TrueUrlRegEx)
If URL.IsEmptyString Then Throw New ArgumentNullException("URL", $"Can't get true URL from [{urlOrig}]") If URL.IsEmptyString Then Throw New ArgumentNullException("URL", $"Can't get true URL from [{urlOrig}]")
Dim isMusic As Boolean = False, isShorts As Boolean = False Dim isMusic As Boolean = False, isShorts As Boolean = False
Dim objType As YouTubeMediaType = Info_GetUrlType(URL, isMusic, isShorts) Dim channelTab As YouTubeChannelTab = YouTubeChannelTab.All
Dim objType As YouTubeMediaType = Info_GetUrlType(URL, isMusic, isShorts,,, channelTab)
If ChannelOption.HasValue Then channelTab = ChannelOption.Value
If Not objType = YouTubeMediaType.Undefined Then If Not objType = YouTubeMediaType.Undefined Then
Dim __GetDefault As Boolean = If(GetDefault, True)
Dim __GetShorts As Boolean = If(GetShorts, True)
If isMusic Then __GetShorts = False
Dim container As IYouTubeMediaContainer Dim container As IYouTubeMediaContainer
Dim pattern$ = "%(channel_id)s_%(id)s_%(playlist_index)s" Dim pattern$ = "%(channel_id)s_%(id)s_%(playlist_index)s"
Select Case objType Select Case objType
Case YouTubeMediaType.Single Case YouTubeMediaType.Single
__GetShorts = False
If isMusic Then container = New Track Else container = New Video If isMusic Then container = New Track Else container = New Video
Case YouTubeMediaType.PlayList : container = New PlayList : pattern = "%(playlist_index)s_%(id)s" : __GetShorts = False Case YouTubeMediaType.PlayList : container = New PlayList : pattern = "%(playlist_index)s_%(id)s"
Case YouTubeMediaType.Channel Case YouTubeMediaType.Channel
container = New Channel container = New Channel
If isMusic Then pattern = "%(playlist_id)s/%(channel_id)s_%(id)s_%(playlist_index)s" If isMusic Then pattern = "%(playlist_id)s/%(channel_id)s_%(id)s_%(playlist_index)s"
@@ -121,11 +153,11 @@ Namespace API.YouTube.Base
Dim useCookiesForce As Boolean = UseCookies.HasValue AndAlso UseCookies.Value AndAlso cookiesExists Dim useCookiesForce As Boolean = UseCookies.HasValue AndAlso UseCookies.Value AndAlso cookiesExists
If UseCookies.HasValue AndAlso UseCookies.Value Then If UseCookies.HasValue AndAlso UseCookies.Value Then
withCookieRequested = True withCookieRequested = True
result = Parse_Internal(URL, pattern, _CachePathDefault, True, YouTubeCookieNetscapeFile, DateAfter, DateBefore, __GetDefault, __GetShorts) result = Parse_Internal(URL, pattern, _CachePathDefault, True, YouTubeCookieNetscapeFile, DateAfter, DateBefore, objType, channelTab, isMusic, UrlAsIs)
End If End If
If Not result And Not withCookieRequested Then If Not result And Not withCookieRequested Then
If Not UseCookies.HasValue OrElse Not UseCookies.Value Then result = Parse_Internal(URL, pattern, _CachePathDefault, False, YouTubeCookieNetscapeFile, DateAfter, DateBefore, __GetDefault, __GetShorts) If Not UseCookies.HasValue OrElse Not UseCookies.Value Then result = Parse_Internal(URL, pattern, _CachePathDefault, False, YouTubeCookieNetscapeFile, DateAfter, DateBefore, objType, channelTab, isMusic, UrlAsIs)
If Not result And Not UseCookies.HasValue And cookiesExists Then result = Parse_Internal(URL, pattern, _CachePathDefault, True, YouTubeCookieNetscapeFile, DateAfter, DateBefore, __GetDefault, __GetShorts) If Not result And Not UseCookies.HasValue And cookiesExists Then result = Parse_Internal(URL, pattern, _CachePathDefault, True, YouTubeCookieNetscapeFile, DateAfter, DateBefore, objType, channelTab, isMusic, UrlAsIs)
End If End If
If result Then If result Then
@@ -139,21 +171,40 @@ Namespace API.YouTube.Base
Private Shared Function Parse_Internal(ByVal URL As String, ByVal OutputPattern As String, ByVal OutputPath As SFile, Private Shared Function Parse_Internal(ByVal URL As String, ByVal OutputPattern As String, ByVal OutputPath As SFile,
ByVal UseCookies As Boolean, ByVal CookiesFile As SFile, ByVal UseCookies As Boolean, ByVal CookiesFile As SFile,
ByVal DateAfter As Date?, ByVal DateBefore As Date?, ByVal DateAfter As Date?, ByVal DateBefore As Date?,
ByVal GetDefault As Boolean, ByVal GetShorts As Boolean) As Boolean ByVal ObjType As YouTubeMediaType, ByVal ChannelTab As YouTubeChannelTab,
ByVal IsMusic As Boolean, ByVal UrlAsIs As Boolean) As Boolean
Try Try
Dim command$ = "yt-dlp --write-info-json --skip-download" Dim command$ = "yt-dlp --write-info-json --skip-download"
command.StringAppend(GetCookiesCommand(UseCookies, CookiesFile), " ") command.StringAppend(GetCookiesCommand(UseCookies, CookiesFile), " ")
If DateAfter.HasValue Then command.StringAppend($"--dateafter {DateAfter.Value:yyyyMMdd}", " ") If DateAfter.HasValue Then command.StringAppend($"--dateafter {DateAfter.Value:yyyyMMdd}", " ")
If DateBefore.HasValue Then command.StringAppend($"--datebefore {DateBefore.Value:yyyyMMdd}", " ") If DateBefore.HasValue Then command.StringAppend($"--datebefore {DateBefore.Value:yyyyMMdd}", " ")
command.StringAppend("{0}" & $" -o ""{OutputPattern}""", " ") command.StringAppend("{0}" & $" -o ""{OutputPattern}""", " ")
'#If DEBUG Then
'Debug.WriteLine(String.Format(command, URL))
'#End If
Dim debugString As Func(Of String, String) = Function(ByVal input As String) As String
#If DEBUG Then #If DEBUG Then
Debug.WriteLine(String.Format(command, URL)) Debug.WriteLine(input)
#End If #End If
Return input
End Function
Using batch As New BatchExecutor(True) Using batch As New BatchExecutor(True)
With batch With batch
.CommandPermanent = BatchExecutor.GetDirectoryCommand(MyYouTubeSettings.YTDLP.Value) .CommandPermanent = BatchExecutor.GetDirectoryCommand(MyYouTubeSettings.YTDLP.Value)
If GetDefault Then .Execute(String.Format(command, URL)) If ObjType = YouTubeMediaType.Channel And Not IsMusic And Not UrlAsIs Then
If GetShorts Then .Execute(String.Format(command, $"{URL.StringTrimEnd("/")}/shorts")) Dim ct As List(Of YouTubeChannelTab) = EnumExtract(Of YouTubeChannelTab)(ChannelTab,, True).ListIfNothing
If ct.Count = 0 Then
.Execute(debugString(String.Format(command, $"{URL.StringTrimEnd("/")}/videos")))
.Execute(debugString(String.Format(command, $"{URL.StringTrimEnd("/")}/shorts")))
.Execute(debugString(String.Format(command, $"{URL.StringTrimEnd("/")}/playlists")))
Else
If ct.Contains(YouTubeChannelTab.Videos) Then .Execute(debugString(String.Format(command, $"{URL.StringTrimEnd("/")}/videos")))
If ct.Contains(YouTubeChannelTab.Shorts) Then .Execute(debugString(String.Format(command, $"{URL.StringTrimEnd("/")}/shorts")))
If ct.Contains(YouTubeChannelTab.Playlists) Then .Execute(debugString(String.Format(command, $"{URL.StringTrimEnd("/")}/playlists")))
End If
Else
.Execute(debugString(String.Format(command, URL)))
End If
End With End With
End Using End Using
Return SFile.GetFiles(OutputPath,, IO.SearchOption.AllDirectories, EDP.ReturnValue).Count > 0 Return SFile.GetFiles(OutputPath,, IO.SearchOption.AllDirectories, EDP.ReturnValue).Count > 0

View File

@@ -147,6 +147,12 @@ Namespace API.YouTube.Base
<Browsable(True), GridVisible, XMLVN({"Info"}), Category("Info"), DisplayName("Create description files"), <Browsable(True), GridVisible, XMLVN({"Info"}), Category("Info"), DisplayName("Create description files"),
Description("Create video description files. Default: false.")> Description("Create video description files. Default: false.")>
Public ReadOnly Property CreateDescriptionFiles As XMLValue(Of Boolean) Public ReadOnly Property CreateDescriptionFiles As XMLValue(Of Boolean)
<Browsable(True), GridVisible, XMLVN({"Info"}, True), Category("Info"), DisplayName("Create thumbnail files (video)"),
Description("Create video thumbnail files. Default: true.")>
Public ReadOnly Property CreateThumbnails_Video As XMLValue(Of Boolean)
<Browsable(True), GridVisible, XMLVN({"Info"}, True), Category("Info"), DisplayName("Create thumbnail files (music)"),
Description("Create music thumbnail files (covers). Default: true.")>
Public ReadOnly Property CreateThumbnails_Music As XMLValue(Of Boolean)
#End Region #End Region
#Region "Defaults" #Region "Defaults"
<Browsable(True), GridVisible, XMLVN({"Defaults"}, True), Category("Defaults"), DisplayName("Standardize URLs"), <Browsable(True), GridVisible, XMLVN({"Defaults"}, True), Category("Defaults"), DisplayName("Standardize URLs"),
@@ -223,6 +229,38 @@ Namespace API.YouTube.Base
Description("Add some additional info to the program info if you need")> Description("Add some additional info to the program info if you need")>
Friend ReadOnly Property ProgramDescription As XMLValue(Of String) Friend ReadOnly Property ProgramDescription As XMLValue(Of String)
#End Region #End Region
#Region "Defaults ChannelsDownload"
<Browsable(True), GridVisible, XMLVN({"Defaults", "Channels"}), Category("Defaults"), DisplayName("Default download tabs for channels"),
Description("Default download tabs for downloading channels"), TypeConverter(GetType(YouTubeChannelTabConverter))>
Public ReadOnly Property ChannelsDownload As XMLValue(Of YouTubeChannelTab)
Private Class YouTubeChannelTabConverter : Inherits TypeConverter
Public Overrides Function ConvertTo(ByVal Context As ITypeDescriptorContext, ByVal Culture As CultureInfo, ByVal Value As Object,
ByVal DestinationType As Type) As Object
If Not DestinationType Is Nothing Then
If DestinationType Is GetType(String) Then
If IsNothing(Value) Then
Return YouTubeChannelTab.All.ToString
Else
Dim v As List(Of YouTubeChannelTab) = EnumExtract(Of YouTubeChannelTab)(Value,,, EDP.ReturnValue).ListIfNothing
If v.ListExists Then
v.Sort()
Return v.ListToStringE(, New ANumbers.EnumToStringProvider(GetType(YouTubeChannelTab)))
Else
Return YouTubeChannelTab.All.ToString
End If
End If
Else
If IsNothing(Value) Then
Return YouTubeChannelTab.All
Else
Return Value
End If
End If
End If
Return MyBase.ConvertTo(Context, Culture, Value, DestinationType)
End Function
End Class
#End Region
#Region "Defaults Video" #Region "Defaults Video"
<Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, "MKV"), Category("Defaults Video"), DisplayName("Default format"), <Browsable(True), GridVisible, XMLVN({"DefaultsVideo"}, "MKV"), Category("Defaults Video"), DisplayName("Default format"),
TypeConverter(GetType(FieldsTypeConverter)), GridStandardValuesProvider(NameOf(AvailableVideoFormats_Impl)), TypeConverter(GetType(FieldsTypeConverter)), GridStandardValuesProvider(NameOf(AvailableVideoFormats_Impl)),

View File

@@ -0,0 +1,179 @@
' 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 ChannelTabsChooserForm : 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
Me.CH_ALL = New System.Windows.Forms.CheckBox()
Me.CH_VIDEOS = New System.Windows.Forms.CheckBox()
Me.CH_SHORTS = New System.Windows.Forms.CheckBox()
Me.CH_PLS = New System.Windows.Forms.CheckBox()
Me.TXT_URL = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.CH_URL_ASIS = New System.Windows.Forms.CheckBox()
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
CONTAINER_MAIN.ContentPanel.SuspendLayout()
CONTAINER_MAIN.SuspendLayout()
TP_MAIN.SuspendLayout()
CType(Me.TXT_URL, 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(474, 159)
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(474, 184)
CONTAINER_MAIN.TabIndex = 0
CONTAINER_MAIN.TopToolStripPanelVisible = False
'
'TP_MAIN
'
TP_MAIN.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
TP_MAIN.ColumnCount = 1
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MAIN.Controls.Add(Me.CH_ALL, 0, 2)
TP_MAIN.Controls.Add(Me.CH_VIDEOS, 0, 3)
TP_MAIN.Controls.Add(Me.CH_SHORTS, 0, 4)
TP_MAIN.Controls.Add(Me.CH_PLS, 0, 5)
TP_MAIN.Controls.Add(Me.TXT_URL, 0, 0)
TP_MAIN.Controls.Add(Me.CH_URL_ASIS, 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 = 7
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MAIN.Size = New System.Drawing.Size(474, 159)
TP_MAIN.TabIndex = 0
'
'CH_ALL
'
Me.CH_ALL.AutoSize = True
Me.CH_ALL.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_ALL.Location = New System.Drawing.Point(4, 59)
Me.CH_ALL.Name = "CH_ALL"
Me.CH_ALL.Size = New System.Drawing.Size(466, 19)
Me.CH_ALL.TabIndex = 2
Me.CH_ALL.Text = "ALL"
Me.CH_ALL.UseVisualStyleBackColor = True
'
'CH_VIDEOS
'
Me.CH_VIDEOS.AutoSize = True
Me.CH_VIDEOS.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_VIDEOS.Location = New System.Drawing.Point(4, 85)
Me.CH_VIDEOS.Name = "CH_VIDEOS"
Me.CH_VIDEOS.Size = New System.Drawing.Size(466, 19)
Me.CH_VIDEOS.TabIndex = 3
Me.CH_VIDEOS.Text = "Videos"
Me.CH_VIDEOS.UseVisualStyleBackColor = True
'
'CH_SHORTS
'
Me.CH_SHORTS.AutoSize = True
Me.CH_SHORTS.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_SHORTS.Location = New System.Drawing.Point(4, 111)
Me.CH_SHORTS.Name = "CH_SHORTS"
Me.CH_SHORTS.Size = New System.Drawing.Size(466, 19)
Me.CH_SHORTS.TabIndex = 4
Me.CH_SHORTS.Text = "Shorts"
Me.CH_SHORTS.UseVisualStyleBackColor = True
'
'CH_PLS
'
Me.CH_PLS.AutoSize = True
Me.CH_PLS.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_PLS.Location = New System.Drawing.Point(4, 137)
Me.CH_PLS.Name = "CH_PLS"
Me.CH_PLS.Size = New System.Drawing.Size(466, 19)
Me.CH_PLS.TabIndex = 5
Me.CH_PLS.Text = "Playlists"
Me.CH_PLS.UseVisualStyleBackColor = True
'
'TXT_URL
'
Me.TXT_URL.CaptionText = "Channel URL"
Me.TXT_URL.CaptionWidth = 80.0R
Me.TXT_URL.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_URL.Location = New System.Drawing.Point(4, 4)
Me.TXT_URL.Name = "TXT_URL"
Me.TXT_URL.Size = New System.Drawing.Size(466, 22)
Me.TXT_URL.TabIndex = 0
'
'CH_URL_ASIS
'
Me.CH_URL_ASIS.AutoSize = True
Me.CH_URL_ASIS.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_URL_ASIS.Location = New System.Drawing.Point(4, 33)
Me.CH_URL_ASIS.Name = "CH_URL_ASIS"
Me.CH_URL_ASIS.Size = New System.Drawing.Size(466, 19)
Me.CH_URL_ASIS.TabIndex = 1
Me.CH_URL_ASIS.Text = "Download URL as is"
Me.CH_URL_ASIS.UseVisualStyleBackColor = True
'
'ChannelTabsChooserForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(474, 184)
Me.Controls.Add(CONTAINER_MAIN)
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
Me.Icon = Global.SCrawler.My.Resources.SiteYouTube.YouTubeIcon_32
Me.MaximizeBox = False
Me.MaximumSize = New System.Drawing.Size(490, 223)
Me.MinimizeBox = False
Me.MinimumSize = New System.Drawing.Size(490, 223)
Me.Name = "ChannelTabsChooserForm"
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
Me.Text = "Tabs"
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
CONTAINER_MAIN.ResumeLayout(False)
CONTAINER_MAIN.PerformLayout()
TP_MAIN.ResumeLayout(False)
TP_MAIN.PerformLayout()
CType(Me.TXT_URL, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
End Sub
Private WithEvents CH_ALL As CheckBox
Private WithEvents CH_VIDEOS As CheckBox
Private WithEvents CH_SHORTS As CheckBox
Private WithEvents CH_PLS As CheckBox
Private WithEvents TXT_URL As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents CH_URL_ASIS As CheckBox
End Class
End Namespace

View File

@@ -0,0 +1,126 @@
<?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>
</root>

View File

@@ -0,0 +1,85 @@
' Copyright (C) Andy https://github.com/AAndyProgram
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports PersonalUtilities.Forms
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.XML.Base
Imports SCrawler.API.YouTube.Base
Namespace API.YouTube.Controls
Friend Class ChannelTabsChooserForm : Implements IDesignXMLContainer
Private WithEvents MyDefs As DefaultFormOptions
Friend Property DesignXML As EContainer Implements IDesignXMLContainer.DesignXML
Private Property DesignXMLNodes As String() Implements IDesignXMLContainer.DesignXMLNodes
Private Property DesignXMLNodeName As String Implements IDesignXMLContainer.DesignXMLNodeName
Private _Result As YouTubeChannelTab = YouTubeChannelTab.All
Friend ReadOnly Property Result As YouTubeChannelTab
Get
Return _Result
End Get
End Property
Friend ReadOnly Property URL As String
Get
Return TXT_URL.Text
End Get
End Property
Friend ReadOnly Property MyUrlAsIs As Boolean
Get
Return CH_URL_ASIS.Checked
End Get
End Property
Friend Sub New(ByVal InitVal As YouTubeChannelTab, ByVal _URL As String)
InitializeComponent()
MyDefs = New DefaultFormOptions(Me)
_Result = InitVal
TXT_URL.Text = _URL
End Sub
Private Sub ChannelTabsChooserForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
With MyDefs
MyDefs.MyXML = DesignXML
If Not DesignXML Is Nothing Then .MyViewInitialize(True)
.AddOkCancelToolbar()
If _Result = YouTubeChannelTab.All And Not MyYouTubeSettings Is Nothing Then _Result = MyYouTubeSettings.ChannelsDownload
Dim r() As YouTubeChannelTab = _Result.EnumExtract(Of YouTubeChannelTab)
If r.ListExists Then
For Each value As YouTubeChannelTab In r
Select Case value
Case YouTubeChannelTab.All : CH_ALL.Checked = True
Case YouTubeChannelTab.Videos : CH_VIDEOS.Checked = True
Case YouTubeChannelTab.Shorts : CH_SHORTS.Checked = True
Case YouTubeChannelTab.Playlists : CH_PLS.Checked = True
End Select
Next
Else
CH_ALL.Checked = True
End If
UpdateCheckBoxes()
.EndLoaderOperations()
.MyOkCancel.EnableOK = True
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
_Result = YouTubeChannelTab.All
If Not CH_ALL.Checked And {CH_VIDEOS, CH_SHORTS, CH_PLS}.Any(Function(c) c.Checked) Then
If CH_VIDEOS.Checked Then _Result += YouTubeChannelTab.Videos
If CH_SHORTS.Checked Then _Result += YouTubeChannelTab.Shorts
If CH_PLS.Checked Then _Result += YouTubeChannelTab.Playlists
End If
MyDefs.CloseForm()
End Sub
Private Sub UpdateCheckBoxes() Handles CH_ALL.CheckedChanged, CH_URL_ASIS.CheckedChanged
Dim e As Boolean = Not CH_ALL.Checked And Not CH_URL_ASIS.Checked
CH_VIDEOS.Enabled = e
CH_SHORTS.Enabled = e
CH_PLS.Enabled = e
End Sub
End Class
End Namespace

View File

@@ -24,14 +24,15 @@ Namespace DownloadObjects.STDownloader
Private Sub InitializeComponent() Private Sub InitializeComponent()
Dim SEP_2 As System.Windows.Forms.ToolStripSeparator Dim SEP_2 As System.Windows.Forms.ToolStripSeparator
Dim SEP_3 As System.Windows.Forms.ToolStripSeparator Dim SEP_3 As System.Windows.Forms.ToolStripSeparator
Dim MENU_ADD_SEP_1 As System.Windows.Forms.ToolStripSeparator
Dim MENU_DEL_CLEAR As System.Windows.Forms.ToolStripDropDownButton Dim MENU_DEL_CLEAR As System.Windows.Forms.ToolStripDropDownButton
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(VideoListForm)) Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(VideoListForm))
Dim MENU_DEL_SEP_1 As System.Windows.Forms.ToolStripSeparator Dim MENU_DEL_SEP_1 As System.Windows.Forms.ToolStripSeparator
Dim MENU_DEL_SEP_2 As System.Windows.Forms.ToolStripSeparator
Me.BTT_DELETE = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_DELETE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CLEAR_SELECTED = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_CLEAR_SELECTED = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CLEAR_DONE = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_CLEAR_DONE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CLEAR_ALL = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_CLEAR_ALL = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_SELECT_ALL = New System.Windows.Forms.ToolStripMenuItem()
Me.TOOLBAR_BOTTOM = New System.Windows.Forms.StatusStrip() Me.TOOLBAR_BOTTOM = New System.Windows.Forms.StatusStrip()
Me.PR_MAIN = New System.Windows.Forms.ToolStripProgressBar() Me.PR_MAIN = New System.Windows.Forms.ToolStripProgressBar()
Me.LBL_INFO = New System.Windows.Forms.ToolStripStatusLabel() Me.LBL_INFO = New System.Windows.Forms.ToolStripStatusLabel()
@@ -42,8 +43,6 @@ Namespace DownloadObjects.STDownloader
Me.MENU_ADD = New System.Windows.Forms.ToolStripDropDownButton() Me.MENU_ADD = New System.Windows.Forms.ToolStripDropDownButton()
Me.BTT_ADD = New PersonalUtilities.Forms.Controls.KeyClick.ToolStripMenuItemKeyClick() Me.BTT_ADD = New PersonalUtilities.Forms.Controls.KeyClick.ToolStripMenuItemKeyClick()
Me.BTT_ADD_PLS_ARR = New PersonalUtilities.Forms.Controls.KeyClick.ToolStripMenuItemKeyClick() Me.BTT_ADD_PLS_ARR = New PersonalUtilities.Forms.Controls.KeyClick.ToolStripMenuItemKeyClick()
Me.BTT_ADD_NO_SHORTS = New PersonalUtilities.Forms.Controls.KeyClick.ToolStripMenuItemKeyClick()
Me.BTT_ADD_SHORTS_ONLY = New PersonalUtilities.Forms.Controls.KeyClick.ToolStripMenuItemKeyClick()
Me.BTT_DOWN = New System.Windows.Forms.ToolStripButton() Me.BTT_DOWN = New System.Windows.Forms.ToolStripButton()
Me.BTT_STOP = New System.Windows.Forms.ToolStripButton() Me.BTT_STOP = New System.Windows.Forms.ToolStripButton()
Me.SEP_LOG = New System.Windows.Forms.ToolStripSeparator() Me.SEP_LOG = New System.Windows.Forms.ToolStripSeparator()
@@ -51,11 +50,12 @@ Namespace DownloadObjects.STDownloader
Me.BTT_INFO = New System.Windows.Forms.ToolStripButton() Me.BTT_INFO = New System.Windows.Forms.ToolStripButton()
Me.BTT_DONATE = New System.Windows.Forms.ToolStripButton() Me.BTT_DONATE = New System.Windows.Forms.ToolStripButton()
Me.BTT_BUG_REPORT = New System.Windows.Forms.ToolStripButton() Me.BTT_BUG_REPORT = New System.Windows.Forms.ToolStripButton()
Me.BTT_SELECT_NONE = New System.Windows.Forms.ToolStripMenuItem()
SEP_2 = New System.Windows.Forms.ToolStripSeparator() SEP_2 = New System.Windows.Forms.ToolStripSeparator()
SEP_3 = New System.Windows.Forms.ToolStripSeparator() SEP_3 = New System.Windows.Forms.ToolStripSeparator()
MENU_ADD_SEP_1 = New System.Windows.Forms.ToolStripSeparator()
MENU_DEL_CLEAR = New System.Windows.Forms.ToolStripDropDownButton() MENU_DEL_CLEAR = New System.Windows.Forms.ToolStripDropDownButton()
MENU_DEL_SEP_1 = New System.Windows.Forms.ToolStripSeparator() MENU_DEL_SEP_1 = New System.Windows.Forms.ToolStripSeparator()
MENU_DEL_SEP_2 = New System.Windows.Forms.ToolStripSeparator()
Me.TOOLBAR_BOTTOM.SuspendLayout() Me.TOOLBAR_BOTTOM.SuspendLayout()
Me.TOOLBAR_TOP.SuspendLayout() Me.TOOLBAR_TOP.SuspendLayout()
Me.SuspendLayout() Me.SuspendLayout()
@@ -70,15 +70,10 @@ Namespace DownloadObjects.STDownloader
SEP_3.Name = "SEP_3" SEP_3.Name = "SEP_3"
SEP_3.Size = New System.Drawing.Size(6, 25) SEP_3.Size = New System.Drawing.Size(6, 25)
' '
'MENU_ADD_SEP_1
'
MENU_ADD_SEP_1.Name = "MENU_ADD_SEP_1"
MENU_ADD_SEP_1.Size = New System.Drawing.Size(181, 6)
'
'MENU_DEL_CLEAR 'MENU_DEL_CLEAR
' '
MENU_DEL_CLEAR.AutoToolTip = False MENU_DEL_CLEAR.AutoToolTip = False
MENU_DEL_CLEAR.DropDownItems.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_DELETE, MENU_DEL_SEP_1, Me.BTT_CLEAR_SELECTED, Me.BTT_CLEAR_DONE, Me.BTT_CLEAR_ALL}) MENU_DEL_CLEAR.DropDownItems.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_DELETE, MENU_DEL_SEP_1, Me.BTT_CLEAR_SELECTED, Me.BTT_CLEAR_DONE, Me.BTT_CLEAR_ALL, MENU_DEL_SEP_2, Me.BTT_SELECT_ALL, Me.BTT_SELECT_NONE})
MENU_DEL_CLEAR.Image = CType(resources.GetObject("MENU_DEL_CLEAR.Image"), System.Drawing.Image) MENU_DEL_CLEAR.Image = CType(resources.GetObject("MENU_DEL_CLEAR.Image"), System.Drawing.Image)
MENU_DEL_CLEAR.ImageTransparentColor = System.Drawing.Color.Magenta MENU_DEL_CLEAR.ImageTransparentColor = System.Drawing.Color.Magenta
MENU_DEL_CLEAR.Name = "MENU_DEL_CLEAR" MENU_DEL_CLEAR.Name = "MENU_DEL_CLEAR"
@@ -128,6 +123,17 @@ Namespace DownloadObjects.STDownloader
Me.BTT_CLEAR_ALL.Text = "Clear all" Me.BTT_CLEAR_ALL.Text = "Clear all"
Me.BTT_CLEAR_ALL.ToolTipText = "Remove all items from the list" Me.BTT_CLEAR_ALL.ToolTipText = "Remove all items from the list"
' '
'MENU_DEL_SEP_2
'
MENU_DEL_SEP_2.Name = "MENU_DEL_SEP_2"
MENU_DEL_SEP_2.Size = New System.Drawing.Size(182, 6)
'
'BTT_SELECT_ALL
'
Me.BTT_SELECT_ALL.Name = "BTT_SELECT_ALL"
Me.BTT_SELECT_ALL.Size = New System.Drawing.Size(185, 22)
Me.BTT_SELECT_ALL.Text = "Select all"
'
'TOOLBAR_BOTTOM 'TOOLBAR_BOTTOM
' '
Me.TOOLBAR_BOTTOM.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.PR_MAIN, Me.LBL_INFO}) Me.TOOLBAR_BOTTOM.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.PR_MAIN, Me.LBL_INFO})
@@ -186,7 +192,7 @@ Namespace DownloadObjects.STDownloader
'MENU_ADD 'MENU_ADD
' '
Me.MENU_ADD.AutoToolTip = False Me.MENU_ADD.AutoToolTip = False
Me.MENU_ADD.DropDownItems.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_ADD, Me.BTT_ADD_PLS_ARR, MENU_ADD_SEP_1, Me.BTT_ADD_NO_SHORTS, Me.BTT_ADD_SHORTS_ONLY}) Me.MENU_ADD.DropDownItems.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_ADD, Me.BTT_ADD_PLS_ARR})
Me.MENU_ADD.Image = CType(resources.GetObject("MENU_ADD.Image"), System.Drawing.Image) Me.MENU_ADD.Image = CType(resources.GetObject("MENU_ADD.Image"), System.Drawing.Image)
Me.MENU_ADD.ImageTransparentColor = System.Drawing.Color.Magenta Me.MENU_ADD.ImageTransparentColor = System.Drawing.Color.Magenta
Me.MENU_ADD.Name = "MENU_ADD" Me.MENU_ADD.Name = "MENU_ADD"
@@ -199,7 +205,7 @@ Namespace DownloadObjects.STDownloader
Me.BTT_ADD.Image = CType(resources.GetObject("BTT_ADD.Image"), System.Drawing.Image) Me.BTT_ADD.Image = CType(resources.GetObject("BTT_ADD.Image"), System.Drawing.Image)
Me.BTT_ADD.ImageTransparentColor = System.Drawing.Color.Magenta Me.BTT_ADD.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_ADD.Name = "BTT_ADD" Me.BTT_ADD.Name = "BTT_ADD"
Me.BTT_ADD.Size = New System.Drawing.Size(184, 22) Me.BTT_ADD.Size = New System.Drawing.Size(149, 22)
Me.BTT_ADD.Tag = "a" Me.BTT_ADD.Tag = "a"
Me.BTT_ADD.Text = "Add (Ins)" Me.BTT_ADD.Text = "Add (Ins)"
Me.BTT_ADD.ToolTipText = "Click to add." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Ctrl+click to use cookies for download (if supported)." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Shift to a" & Me.BTT_ADD.ToolTipText = "Click to add." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Ctrl+click to use cookies for download (if supported)." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Shift to a" &
@@ -211,35 +217,11 @@ Namespace DownloadObjects.STDownloader
Me.BTT_ADD_PLS_ARR.Image = CType(resources.GetObject("BTT_ADD_PLS_ARR.Image"), System.Drawing.Image) Me.BTT_ADD_PLS_ARR.Image = CType(resources.GetObject("BTT_ADD_PLS_ARR.Image"), System.Drawing.Image)
Me.BTT_ADD_PLS_ARR.ImageTransparentColor = System.Drawing.Color.Magenta Me.BTT_ADD_PLS_ARR.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_ADD_PLS_ARR.Name = "BTT_ADD_PLS_ARR" Me.BTT_ADD_PLS_ARR.Name = "BTT_ADD_PLS_ARR"
Me.BTT_ADD_PLS_ARR.Size = New System.Drawing.Size(184, 22) Me.BTT_ADD_PLS_ARR.Size = New System.Drawing.Size(149, 22)
Me.BTT_ADD_PLS_ARR.Tag = "pls" Me.BTT_ADD_PLS_ARR.Tag = "pls"
Me.BTT_ADD_PLS_ARR.Text = "Add playlist array" Me.BTT_ADD_PLS_ARR.Text = "Add URL array"
Me.BTT_ADD_PLS_ARR.ToolTipText = "Click to add." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Ctrl+click to use cookies for download (if supported)." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Shift to a" & Me.BTT_ADD_PLS_ARR.ToolTipText = "Click to add." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Ctrl+click to use cookies for download (if supported)." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Shift to a" &
"dd without downloading." "dd without downloading."
'
'BTT_ADD_NO_SHORTS
'
Me.BTT_ADD_NO_SHORTS.AutoToolTip = True
Me.BTT_ADD_NO_SHORTS.Image = CType(resources.GetObject("BTT_ADD_NO_SHORTS.Image"), System.Drawing.Image)
Me.BTT_ADD_NO_SHORTS.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_ADD_NO_SHORTS.Name = "BTT_ADD_NO_SHORTS"
Me.BTT_ADD_NO_SHORTS.Size = New System.Drawing.Size(184, 22)
Me.BTT_ADD_NO_SHORTS.Tag = "ans"
Me.BTT_ADD_NO_SHORTS.Text = "Add (without Shorts)"
Me.BTT_ADD_NO_SHORTS.ToolTipText = "Download all videos except 'Shorts'." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Click to add." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Ctrl+click to use cookies fo" &
"r download (if supported)." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Shift to add without downloading."
'
'BTT_ADD_SHORTS_ONLY
'
Me.BTT_ADD_SHORTS_ONLY.AutoToolTip = True
Me.BTT_ADD_SHORTS_ONLY.Image = CType(resources.GetObject("BTT_ADD_SHORTS_ONLY.Image"), System.Drawing.Image)
Me.BTT_ADD_SHORTS_ONLY.ImageTransparentColor = System.Drawing.Color.Magenta
Me.BTT_ADD_SHORTS_ONLY.Name = "BTT_ADD_SHORTS_ONLY"
Me.BTT_ADD_SHORTS_ONLY.Size = New System.Drawing.Size(184, 22)
Me.BTT_ADD_SHORTS_ONLY.Tag = "as"
Me.BTT_ADD_SHORTS_ONLY.Text = "Add (Shorts only)"
Me.BTT_ADD_SHORTS_ONLY.ToolTipText = "Download only 'Shorts' videos." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Click to add." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Ctrl+click to use cookies for down" &
"load (if supported)." & Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10) & "Shift to add without downloading."
' '
'BTT_DOWN 'BTT_DOWN
' '
@@ -304,6 +286,12 @@ Namespace DownloadObjects.STDownloader
Me.BTT_BUG_REPORT.Size = New System.Drawing.Size(23, 22) Me.BTT_BUG_REPORT.Size = New System.Drawing.Size(23, 22)
Me.BTT_BUG_REPORT.Text = "Bug report" Me.BTT_BUG_REPORT.Text = "Bug report"
' '
'BTT_SELECT_NONE
'
Me.BTT_SELECT_NONE.Name = "BTT_SELECT_NONE"
Me.BTT_SELECT_NONE.Size = New System.Drawing.Size(185, 22)
Me.BTT_SELECT_NONE.Text = "Select none"
'
'VideoListForm 'VideoListForm
' '
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
@@ -343,11 +331,11 @@ Namespace DownloadObjects.STDownloader
Private WithEvents BTT_DONATE As ToolStripButton Private WithEvents BTT_DONATE As ToolStripButton
Protected WithEvents BTT_ADD As PersonalUtilities.Forms.Controls.KeyClick.ToolStripMenuItemKeyClick Protected WithEvents BTT_ADD As PersonalUtilities.Forms.Controls.KeyClick.ToolStripMenuItemKeyClick
Protected WithEvents BTT_ADD_PLS_ARR As PersonalUtilities.Forms.Controls.KeyClick.ToolStripMenuItemKeyClick Protected WithEvents BTT_ADD_PLS_ARR As PersonalUtilities.Forms.Controls.KeyClick.ToolStripMenuItemKeyClick
Protected WithEvents BTT_ADD_NO_SHORTS As PersonalUtilities.Forms.Controls.KeyClick.ToolStripMenuItemKeyClick
Protected WithEvents BTT_ADD_SHORTS_ONLY As PersonalUtilities.Forms.Controls.KeyClick.ToolStripMenuItemKeyClick
Protected WithEvents MENU_ADD As ToolStripDropDownButton Protected WithEvents MENU_ADD As ToolStripDropDownButton
Protected WithEvents BTT_DOWN As ToolStripButton Protected WithEvents BTT_DOWN As ToolStripButton
Private WithEvents BTT_BUG_REPORT As ToolStripButton Private WithEvents BTT_BUG_REPORT As ToolStripButton
Private WithEvents BTT_CLEAR_SELECTED As ToolStripMenuItem Private WithEvents BTT_CLEAR_SELECTED As ToolStripMenuItem
Private WithEvents BTT_SELECT_ALL As ToolStripMenuItem
Private WithEvents BTT_SELECT_NONE As ToolStripMenuItem
End Class End Class
End Namespace End Namespace

View File

@@ -123,9 +123,6 @@
<metadata name="SEP_3.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="SEP_3.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<metadata name="MENU_ADD_SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="MENU_DEL_CLEAR.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="MENU_DEL_CLEAR.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
@@ -134,29 +131,29 @@
<value> <value>
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
9iQAAAAASUVORK5CYII= HR8AAAAASUVORK5CYII=
</value> </value>
</data> </data>
<metadata name="MENU_DEL_SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="MENU_DEL_SEP_1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
@@ -195,87 +192,90 @@
<value> <value>
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
9iQAAAAASUVORK5CYII= HR8AAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="BTT_CLEAR_ALL.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="BTT_CLEAR_ALL.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAVDSURBVEhLjZVtTFNXGMcLQmdHO6AdarLSOcTxXqC3lls3 YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAVDSURBVEhLjZVtTFNXGMcLQmdHO6AdarLSOcTxXqC3lls3
FceLFC3YUkHHiJpRcQXFF5QoRmM00fiSLNmH7cP2YctMZtwyXZaNCaNsTsAJAzdcENBhLaXvhctekkV6 FeVFihZsqaBjRM2ouILiC0oUozGaaBSTJfuwfdg+bJnJnFuiyzKZMOp8ATJl4IYLAjqspfS9cNlLskjP
9j+l1RnLxpP8cnvPec7/+fc5597LozFQVBRjTkp6v3PJkpGrMtl766XSFzAcFZj8nxhWqdjfZLJro4sX /qe0OmPZeJJfbu85z/k//z7n3Ht5NPqLimLMSUkfXV20aPiKTPbhOqn0FQxHBSb/J4ZUKvY3mez6yMKF
919OTjZgKAZEBCZpDJpMwptFRZ8ONzeTsfPnyXdNTf6rLNuRJxItx3T0bFb4GGKYV21bttznzpwh0+fO fReTkw0YigERgUkaAyaT8FZR0ZdDzc1k9OxZ0tHU5L/Csp15ItFSTEfPZIWPQYZ507Z580Pu9Gky1dpK
kZHKSs87qan1stjYeEzPFulYtuzdO/v2kXvHj5OxY8eIFcmWgwdJK8tek4tELyMlbJFRtfo1iFu4s2cJ hisrPe+nptbLYmPjMT1TpHPJkg/u7d1LHhw7RkaPHiVWJFsOHCBtLHtdLhK9jpSwRUbU6jUQt3BnzhAO
h7VcSwuZPnqU3NFqvV9IpW8jRQyieJ0SiZWK32tqIvcPHyZWJE2cOkW6m5v9V1WqH7JEohQkPlEEbSm2 a7mWFjJ15Ai5p9V6v5ZK30OKGETxrkokVir+oKmJPDx0iFiRNH7yJLnW3Oy/olLdyBKJUpD4TBG0pdhW
VVVZqXMqPg1x7sABMg1jvpoaYk5IuI00Foh47YmJF0Zqa8kYCliA9dAhYsMCx8mT5Aba1c6y3ZlCYSqS VWWlzqn4FMS5/fvJFIz5amqIOSHhLtJYIOJ1JCaeG66tJaMoYAHWgweJDQscJ06QG2hXB8t2ZwqFqUgO
A0WGFYriicpK69Tp04SDmWmY4rBueu9eMrlzJ2lVqVxbJZJLSC0FYp5+6dIXW5XKa53bt/sfIGkcTMCN FBlSKIrHKyutk6dOEQ5mpmCKw7qpPXvIxI4dpE2lcm2RSC4gtRSIefrFi19tUyqvt2/b5n+EpDEwDjcO
A3viRsuc+/eTThTJFQrTfmKYonGDwTZ14kSgJRwcc2gv19hIpiBuzs31pAgEH0HYCOSAbjgvmpFIUlGk 7IkbLXPu20euokiuUJj2E8MUjRkMtsnjxwMt4eCYQ3u5xkYyCXFzbq4nRSD4FMJGIAd0w3nRjESSiiLd
27J1K7Ht2kXsDQ3EsWcPcaGYF0K9DQ3+HrX61t3ycit35EjAMYc5Drlcff0j8TSB4AL0akFGUDwSBIKf li1biG3nTmJvaCCO3buJC8W8EOpuaPD3qNV37peXW7nDhwOOOcxxyOXq65+IpwkE56BXCzKC4pEgEPxc
KxanfaNQdHVVV/vtdXXECdwmE/FAwIdivt27yRTcTlFh3HO4D4ijvV1KpVcuFFJx6jwdLASPj2ow+Cqx sTjtO4Wi64fqar+9ro44gdtkIh4I+FDMt2sXmYTbSSqMew73AXG0t0up9MqFQipOnaeD+eDpUQ0GXyUW
OL09O7vbtmkTcW7bRtzAazQSHxxOouAkNnCyvJz41q4lPrWaeEBXXp4vRyS6iPU7AHUuAE+Jh4K/Ij4+ p3dkZ3fbNm4kzq1biRt4jUbig8MJFJzABk6UlxPf6tXEp1YTD+jKy/PliETnsX47oM4F4DnxUPCXxcdn
o10u7x7MyXno2byZuDUa4mYY4pJKiUskIq7oaOJasID0CoX+tqQkLxsXRze0DmSCZ8Gc4qEItOumXD4w dMjl3QMZGY89mzYRt0ZD3AxDXFIpcYlExBUdTVzz5pFuodDfnpTkZePi6IbWgUzwIphVPBSBdt2Sy/vH
AUE7xBzACahwgKgo0p+d/ZchNfUr5L8FssC8xANhq6kx2dRqi10geFoc0LHB5OSHZq32blpiYjmWxIL5 IWiHmAM4ARUOEBVF+rKz/zKkpn6L/HdBFpiTeCBsNTUmm1ptsQsEz4sDOjaQnPzYrNXeT0tMLMeSWDA3
ifuMxv2uggKXHe7nEh8H94ElI4P063S3X1+5MgdL//O1Egi30djiXLfObY+JeUrcid7TdlHxMTASGUkG cZ/RuM9VUOCyw/1s4mPgIbBkZJA+ne7uW8uX52Dpf75WAuE2Gluca9e67TExz4k70XvaLio+CoYjI8kA
QXtOjn+gouJXA8vSNs1dxLtjx2FHSYknnHOnREIelJT8fSMlxU/Fh4PifaALmBlmZoD+k7mK4Ci22AsK uJyT4++vqPjVwLK0TbMX8W7ffshRUuIJ59wpkZBHJSV/30hJ8VPxoaB4L+gCZoaZ7qf/ZLYiOIot9oIC
vHahMCD8RFsWLSJDpaW/n1i9uqdvw4YJS1oa+QWiveA6+J4WoKxYMfOjwXCrQC6nL8jHr3pPbW0zFXeE r10oDAg/05YFC8hgaenvx1eu7Oldv37ckpZGfoHobXATXKMFKMuWTf9oMNwpkMvpC/Lpq95TW9tMxR3h
E09IIENr1vxRzzDtSG0oycx843ZZ2d0h9D4k3gHaQCstolLN9FRU9H2o1dKN54MInmfjRqsjLi68c4jX xBMSyOCqVX/UM0wHUhtKMjPfvltWdn8QvQ+Jd4J20EaLqFTTPRUVvZ9otXTj+SCC59mwweqIiwvvHOJ1
KRRtSDQBupHiPfn5r/Tr9aO3srIeiX8NvgRXwEB6+sNevf4OcpcCPs+u0w15ZLKwzk0M8y2S6oPioS8V CkU7Ek2AbqR4d37+G316/cidrKwn4pfBN+AS6E9Pf3xbr7+H3MWAz7PrdIMemSyscxPDfI+k+qB46EvF
f29hIdtfUTF6OSvL/2/xzyIiSC8KmDWaceQVgXheT3X1lgmNxu2GaMj5YHHxn7vCi4eC35ifn4eNHbmZ 31NYyPZVVIxcyMry/1v8q4gIchsFzBrNGPKKQDyvp7p687hG43ZDNOR8oLj4z53hxUPBb8zPz8PGDt/K
nU0uB8XNeXkzn2g0D0qXL/8AObMFEAvbKiuPWMvKvH0s66fOG5XKDozPJR4KvnHVKgVtx+dYZ1arZy7B ziYXg+LmvLzpzzWaR6VLl36MnJkCiPntlZWHrWVl3h6W9VPnjUplJ8ZnEw8F37hihYK24wusM6vV0xfg
+XMCwTnM6cBsixARTFJSbJ9e//G9sjLnxcJCnL7IRowzQEjnadIcwb9SVfXmzzrd+HWt1lWSkkK/BXog /CWBoBVzOjDTIkQEk5QU26vXf/agrMx5vrAQpy+yEeMMENJ5mjRL8C9VVb3zs043dlOrdZWkpNBvgR5I
BfS4PlpLf8QBJVgfvM738X8G0KNJT84G8BII+8AtANQx/VjTK72fT1AT9P3/fBBaMGiMx/sHXLrYtE2a AT2uT9bSH3FACdYFr3N9/F8A9GjSk7MevAbCPnDzAHVMP9b0Su/nEtQEff+/HIQWDBrj8f4B7zPYbtFn
9iQAAAAASUVORK5CYII= HR8AAAAASUVORK5CYII=
</value> </value>
</data> </data>
<metadata name="MENU_DEL_SEP_2.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<data name="MENU_DEL_CLEAR.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="MENU_DEL_CLEAR.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
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
22tl8CvUAAAAAElFTkSuQmCC dCWdzmEAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<metadata name="TOOLBAR_BOTTOM.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="TOOLBAR_BOTTOM.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
@@ -287,135 +287,93 @@
<data name="BTT_ADD.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="BTT_ADD.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
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
jZbUijkXhD9w0a0SO8Tg+AAAAABJRU5ErkJggg== hKygM1JCJAAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="BTT_ADD_PLS_ARR.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="BTT_ADD_PLS_ARR.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
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 H0WkrMjY2947AAAAAElFTkSuQmCC
</value>
</data>
<data name="BTT_ADD_NO_SHORTS.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAN6SURBVEhLrZVJTFNRFIYfQhgkQA1OZTCKoqLBVgRRpEpb
hQpqrAwiBYJIQTCiBCpxSuO41GjcGRfEGOPGYFw5LJAYFQco8opQIKUTFEkw7K/5PfelRBYEDL6T/GmT
e/N/55733/eEhSr0XnBb2P1gzCW+Fti2+OJGabZUpuvR4ECvBgaRZNeg2KmXIIFtiy9ukvE9lS3tFBD9
UUDsFwHx30Jg9ubLB9glprKYTwJWfAnC2p4wqMVoXPAXygfYQwDeeZItDGn9McgZWIWbk+XyAbRiGkuy
hSOjX4E8RxzNfwPuTdXKB6gWd7F0uwL5jniUjW5CrUuNR9ON8gGaxRxmGEpAhSsFDe40NHuy8GTa8m+A
+XI+I3Of7ne5azPOutPROqbBNX8u2n61YPnTiHmlfB7ZJnWon8k45btgQINjDh0qnXk46zmCi75i3PJX
0v90XPLtxXV/Hm5MGNA21YLHUxYJ9HCqEXcna3B9woQLviIaYQEaXMehbI+EBODm0R8o410CEnpCoaIY
8qQYR5Jw0rUV5zyZuDymJQMDbk/kS4Br47lkpkGtW42SkWToB1dDZY9GYncoFORz3G78C+Cdc3O+qLJH
0WYlCgPm572ZuOLT4YbfQIBcXB3XweLLpmexA1WjW3B0eB32DaxEqhiFuJ4QKD4LiKBLWdg7C1DQr8Ea
MldTB3qHUoqh2a1Ck3cnLo3l4AqZXvTtg8WbjfOeDNTRWoVrCw4Pr8VeOqlk3h0Cfhm5edBrAcbPswAn
HPuxuz+WYpgAk3MzGulhtlBSWsmQmzZ7syQ10ajqaCQ8TYeG1yD7x0qk9EVC+TUYUTTi8A4BwitSOwHe
zwLUD2Qxy5COWUcrmNV1ilnddczqqaXf0+ym4wx78LOezHfC7FKhdHQj8ocT0eqphMlm+F0j6lm5qGWl
JB1J+530jdSlZRKAx3SuiM2Ib7oz1MrM7m0odSbjIJ0yk07b4C6V1uYVj+lCxTfedjSxEnoueYPx2EE3
er0tAlXOY5JJYNvii5tYfzSw3ME46UXH36axlJQyR2DG/1sSQKxh2+0xSKCkLKM4829D0UzO/7e4SaNo
YondYVBQDJe+ExD8hlJikxFQLeoYNw+nzpfwGL4kwCcZASaKXwR1LtAFEl6QnhGgU0ZAUZ9RGomxi0QX
yNhBeisXgLLMjebUgjkXhD+4Jq73JQ87ogAAAABJRU5ErkJggg==
</value>
</data>
<data name="BTT_ADD_SHORTS_ONLY.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAN6SURBVEhLrZVJTFNRFIYfQhgkQA1OZTCKoqLBVgRRpEpb
hQpqrAwiBYJIQTCiBCpxSuO41GjcGRfEGOPGYFw5LJAYFQco8opQIKUTFEkw7K/5PfelRBYEDL6T/GmT
e/N/55733/eEhSr0XnBb2P1gzCW+Fti2+OJGabZUpuvR4ECvBgaRZNeg2KmXIIFtiy9ukvE9lS3tFBD9
UUDsFwHx30Jg9ubLB9glprKYTwJWfAnC2p4wqMVoXPAXygfYQwDeeZItDGn9McgZWIWbk+XyAbRiGkuy
hSOjX4E8RxzNfwPuTdXKB6gWd7F0uwL5jniUjW5CrUuNR9ON8gGaxRxmGEpAhSsFDe40NHuy8GTa8m+A
+XI+I3Of7ne5azPOutPROqbBNX8u2n61YPnTiHmlfB7ZJnWon8k45btgQINjDh0qnXk46zmCi75i3PJX
0v90XPLtxXV/Hm5MGNA21YLHUxYJ9HCqEXcna3B9woQLviIaYQEaXMehbI+EBODm0R8o410CEnpCoaIY
8qQYR5Jw0rUV5zyZuDymJQMDbk/kS4Br47lkpkGtW42SkWToB1dDZY9GYncoFORz3G78C+Cdc3O+qLJH
0WYlCgPm572ZuOLT4YbfQIBcXB3XweLLpmexA1WjW3B0eB32DaxEqhiFuJ4QKD4LiKBLWdg7C1DQr8Ea
MldTB3qHUoqh2a1Ck3cnLo3l4AqZXvTtg8WbjfOeDNTRWoVrCw4Pr8VeOqlk3h0Cfhm5edBrAcbPswAn
HPuxuz+WYpgAk3MzGulhtlBSWsmQmzZ7syQ10ajqaCQ8TYeG1yD7x0qk9EVC+TUYUTTi8A4BwitSOwHe
zwLUD2Qxy5COWUcrmNV1ilnddczqqaXf0+ym4wx78LOezHfC7FKhdHQj8ocT0eqphMlm+F0j6lm5qGWl
JB1J+530jdSlZRKAx3SuiM2Ib7oz1MrM7m0odSbjIJ0yk07b4C6V1uYVj+lCxTfedjSxEnoueYPx2EE3
er0tAlXOY5JJYNvii5tYfzSw3ME46UXH36axlJQyR2DG/1sSQKxh2+0xSKCkLKM4829D0UzO/7e4SaNo
YondYVBQDJe+ExD8hlJikxFQLeoYNw+nzpfwGL4kwCcZASaKXwR1LtAFEl6QnhGgU0ZAUZ9RGomxi0QX
yNhBeisXgLLMjebUgjkXhD+4Jq73JQ87ogAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="MENU_ADD.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="MENU_ADD.Image" 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="BTT_STOP.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="BTT_STOP.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
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
ugAAAABJRU5ErkJggg== bAAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="BTT_LOG.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="BTT_LOG.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">

View File

@@ -59,8 +59,6 @@ Namespace DownloadObjects.STDownloader
MyDownloaderSettings = MyYouTubeSettings MyDownloaderSettings = MyYouTubeSettings
End If End If
CheckVersion(False)
With MyView : .Import() : .SetFormSize() : End With With MyView : .Import() : .SetFormSize() : End With
BTT_DELETE.Enabled = False BTT_DELETE.Enabled = False
If Not AppMode Then If Not AppMode Then
@@ -239,8 +237,7 @@ Namespace DownloadObjects.STDownloader
Protected Overridable Sub BTT_SETTINGS_Click(sender As Object, e As EventArgs) Handles BTT_SETTINGS.Click Protected Overridable Sub BTT_SETTINGS_Click(sender As Object, e As EventArgs) Handles BTT_SETTINGS.Click
MyYouTubeSettings.ShowForm(AppMode) MyYouTubeSettings.ShowForm(AppMode)
End Sub End Sub
Protected Overridable Sub BTT_ADD_KeyClick(ByVal Sender As ToolStripMenuItemKeyClick, ByVal e As KeyClickEventArgs) Handles BTT_ADD.KeyClick, BTT_ADD_PLS_ARR.KeyClick, Protected Overridable Sub BTT_ADD_KeyClick(ByVal Sender As ToolStripMenuItemKeyClick, ByVal e As KeyClickEventArgs) Handles BTT_ADD.KeyClick, BTT_ADD_PLS_ARR.KeyClick
BTT_ADD_NO_SHORTS.KeyClick, BTT_ADD_SHORTS_ONLY.KeyClick
Dim pForm As ParsingProgressForm = Nothing Dim pForm As ParsingProgressForm = Nothing
Try Try
Dim useCookies As Boolean = MyYouTubeSettings.DefaultUseCookies Dim useCookies As Boolean = MyYouTubeSettings.DefaultUseCookies
@@ -254,8 +251,6 @@ Namespace DownloadObjects.STDownloader
Dim c As IYouTubeMediaContainer = Nothing Dim c As IYouTubeMediaContainer = Nothing
Dim url$ = String.Empty Dim url$ = String.Empty
Dim GetDefault As Boolean = True
Dim GetShorts As Boolean = True
If sTag = "pls" Then If sTag = "pls" Then
Using pf As New PlaylistArrayForm With {.DesignXML = DesignXML} Using pf As New PlaylistArrayForm With {.DesignXML = DesignXML}
@@ -268,7 +263,7 @@ Namespace DownloadObjects.STDownloader
pForm.SetInitialValues(.Count, "Parsing playlists...") pForm.SetInitialValues(.Count, "Parsing playlists...")
Dim containers As New List(Of IYouTubeMediaContainer) Dim containers As New List(Of IYouTubeMediaContainer)
For Each u$ In .Self For Each u$ In .Self
containers.Add(YouTubeFunctions.Parse(standardize(u), useCookiesParse, pForm.Token, pForm.MyProgress, True, False)) containers.Add(YouTubeFunctions.Parse(standardize(u), useCookiesParse, pForm.Token, pForm.MyProgress))
pForm.NextPlaylist() pForm.NextPlaylist()
pForm.MyProgress.Perform() pForm.MyProgress.Perform()
Next Next
@@ -297,20 +292,36 @@ Namespace DownloadObjects.STDownloader
End If End If
End Using End Using
Else Else
Select Case sTag
Case "ans" : GetShorts = False
Case "as" : GetDefault = False : GetShorts = True
End Select
url = BufferText url = BufferText
If url.IsEmptyString OrElse Not YouTubeFunctions.IsMyUrl(url) Then url = InputBoxE("Enter a valid URL to the YouTube video:", "YouTube link") If url.IsEmptyString OrElse Not YouTubeFunctions.IsMyUrl(url) Then url = InputBoxE("Enter a valid URL to the YouTube video:", "YouTube link")
End If End If
If Not c Is Nothing OrElse YouTubeFunctions.IsMyUrl(url) Then If Not c Is Nothing OrElse YouTubeFunctions.IsMyUrl(url) Then
If c Is Nothing Then If c Is Nothing Then
Dim downAsIs As Boolean = False
Dim channelTab As YouTubeChannelTab? = Nothing
Dim __channelTab As YouTubeChannelTab = YouTubeChannelTab.All
Dim oType As YouTubeMediaType = YouTubeFunctions.Info_GetUrlType(url,,,,, __channelTab)
If oType = YouTubeMediaType.Channel Then
channelTab = __channelTab
Using channelTabForm As New ChannelTabsChooserForm(__channelTab, url) With {.DesignXML = DesignXML}
With channelTabForm
.ShowDialog()
If .DialogResult = DialogResult.OK Then
channelTab = .Result
downAsIs = .MyUrlAsIs
url = YouTubeFunctions.StandardizeURL_Channel(.URL, Not downAsIs)
Else
Exit Sub
End If
End With
End Using
End If
pForm = New ParsingProgressForm pForm = New ParsingProgressForm
pForm.Show(Me) pForm.Show(Me)
pForm.SetInitialValues(1, "Parsing data...") pForm.SetInitialValues(1, "Parsing data...")
c = YouTubeFunctions.Parse(standardize(url), useCookiesParse, pForm.Token, pForm.MyProgress, GetDefault, GetShorts) c = YouTubeFunctions.Parse(standardize(url), useCookiesParse, pForm.Token, pForm.MyProgress,,, channelTab,
oType <> YouTubeMediaType.Channel Or downAsIs)
pForm.Dispose() pForm.Dispose()
End If End If
If Not c Is Nothing Then If Not c Is Nothing Then
@@ -424,6 +435,19 @@ Namespace DownloadObjects.STDownloader
Protected Overridable Sub BTT_CLEAR_ALL_Click(sender As Object, e As EventArgs) Handles BTT_CLEAR_ALL.Click Protected Overridable Sub BTT_CLEAR_ALL_Click(sender As Object, e As EventArgs) Handles BTT_CLEAR_ALL.Click
RemoveControls(, False) RemoveControls(, False)
End Sub End Sub
Private Sub BTT_SELECT_ALL_Click(sender As Object, e As EventArgs) Handles BTT_SELECT_ALL.Click, BTT_SELECT_NONE.Click
Try
Dim checked As Boolean = sender Is BTT_SELECT_ALL
ControlInvokeFast(TP_CONTROLS, Sub()
With TP_CONTROLS.Controls
If .Count > 0 Then
For Each cnt As MediaItem In .Self : cnt.Checked = checked : Next
End If
End With
End Sub, EDP.None)
Catch
End Try
End Sub
#End Region #End Region
Private Sub BTT_LOG_Click(sender As Object, e As EventArgs) Handles BTT_LOG.Click Private Sub BTT_LOG_Click(sender As Object, e As EventArgs) Handles BTT_LOG.Click
MyMainLOG_ShowForm(DesignXML,,,, AddressOf UpdateLogButton) MyMainLOG_ShowForm(DesignXML,,,, AddressOf UpdateLogButton)
@@ -444,7 +468,10 @@ Namespace DownloadObjects.STDownloader
Try : Process.Start("https://github.com/AAndyProgram/SCrawler/blob/main/HowToSupport.md") : Catch : End Try Try : Process.Start("https://github.com/AAndyProgram/SCrawler/blob/main/HowToSupport.md") : Catch : End Try
End Sub End Sub
Private Sub BTT_INFO_Click(sender As Object, e As EventArgs) Handles BTT_INFO.Click Private Sub BTT_INFO_Click(sender As Object, e As EventArgs) Handles BTT_INFO.Click
CheckVersion(True) CheckVersionImpl(True)
End Sub
Protected Sub CheckVersionImpl(ByVal Force As Boolean)
CheckVersion(Force)
End Sub End Sub
Protected Overloads Sub RemoveControls(Optional ByVal Predicate As Predicate(Of MediaItem) = Nothing, Optional ByVal RemoveFiles As Boolean = False) Protected Overloads Sub RemoveControls(Optional ByVal Predicate As Predicate(Of MediaItem) = Nothing, Optional ByVal RemoveFiles As Boolean = False)
ControlInvokeFast(TP_CONTROLS, Sub() ControlInvokeFast(TP_CONTROLS, Sub()
@@ -497,16 +524,23 @@ Namespace DownloadObjects.STDownloader
RemoveControls(Sender, False) RemoveControls(Sender, False)
End Sub End Sub
Private Sub MediaControl_DownloadAgain(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer) Private Sub MediaControl_DownloadAgain(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer)
If Not Container.URL.IsEmptyString Then BufferText = Container.URL : BTT_ADD.PerformClick() Try
If Not Container.URL.IsEmptyString Then BufferText = Container.URL : BTT_ADD.PerformClick()
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[VideoListForm.DownloadAgain]")
End Try
End Sub End Sub
Private Sub MediaControl_DownloadRequested(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer) Private Sub MediaControl_DownloadRequested(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer)
AddToDownload(Sender, True) AddToDownload(Sender, True)
End Sub End Sub
Private Sub MediaControl_CheckedChanged(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer) Private Sub MediaControl_CheckedChanged(ByVal Sender As MediaItem, ByVal Container As IYouTubeMediaContainer)
With TP_CONTROLS.Controls Try
ControlInvokeFast(TOOLBAR_TOP, BTT_DELETE, With TP_CONTROLS.Controls
Sub() BTT_DELETE.Enabled = .Count > 0 AndAlso .Cast(Of MediaItem).ListExists(Function(cnt) cnt.Checked), EDP.None) ControlInvokeFast(TOOLBAR_TOP, BTT_DELETE,
End With Sub() BTT_DELETE.Enabled = .Count > 0 AndAlso .Cast(Of MediaItem).ListExists(Function(cnt) cnt.Checked), EDP.None)
End With
Catch
End Try
End Sub End Sub
#End Region #End Region
#End Region #End Region

View File

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

View File

@@ -856,33 +856,35 @@ Namespace API.YouTube.Objects
CreateUrlFile(url, ff) CreateUrlFile(url, ff)
If ff.Exists Then Files.Add(ff) If ff.Exists Then Files.Add(ff)
End If End If
Using resp As New Responser If MyYouTubeSettings.CreateThumbnails_Music Then
If UseCookies And MyYouTubeSettings.Cookies.Count > 0 Then resp.Cookies.AddRange(MyYouTubeSettings.Cookies,, EDP.SendToLog) Using resp As New Responser
r = resp.GetResponse(url,, EDP.ReturnValue) If UseCookies And MyYouTubeSettings.Cookies.Count > 0 Then resp.Cookies.AddRange(MyYouTubeSettings.Cookies,, EDP.SendToLog)
If Not r.IsEmptyString Then r = resp.GetResponse(url,, EDP.ReturnValue)
Dim p As RParams = RParams.DM("(?<=https:[\\/]{2,4})[^\.]*[\.]?googleusercontent.com[^\,]+?w(\d+).h(\d+)[^\,]+?(?=\\x22)", 0, RegexReturn.List, EDP.ReturnValue) If Not r.IsEmptyString Then
Dim l As List(Of String) = RegexReplace(r, p) Dim p As RParams = RParams.DM("(?<=https:[\\/]{2,4})[^\.]*[\.]?googleusercontent.com[^\,]+?w(\d+).h(\d+)[^\,]+?(?=\\x22)", 0, RegexReturn.List, EDP.ReturnValue)
If l.ListExists Then l.RemoveAll(Function(uu) uu.IsEmptyString) Dim l As List(Of String) = RegexReplace(r, p)
If l.ListExists Then If l.ListExists Then l.RemoveAll(Function(uu) uu.IsEmptyString)
Dim u$ = l.Last If l.ListExists Then
u = u.Replace("\/", "/").TrimStart("/") Dim u$ = l.Last
Dim position% u = u.Replace("\/", "/").TrimStart("/")
Dim ch$ Dim position%
Do Dim ch$
position = InStr(u, "\") Do
If position > 0 Then position = InStr(u, "\")
ch = $"%{Mid(u, position + 2, 2)}" If position > 0 Then
ch = SymbolsConverter.ASCII.Decode(ch, New ErrorsDescriber(False, False, False, String.Empty)) ch = $"%{Mid(u, position + 2, 2)}"
u = u.Replace(Mid(u, position, 4), ch) ch = SymbolsConverter.ASCII.Decode(ch, New ErrorsDescriber(False, False, False, String.Empty))
End If u = u.Replace(Mid(u, position, 4), ch)
Loop While position > 0 End If
url = LinkFormatterSecure(u) Loop While position > 0
f.Name = "cover" url = LinkFormatterSecure(u)
f.Extension = "jpg" f.Name = "cover"
If resp.DownloadFile(url, f, EDP.ReturnValue) And f.Exists Then CoverDownloaded = True f.Extension = "jpg"
If resp.DownloadFile(url, f, EDP.ReturnValue) And f.Exists Then CoverDownloaded = True
End If
End If End If
End If End Using
End Using End If
Catch ex As Exception Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, $"DownloadPlaylistCover({PlsId}, {f})") ErrorsDescriber.Execute(EDP.SendToLog, ex, $"DownloadPlaylistCover({PlsId}, {f})")
End Try End Try
@@ -951,7 +953,9 @@ Namespace API.YouTube.Objects
_ThumbnailFile = File _ThumbnailFile = File
_ThumbnailFile.Name &= "_thumb" _ThumbnailFile.Name &= "_thumb"
_ThumbnailFile.Extension = "jpg" _ThumbnailFile.Extension = "jpg"
If Not ThumbnailUrl.IsEmptyString Then GetWebFile(ThumbnailUrl, _ThumbnailFile, EDP.None) If Not ThumbnailUrl.IsEmptyString And
If(IsMusic, MyYouTubeSettings.CreateThumbnails_Music, MyYouTubeSettings.CreateThumbnails_Video).Value Then _
GetWebFile(ThumbnailUrl, _ThumbnailFile, EDP.None)
ThrowAny(Token) ThrowAny(Token)
If MyYouTubeSettings.FFMPEG.Value.Exists Then If MyYouTubeSettings.FFMPEG.Value.Exists Then

View File

@@ -115,6 +115,12 @@
<ItemGroup> <ItemGroup>
<Compile Include="Attributes\GridVisibleAttribute.vb" /> <Compile Include="Attributes\GridVisibleAttribute.vb" />
<Compile Include="Base\TableControlsProcessor.vb" /> <Compile Include="Base\TableControlsProcessor.vb" />
<Compile Include="Controls\ChannelTabsChooserForm.Designer.vb">
<DependentUpon>ChannelTabsChooserForm.vb</DependentUpon>
</Compile>
<Compile Include="Controls\ChannelTabsChooserForm.vb">
<SubType>Form</SubType>
</Compile>
<Compile Include="Controls\PlayListParserForm.Designer.vb"> <Compile Include="Controls\PlayListParserForm.Designer.vb">
<DependentUpon>PlayListParserForm.vb</DependentUpon> <DependentUpon>PlayListParserForm.vb</DependentUpon>
</Compile> </Compile>
@@ -208,6 +214,9 @@
<Compile Include="Base\YouTubeSettings.vb" /> <Compile Include="Base\YouTubeSettings.vb" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Controls\ChannelTabsChooserForm.resx">
<DependentUpon>ChannelTabsChooserForm.vb</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Controls\PlayListParserForm.resx"> <EmbeddedResource Include="Controls\PlayListParserForm.resx">
<DependentUpon>PlayListParserForm.vb</DependentUpon> <DependentUpon>PlayListParserForm.vb</DependentUpon>
</EmbeddedResource> </EmbeddedResource>

View File

@@ -20,6 +20,8 @@ Public Class MainFrame
Protected Overrides Sub VideoListForm_Load(sender As Object, e As EventArgs) Protected Overrides Sub VideoListForm_Load(sender As Object, e As EventArgs)
MyBase.VideoListForm_Load(sender, e) MyBase.VideoListForm_Load(sender, e)
TRAY_ICON.Visible = MyYouTubeSettings.CloseToTray TRAY_ICON.Visible = MyYouTubeSettings.CloseToTray
CheckNewReleaseFolder()
CheckVersionImpl(False)
End Sub End Sub
Private _CloseInvoked As Boolean = False Private _CloseInvoked As Boolean = False
Private _IgnoreTrayOptions As Boolean = False Private _IgnoreTrayOptions As Boolean = False

View File

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

View File

@@ -18,8 +18,30 @@ Namespace API.Base
Friend ReadOnly TsFilesRegEx As RParams = RParams.DM(".+?\.ts[^\r\n]*", 0, RegexReturn.List) Friend ReadOnly TsFilesRegEx As RParams = RParams.DM(".+?\.ts[^\r\n]*", 0, RegexReturn.List)
End Module End Module
End Namespace End Namespace
Friend Structure M3U8URL
Friend URL As String
Friend Extension As String
Friend Sub New(ByVal _URL As String, Optional ByVal _Extension As String = Nothing)
URL = _URL
Extension = _Extension
End Sub
Public Shared Widening Operator CType(ByVal URL As String) As M3U8URL
Return New M3U8URL(URL)
End Operator
Public Overrides Function Equals(ByVal Obj As Object) As Boolean
If Not IsNothing(Obj) Then
If TypeOf Obj Is M3U8URL Then
Return CType(Obj, M3U8URL).URL = URL
Else
Return CStr(Obj) = URL
End If
End If
Return False
End Function
End Structure
Friend NotInheritable Class M3U8Base Friend NotInheritable Class M3U8Base
Friend Const TempCacheFolderName As String = "tmpCache" Friend Const TempCacheFolderName As String = "tmpCache"
Friend Const TempFilePrefix As String = "ConPart_"
Private Sub New() Private Sub New()
End Sub End Sub
Friend Shared Function CreateUrl(ByVal Appender As String, ByVal File As String) As String Friend Shared Function CreateUrl(ByVal Appender As String, ByVal File As String) As String
@@ -32,9 +54,17 @@ Namespace API.Base
Return $"{Appender.StringTrimEnd("/")}/{File}" Return $"{Appender.StringTrimEnd("/")}/{File}"
End If End If
End Function End Function
Friend Shared Function Download(ByVal URLs As List(Of String), ByVal DestinationFile As SFile, Optional ByVal Responser As Responser = Nothing, Friend Overloads Shared Function Download(ByVal URLs As List(Of String), ByVal DestinationFile As SFile, Optional ByVal Responser As Responser = Nothing,
Optional ByVal Token As CancellationToken = Nothing, Optional ByVal Progress As MyProgress = Nothing, Optional ByVal Token As CancellationToken = Nothing, Optional ByVal Progress As MyProgress = Nothing,
Optional ByVal UsePreProgress As Boolean = True, Optional ByVal ExistingCache As CacheKeeper = Nothing) As SFile Optional ByVal UsePreProgress As Boolean = True, Optional ByVal ExistingCache As CacheKeeper = Nothing,
Optional ByVal OnlyDownload As Boolean = False) As SFile
Return Download(URLs.ListCast(Of M3U8URL), DestinationFile, Responser, Token, Progress, UsePreProgress, ExistingCache, OnlyDownload)
End Function
Friend Overloads Shared Function Download(ByVal URLs As List(Of M3U8URL), ByVal DestinationFile As SFile, Optional ByVal Responser As Responser = Nothing,
Optional ByVal Token As CancellationToken = Nothing, Optional ByVal Progress As MyProgress = Nothing,
Optional ByVal UsePreProgress As Boolean = True, Optional ByVal ExistingCache As CacheKeeper = Nothing,
Optional ByVal OnlyDownload As Boolean = False) As SFile
Const defaultExtension$ = "ts"
Dim Cache As CacheKeeper = Nothing Dim Cache As CacheKeeper = Nothing
Using tmpPr As New PreProgress(Progress) Using tmpPr As New PreProgress(Progress)
Try Try
@@ -59,10 +89,13 @@ Namespace API.Base
End If End If
End If End If
Dim p As SFileNumbers = SFileNumbers.Default(ConcatFile.Name) Dim p As SFileNumbers = SFileNumbers.Default(ConcatFile.Name)
Dim pNum As ANumbers = SFileNumbers.NumberProviderDefault
p.NumberProvider = pNum
DirectCast(p.NumberProvider, ANumbers).GroupSize = {URLs.Count.ToString.Length, 3}.Max
ConcatFile = SFile.IndexReindex(ConcatFile,,, p, EDP.ReturnValue) ConcatFile = SFile.IndexReindex(ConcatFile,,, p, EDP.ReturnValue)
Dim i% Dim i%
Dim dFile As SFile = cache2.RootDirectory Dim dFile As SFile = cache2.RootDirectory
dFile.Extension = "ts" dFile.Extension = defaultExtension
Using w As New DownloadObjects.WebClient2(Responser) Using w As New DownloadObjects.WebClient2(Responser)
For i = 0 To URLs.Count - 1 For i = 0 To URLs.Count - 1
If progressExists Then If progressExists Then
@@ -73,12 +106,14 @@ Namespace API.Base
End If End If
End If End If
Token.ThrowIfCancellationRequested() Token.ThrowIfCancellationRequested()
dFile.Name = $"ConPart_{i}" dFile.Name = $"{TempFilePrefix}{i.NumToString(pNum)}"
w.DownloadFile(URLs(i), dFile) dFile.Extension = URLs(i).Extension.IfNullOrEmpty(defaultExtension)
w.DownloadFile(URLs(i).URL, dFile)
cache2.AddFile(dFile, True) cache2.AddFile(dFile, True)
Next Next
End Using End Using
DestinationFile = FFMPEG.ConcatenateFiles(cache2, Settings.FfmpegFile.File, ConcatFile, Settings.CMDEncoding, p, EDP.ThrowException) If Not OnlyDownload Then _
DestinationFile = FFMPEG.ConcatenateFiles(cache2, Settings.FfmpegFile.File, ConcatFile, Settings.CMDEncoding, p, EDP.ThrowException)
Return DestinationFile Return DestinationFile
End If End If
End If End If

View File

@@ -47,6 +47,7 @@ Namespace API.Base
Progress.InformationTemporary = $"{HOST.Name} ({c - s}/{c}) Images: {_TotalImages}; Videos: {_TotalVideos}" Progress.InformationTemporary = $"{HOST.Name} ({c - s}/{c}) Images: {_TotalImages}; Videos: {_TotalVideos}"
End If End If
End If End If
If _FeedDataExists Then Downloader.Files.Sort()
End Sub End Sub
Private Overloads Sub Download(ByVal Host As SettingsHost, ByVal Number As Integer, ByVal Count As Integer, Private Overloads Sub Download(ByVal Host As SettingsHost, ByVal Number As Integer, ByVal Count As Integer,
ByVal Token As CancellationToken, ByVal Multiple As Boolean) ByVal Token As CancellationToken, ByVal Multiple As Boolean)

View File

@@ -136,7 +136,9 @@ Namespace API.Twitter
Private Function GetContainerSubnodes() As List(Of String()) Private Function GetContainerSubnodes() As List(Of String())
Return New List(Of String()) From { Return New List(Of String()) From {
{{"content", "itemContent", "tweet_results", "result", "legacy"}}, {{"content", "itemContent", "tweet_results", "result", "legacy"}},
{{"content", "itemContent", "tweet_results", "result", "tweet", "legacy"}} {{"content", "itemContent", "tweet_results", "result", "tweet", "legacy"}},
{{"item", "itemContent", "tweet_results", "result", "legacy"}},
{{"item", "itemContent", "tweet_results", "result", "tweet", "legacy"}}
} }
End Function End Function
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
@@ -160,7 +162,7 @@ Namespace API.Twitter
Const entry$ = "entry" Const entry$ = "entry"
Dim PostID$ = String.Empty Dim PostID$ = String.Empty
Dim PostDate$, tmpUserId$ Dim PostDate$, tmpUserId$
Dim i% Dim i%, nodeIndx%
Dim dirIndx% = -1 Dim dirIndx% = -1
Dim nodes As List(Of String()) = GetContainerSubnodes() Dim nodes As List(Of String()) = GetContainerSubnodes()
Dim node$() Dim node$()
@@ -168,10 +170,12 @@ Namespace API.Twitter
Dim pinNode As Predicate(Of EContainer) = Function(ee) ee.Value("type").StringToLower = "timelinepinentry" Dim pinNode As Predicate(Of EContainer) = Function(ee) ee.Value("type").StringToLower = "timelinepinentry"
Dim entriesNode As Predicate(Of EContainer) = Function(ee) ee.Name = "entries" Or ee.Name = entry Dim entriesNode As Predicate(Of EContainer) = Function(ee) ee.Name = "entries" Or ee.Name = entry
Dim sourceIdPredicate As Predicate(Of EContainer) = Function(ee) ee.Name = "source_user_id_str" Or ee.Name = "source_user_id" Dim sourceIdPredicate As Predicate(Of EContainer) = Function(ee) ee.Name = "source_user_id_str" Or ee.Name = "source_user_id"
Dim moduleItemsPredicate As Predicate(Of EContainer) = Function(ee) ee.Name.StringToLower = "moduleitems"
Dim newTwitterNodes() As Object = {0, "content", "items"}
Dim p As Predicate(Of EContainer) Dim p As Predicate(Of EContainer)
Dim pIndx% Dim pIndx%
Dim isOneNode As Boolean, isPins As Boolean, ExistsDetected As Boolean, userInfoParsed As Boolean = False Dim isOneNode As Boolean, isPins As Boolean, ExistsDetected As Boolean, userInfoParsed As Boolean = False
Dim j As EContainer, rootNode As EContainer, tmpNode As EContainer, nn As EContainer = Nothing Dim j As EContainer, rootNode As EContainer, optionalNode As EContainer, workingNode As EContainer, tmpNode As EContainer, nn As EContainer = Nothing
Dim __parseContainer As Func(Of EContainer, Boolean) = Dim __parseContainer As Func(Of EContainer, Boolean) =
Function(ByVal ee As EContainer) As Boolean Function(ByVal ee As EContainer) As Boolean
@@ -286,18 +290,21 @@ Namespace API.Twitter
End If End If
Else Else
For pIndx = 0 To IIf(dirIndx < 2, 1, 0) For pIndx = 0 To IIf(dirIndx < 2, 1, 0)
optionalNode = Nothing
Select Case dirIndx Select Case dirIndx
Case 0, 1 Case 0, 1
rootNode = j({"data", "user", "result", "timeline_v2", "timeline", "instructions"}) rootNode = j({"data", "user", "result", "timeline_v2", "timeline", "instructions"})
If rootNode.ListExists Then If rootNode.ListExists Then
p = If(pIndx = 0, pinNode, timelineNode) p = If(pIndx = 0, pinNode, timelineNode)
isPins = pIndx = 0 isPins = pIndx = 0
optionalNode = rootNode
rootNode = rootNode.Find(p, False) rootNode = rootNode.Find(p, False)
If rootNode.ListExists Then rootNode = rootNode.Find(entriesNode, False) If rootNode.ListExists Then rootNode = rootNode.Find(entriesNode, False)
End If End If
Case Else Case Else
isPins = False isPins = False
rootNode = j({"globalObjects", "tweets"}) rootNode = j({"globalObjects", "tweets"})
optionalNode = rootNode
End Select End Select
If rootNode.ListExists Then If rootNode.ListExists Then
@@ -308,9 +315,23 @@ Namespace API.Twitter
ProgressPre.Perform() ProgressPre.Perform()
If Not __parseContainer(.Self) Then Exit For If Not __parseContainer(.Self) Then Exit For
Else Else
For Each tmpNode In .Self For nodeIndx = 0 To 1
ProgressPre.Perform() If nodeIndx = 0 Then
If Not __parseContainer(tmpNode) Then Exit For workingNode = rootNode
Else
workingNode = optionalNode
If workingNode.ListExists Then workingNode = workingNode.Find(moduleItemsPredicate, True)
End If
If workingNode.ListExists Then
With workingNode
For Each tmpNode In If(If(.ItemF(newTwitterNodes)?.Count, 0) > 0,
.ItemF(newTwitterNodes),
.Self)
ProgressPre.Perform()
If Not __parseContainer(tmpNode) Then Exit For
Next
End With
End If
Next Next
End If End If
End With End With

View File

@@ -14,5 +14,6 @@ Namespace API.Xhamster
Friend ReadOnly HtmlScript As RParams = RParams.DMS("\<script id='initials-script'\>window.initials=(\{.+?\});\</script\>", 1, EDP.ReturnValue, Friend ReadOnly HtmlScript As RParams = RParams.DMS("\<script id='initials-script'\>window.initials=(\{.+?\});\</script\>", 1, EDP.ReturnValue,
CType(Function(Input$) Input.StringTrim, Func(Of String, String))) CType(Function(Input$) Input.StringTrim, Func(Of String, String)))
Friend ReadOnly FirstM3U8FileRegEx As RParams = RParams.DM("RESOLUTION=\d+x(\d+).*?[\r\n]+?([^#]*?\.m3u8.*)", 0, RegexReturn.List) Friend ReadOnly FirstM3U8FileRegEx As RParams = RParams.DM("RESOLUTION=\d+x(\d+).*?[\r\n]+?([^#]*?\.m3u8.*)", 0, RegexReturn.List)
Friend ReadOnly SecondM3U8FileRegEx As RParams = RParams.DM("(#EXT-X-MAP.URI=""([^""]+((?<=\.)([^\?\.]{2,5})(?=(\?|\Z|"")))(.+|))""|#EXTINF[^\r\n]*[\r\n]+(([^\r\n]+((?<=\.)([^\?\.\r\n]{2,5})(?=(\?[^\r\n]+|[\r\n]+)))([^\r\n]+|))([\r\n]+|\Z)))", 0, RegexReturn.List)
End Module End Module
End Namespace End Namespace

View File

@@ -10,6 +10,7 @@ Imports System.Threading
Imports SCrawler.API.Base Imports SCrawler.API.Base
Imports SCrawler.API.Base.M3U8Declarations Imports SCrawler.API.Base.M3U8Declarations
Imports PersonalUtilities.Forms.Toolbars Imports PersonalUtilities.Forms.Toolbars
Imports PersonalUtilities.Tools
Imports PersonalUtilities.Tools.Web.Clients Imports PersonalUtilities.Tools.Web.Clients
Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Functions.RegularExpressions
Namespace API.Xhamster Namespace API.Xhamster
@@ -40,18 +41,40 @@ Namespace API.Xhamster
Next Next
Return String.Empty Return String.Empty
End Function End Function
Private Shared Function ParseSecondM3U8(ByVal URL As String, ByVal Responser As Responser, ByVal Appender As String) As List(Of String) Private Shared Function ParseSecondM3U8(ByVal URL As String, ByVal Responser As Responser, ByVal Appender As String) As List(Of M3U8URL)
Dim r$ Dim r$
Dim l As List(Of String) Dim l As List(Of String)
Dim ll As List(Of M3U8URL) = Nothing
Dim u As M3U8URL
Dim rmsF As Func(Of RegexMatchStruct, M3U8URL) =
Function(ByVal rms As RegexMatchStruct) As M3U8URL
With rms
If .Arr(0).IsEmptyString Then
Return New M3U8URL(.Arr(3).IfNullOrEmpty(.Arr(4)), .Arr(5).IfNullOrEmpty(.Arr(6)))
Else
Return New M3U8URL(.Arr(0), .Arr(1).IfNullOrEmpty(.Arr(2)))
End If
End With
End Function
For i% = 0 To 1 For i% = 0 To 1
Try Try
Responser.UseGZipStream = i Responser.UseGZipStream = i
r = Responser.GetResponse(URL) r = Responser.GetResponse(URL)
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
l = RegexReplace(r, TsFilesRegEx) l = RegexReplace(r, TsFilesRegEx)
If l.ListExists Then If Not l.ListExists Then
For indx% = 0 To l.Count - 1 : l(indx) = M3U8Base.CreateUrl(Appender, l(indx)) : Next With RegexFields(Of RegexMatchStruct)(r, {SecondM3U8FileRegEx}, {2, 4, 3, 8, 7, 10, 9}, EDP.ReturnValue)
Return l If .ListExists Then ll = .Select(rmsF).ListWithRemove(Function(v) v.URL.IsEmptyString)
End With
End If
If Not ll.ListExists And l.ListExists Then ll = l.ListCast(Of M3U8URL)
If ll.ListExists Then
For indx% = 0 To ll.Count - 1
u = ll(indx)
u.URL = M3U8Base.CreateUrl(Appender, u.URL)
ll(indx) = u
Next
Return ll
End If End If
End If End If
Catch Catch
@@ -59,14 +82,14 @@ Namespace API.Xhamster
Next Next
Return Nothing Return Nothing
End Function End Function
Private Shared Function ObtainUrls(ByVal URL As String, ByVal Responser As Responser, ByVal UHD As Boolean) As List(Of String) Private Shared Function ObtainUrls(ByVal URL As String, ByVal Responser As Responser, ByVal UHD As Boolean) As List(Of M3U8URL)
Try Try
Dim file$ = ParseFirstM3U8(URL, Responser, UHD) Dim file$ = ParseFirstM3U8(URL, Responser, UHD)
If Not file.IsEmptyString Then If Not file.IsEmptyString Then
Responser.UseGZipStream = False Responser.UseGZipStream = False
Dim appender$ = URL.Replace(URL.Split("/").LastOrDefault, String.Empty) Dim appender$ = URL.Replace(URL.Split("/").LastOrDefault, String.Empty)
URL = M3U8Base.CreateUrl(appender, file) URL = M3U8Base.CreateUrl(appender, file)
Dim l As List(Of String) = ParseSecondM3U8(URL, Responser, appender) Dim l As List(Of M3U8URL) = ParseSecondM3U8(URL, Responser, appender)
If l.ListExists Then Return l If l.ListExists Then Return l
End If End If
Return Nothing Return Nothing
@@ -75,8 +98,57 @@ Namespace API.Xhamster
End Try End Try
End Function End Function
Friend Shared Function Download(ByVal Media As UserMedia, ByVal Responser As Responser, ByVal UHD As Boolean, Friend Shared Function Download(ByVal Media As UserMedia, ByVal Responser As Responser, ByVal UHD As Boolean,
ByVal Token As CancellationToken, ByVal Progress As MyProgress, ByVal UsePreProgress As Boolean) As SFile ByVal Token As CancellationToken, ByVal Progress As MyProgress, ByVal UsePreProgress As Boolean,
Return M3U8Base.Download(ObtainUrls(Media.URL, Responser, UHD), Media.File, Responser, Token, Progress, UsePreProgress) ByVal ReencodeVideos As Boolean) As SFile
'Return M3U8Base.Download(ObtainUrls(Media.URL, Responser, UHD), Media.File, Responser, Token, Progress, UsePreProgress)
Dim Cache As CacheKeeper = Nothing
Try
Dim urls As List(Of M3U8URL) = ObtainUrls(Media.URL, Responser, UHD)
If urls.ListExists Then
Cache = New CacheKeeper($"{Media.File.PathWithSeparator}_{M3U8Base.TempCacheFolderName}\") With {.DisposeSuspended = True}
Cache.CacheDeleteError = CacheDeletionError(Cache)
Dim isNewWay As Boolean = Not urls(0).Extension.IsEmptyString AndAlso urls(0).Extension = "mp4" AndAlso urls.Count > 1 AndAlso
urls.Exists(Function(u) Not u.Extension = urls(0).Extension)
Dim f As SFile = M3U8Base.Download(urls, Media.File, Responser, Token, Progress, UsePreProgress, Cache, isNewWay)
If isNewWay Then
f = Media.File
With DirectCast(Cache.CurrentInstance, CacheKeeper)
If .Count > 0 Then
Using batch As New BatchExecutor With {.Encoding = Settings.CMDEncoding}
batch.ChangeDirectory(.Self.RootDirectory)
Using bat As New TextSaver($"{ .RootDirectory.PathWithSeparator}Merge.bat")
Dim tmpFile As SFile
Dim tmpFileStr$
If ReencodeVideos Then
tmpFile = $"{ .Self.RootDirectory.PathWithSeparator}NewVideo.{urls(1).Extension}"
tmpFileStr = tmpFile.File
.AddFile(tmpFile)
Else
tmpFile = Media.File
tmpFileStr = $"""{tmpFile}"""
End If
bat.AppendLine($"copy /b { .First.File} + {M3U8Base.TempFilePrefix}*.{urls(1).Extension} {tmpFileStr}")
If ReencodeVideos Then bat.AppendLine($"""{Settings.FfmpegFile}"" -i ""{tmpFile}"" ""{Media.File}""")
bat.Save()
.AddFile(bat.File)
batch.Execute($"""{bat.File}""")
If f.Exists Then Return f
End Using
End Using
End If
End With
ElseIf f.Exists Then
Return f
End If
End If
Return Nothing
Finally
Cache.DisposeIfReady(False)
End Try
End Function End Function
End Class End Class
End Namespace End Namespace

View File

@@ -28,7 +28,11 @@ Namespace API.Xhamster
End Get End Get
End Property End Property
<PropertyOption(ControlText:="Download UHD", ControlToolTip:="Download UHD (4K) content"), PXML, PClonable> <PropertyOption(ControlText:="Download UHD", ControlToolTip:="Download UHD (4K) content"), PXML, PClonable>
Friend Property DownloadUHD As PropertyValue Friend ReadOnly Property DownloadUHD As PropertyValue
<PropertyOption(ControlText:="Re-encode downloaded videos if necessary",
ControlToolTip:="If enabled and the video is downloaded in a non-native format, the video will be re-encoded." & vbCr &
"Attention! Enabling this setting results in maximum CPU usage."), PXML, PClonable>
Friend ReadOnly Property ReencodeVideos As PropertyValue
#End Region #End Region
#Region "Initializer" #Region "Initializer"
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean) Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
@@ -38,6 +42,7 @@ Namespace API.Xhamster
SiteDomains = New PropertyValue(Domains.DomainsDefault, GetType(String)) SiteDomains = New PropertyValue(Domains.DomainsDefault, GetType(String))
Domains.DestinationProp = SiteDomains Domains.DestinationProp = SiteDomains
DownloadUHD = New PropertyValue(False) DownloadUHD = New PropertyValue(False)
ReencodeVideos = New PropertyValue(False)
_SubscriptionsAllowed = True _SubscriptionsAllowed = True
UrlPatternUser = "https://xhamster.com/{0}/{1}" UrlPatternUser = "https://xhamster.com/{0}/{1}"

View File

@@ -537,7 +537,7 @@ Namespace API.Xhamster
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) 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)}) Dim url$ = node.GetNode({New NodeParams("url", True, True, True, True, 2)}).XmlIfNothingValue
If Not url.IsEmptyString Then m.URL = url : m.Type = UTypes.m3u8 : Return True If Not url.IsEmptyString Then m.URL = url : m.Type = UTypes.m3u8 : Return True
End If End If
Return False Return False
@@ -555,7 +555,7 @@ Namespace API.Xhamster
End Sub End Sub
Protected Overrides Function DownloadM3U8(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile, ByVal Token As CancellationToken) As SFile Protected Overrides Function DownloadM3U8(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile, ByVal Token As CancellationToken) As SFile
Media.File = DestinationFile Media.File = DestinationFile
Return M3U8.Download(Media, Responser, MySettings.DownloadUHD.Value, Token, Progress, Not IsSingleObjectDownload) Return M3U8.Download(Media, Responser, MySettings.DownloadUHD.Value, Token, Progress, Not IsSingleObjectDownload, MySettings.ReencodeVideos.Value)
End Function End Function
#End Region #End Region
#Region "Create media" #Region "Create media"

View File

@@ -175,7 +175,7 @@ Namespace API.YouTube
maxDate = Nothing maxDate = Nothing
LastDownloadDatePlaylist = nDate(LastDownloadDatePlaylist) LastDownloadDatePlaylist = nDate(LastDownloadDatePlaylist)
url = $"https://{IIf(IsMusic, "music", "www")}.youtube.com/playlist?list={ID}" url = $"https://{IIf(IsMusic, "music", "www")}.youtube.com/playlist?list={ID}"
container = YouTubeFunctions.Parse(url, YTUseCookies, Token, pr, True, False,, LastDownloadDatePlaylist) container = YouTubeFunctions.Parse(url, YTUseCookies, Token, pr,, LastDownloadDatePlaylist,, True)
applySpecFolder.Invoke(String.Empty, False) applySpecFolder.Invoke(String.Empty, False)
If fillList.Invoke(LastDownloadDatePlaylist) Then LastDownloadDatePlaylist = If(maxDate, Now) If fillList.Invoke(LastDownloadDatePlaylist) Then LastDownloadDatePlaylist = If(maxDate, Now)
ElseIf YTMediaType = YouTubeMediaType.Channel Then ElseIf YTMediaType = YouTubeMediaType.Channel Then
@@ -183,7 +183,7 @@ Namespace API.YouTube
maxDate = Nothing maxDate = Nothing
LastDownloadDateVideos = nDate(LastDownloadDateVideos) LastDownloadDateVideos = nDate(LastDownloadDateVideos)
url = $"https://{IIf(IsMusic, "music", "www")}.youtube.com/{IIf(IsMusic Or IsChannelUser, $"{YouTubeFunctions.UserChannelOption}/", "@")}{ID}" url = $"https://{IIf(IsMusic, "music", "www")}.youtube.com/{IIf(IsMusic Or IsChannelUser, $"{YouTubeFunctions.UserChannelOption}/", "@")}{ID}"
container = YouTubeFunctions.Parse(url, YTUseCookies, Token, pr, True, False,, LastDownloadDateVideos) container = YouTubeFunctions.Parse(url, YTUseCookies, Token, pr,, LastDownloadDateVideos,, True)
applySpecFolder.Invoke(IIf(IsMusic, String.Empty, "Videos"), False) applySpecFolder.Invoke(IIf(IsMusic, String.Empty, "Videos"), False)
If fillList.Invoke(LastDownloadDateVideos) Then LastDownloadDateVideos = If(maxDate, Now) If fillList.Invoke(LastDownloadDateVideos) Then LastDownloadDateVideos = If(maxDate, Now)
End If End If
@@ -191,7 +191,7 @@ Namespace API.YouTube
maxDate = Nothing maxDate = Nothing
LastDownloadDateShorts = nDate(LastDownloadDateShorts) LastDownloadDateShorts = nDate(LastDownloadDateShorts)
url = $"https://www.youtube.com/{IIf(IsChannelUser, $"{YouTubeFunctions.UserChannelOption}/", "@")}{ID}/shorts" url = $"https://www.youtube.com/{IIf(IsChannelUser, $"{YouTubeFunctions.UserChannelOption}/", "@")}{ID}/shorts"
container = YouTubeFunctions.Parse(url, YTUseCookies, Token, pr, True, False,, LastDownloadDateShorts) container = YouTubeFunctions.Parse(url, YTUseCookies, Token, pr,, LastDownloadDateShorts,, True)
applySpecFolder.Invoke("Shorts", False) applySpecFolder.Invoke("Shorts", False)
If fillList.Invoke(LastDownloadDateShorts) Then LastDownloadDateShorts = If(maxDate, Now) If fillList.Invoke(LastDownloadDateShorts) Then LastDownloadDateShorts = If(maxDate, Now)
End If End If
@@ -199,7 +199,7 @@ Namespace API.YouTube
maxDate = Nothing maxDate = Nothing
LastDownloadDatePlaylist = nDate(LastDownloadDatePlaylist) LastDownloadDatePlaylist = nDate(LastDownloadDatePlaylist)
url = $"https://www.youtube.com/{IIf(IsChannelUser, $"{YouTubeFunctions.UserChannelOption}/", "@")}{ID}/playlists" url = $"https://www.youtube.com/{IIf(IsChannelUser, $"{YouTubeFunctions.UserChannelOption}/", "@")}{ID}/playlists"
container = YouTubeFunctions.Parse(url, YTUseCookies, Token, pr, True, False,, LastDownloadDatePlaylist) container = YouTubeFunctions.Parse(url, YTUseCookies, Token, pr,, LastDownloadDatePlaylist,, True)
applySpecFolder.Invoke("Playlists", True) applySpecFolder.Invoke("Playlists", True)
If fillList.Invoke(LastDownloadDatePlaylist) Then LastDownloadDatePlaylist = If(maxDate, Now) If fillList.Invoke(LastDownloadDatePlaylist) Then LastDownloadDatePlaylist = If(maxDate, Now)
End If End If

View File

@@ -25,8 +25,6 @@ Namespace DownloadObjects.STDownloader
AppMode = False AppMode = False
Icon = My.Resources.ArrowDownIcon_Blue_24 Icon = My.Resources.ArrowDownIcon_Blue_24
BTT_ADD_PLS_ARR.Text = $"YouTube: {BTT_ADD_PLS_ARR.Text}" BTT_ADD_PLS_ARR.Text = $"YouTube: {BTT_ADD_PLS_ARR.Text}"
BTT_ADD_NO_SHORTS.Text = $"YouTube: {BTT_ADD_NO_SHORTS.Text}"
BTT_ADD_SHORTS_ONLY.Text = $"YouTube: {BTT_ADD_SHORTS_ONLY.Text}"
BTT_ADD_URLS_ARR = New ToolStripMenuItemKeyClick("Add an array of URLs", PersonalUtilities.My.Resources.PlusPic_Green_24) With {.Tag = UrlsArrTag} BTT_ADD_URLS_ARR = New ToolStripMenuItemKeyClick("Add an array of URLs", PersonalUtilities.My.Resources.PlusPic_Green_24) With {.Tag = UrlsArrTag}
BTT_ADD_URLS_EXTERNAL = New ToolStripMenuItemKeyClick With {.Tag = TAG_EXTERNAL} BTT_ADD_URLS_EXTERNAL = New ToolStripMenuItemKeyClick With {.Tag = TAG_EXTERNAL}
MENU_ADD.DropDownItems.Insert(1, BTT_ADD_URLS_ARR) MENU_ADD.DropDownItems.Insert(1, BTT_ADD_URLS_ARR)

View File

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

View File

@@ -70,6 +70,9 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
Public Shared Widening Operator CType(ByVal f As ProgramFile) As SFile Public Shared Widening Operator CType(ByVal f As ProgramFile) As SFile
Return f.File Return f.File
End Operator End Operator
Public Shared Narrowing Operator CType(ByVal f As ProgramFile) As String
Return f.ToString
End Operator
Public Overrides Function ToString() As String Public Overrides Function ToString() As String
Return File.ToString Return File.ToString
End Function End Function