2025.2.25.0

PluginProvider
IPluginContentProvider: add 'NameTrue' property

YT
YouTubeSettings: remove the 'CreateDescriptionFiles_AddUploadDate' property
PlayListParserForm: add 'RDAMP' as default value when initializing form
YouTubeMediaContainerBase: fix line breaks

SCrawler
API.Base: add 'EditorExchangeOptionsBase' class
API.Base.GDL: move functions to Pinterest.UserData
API.Base.IUserData: add 'NameTrue' property
API.Base.SiteSettingsBase: update the 'GetUserUrl' function to use the 'NameTrue' property; update 'UserOptions' function
API.Base.UserDataBase: add 'NameTrue' property; add 'SimpleDownloadAvatar' function to get rid of the  same functions of other classes; Update 'UserDescriptionUpdate' function
API.Base.InternalSettingsForm: calculate max offset

ADD API.Bluesky

API.Facebook: add 'Reels' downloads; fix video downloading
API.Instagram: add inheritance 'EditorExchangeOptionsBase'; remove 'GetUserUrl' function from 'SiteSettings'; update 'UserData' class to new environment; add saving 'heic' file along with 'jpg'
API.LPSG.UserData: simplify 403 error
API.Mastodon: update classes to new environment
API.OnlyFans: add 'AppTokenDefault'; disable cookies update; update 'UserData' class to new environment
API.Pinterest: add sub-boards downloading; update download functions
API.PornHub: fix photo & video downloading; remove 'ModelHub' support
API.Reddit: fix token update; update 'UserData' class to new environment
API.ThisVid: update 'UserData' class to new environment
API.ThreadsNet: fix data download; update classes to new environment; fix 'UserID' extraction; add the ability to manually change the UserName
API.TikTok: update classes to new environment
API.Twitter: update classes to new environment; add sleep timers to fully download large profiles; add 'CookiesUpdate' hidden property
API.Xhamster: update classes to new environment
API.XVIDEOS: update classes to new environment

Feed: add the ability to invert selection; open post URL when double-clicking on subscription image
FeedSpecialCollection: update 'FeedsComparer'
GlobalSettingsForm: remove 'UserAgent' from the 'Basis' tab
UserDataHost: update class to new environment
SettingsCLS: set the 'UserSiteNameAsFriendly' property to 'True' by default; disable 'DownDetector'; add 'UsersListProtected' property
This commit is contained in:
Andy
2025-02-25 19:47:33 +03:00
parent 4d74f5204b
commit 2f838929cc
81 changed files with 2030 additions and 888 deletions

View File

@@ -1,3 +1,35 @@
# 2025.2.25.0
*2025-02-25*
- Added
- Sites:
- **Bluesky**
- Facebook: **`Reels` downloads**
- OnlyFans: default value for `App-Token`
- Pinterest: **sub-boards downloading**
- Threads: ability to manually change `UserName`
- Twitter:
- new icon support
- **sleep timers to fully download large profiles**
- Feed:
- ability to invert selection
- open post URL when double-clicking on subscription image
- Minor improvements
- Updated
- yt-dlp up to version **2025.02.19**
- gallery-dl up to version **1.28.5**
- PluginProvider
- `IPluginContentProvider`: added property `NameTrue`
- Fixed
- Sites:
- Facebook: videos are not downloading
- LPSG: simplified 403 error
- PornHub: photos & videos are not downloading
- Reddit: **token does not update automatically**
- Threads: **data is not downloading**
- Minor bugs
# 2025.1.12.0 # 2025.1.12.0
*2025-01-12* *2025-01-12*

1
FAQ.md
View File

@@ -63,6 +63,7 @@ I strongly recommend you to **regularly** create backup copies of the settings f
- Reddit: don't use credentials at all or configure [OAuth](https://github.com/AAndyProgram/SCrawler/wiki/Settings#how-to-get-reddit-credentials). **Reddit profiles can be downloaded without any credentials at all. Subreddits require OAuth! If nothing downloads, use OAuth!** Don't use OAuth token to download saved posts (use cookies only). - Reddit: don't use credentials at all or configure [OAuth](https://github.com/AAndyProgram/SCrawler/wiki/Settings#how-to-get-reddit-credentials). **Reddit profiles can be downloaded without any credentials at all. Subreddits require OAuth! If nothing downloads, use OAuth!** Don't use OAuth token to download saved posts (use cookies only).
- **META** (**Instagram**, Threads, Facebook): you need **cookies** and fill in **all fields** - **META** (**Instagram**, Threads, Facebook): you need **cookies** and fill in **all fields**
- **Instagram [TIPS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#instagram-tips)**
- **Instagram saved posts**: I don't consider questions like "I have 10k saved posts and only 1000 were downloaded". Download posts, remove them from saved posts, delete the `Saved posts` **settings folder**, repeat. - **Instagram saved posts**: I don't consider questions like "I have 10k saved posts and only 1000 were downloaded". Download posts, remove them from saved posts, delete the `Saved posts` **settings folder**, repeat.
- TikTok: works via yt-dlp. If something doesn't download, we need to wait until yt-dlp fixes it. TikTok doesn't require cookies to download. - TikTok: works via yt-dlp. If something doesn't download, we need to wait until yt-dlp fixes it. TikTok doesn't require cookies to download.
- Porn sites: **COOKIES**! - Porn sites: **COOKIES**!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -38,6 +38,7 @@ A program to download photo and video from [any site](#supported-sites) (e.g. Yo
- Reddit images, galleries of images, videos, saved posts; - Reddit images, galleries of images, videos, saved posts;
- Redgifs images and videos (https://www.redgifs.com/); - Redgifs images and videos (https://www.redgifs.com/);
- Twitter images and videos, saved (bookmarked) posts, likes, communities; - Twitter images and videos, saved (bookmarked) posts, likes, communities;
- Bluesky images and videos;
- OnlyFans images and videos, saved (bookmarked) posts, stories; - OnlyFans images and videos, saved (bookmarked) posts, stories;
- JustForFans images and videos, saved (bookmarked) posts; - JustForFans images and videos, saved (bookmarked) posts;
- Mastodon images and videos, saved (bookmarked) posts; - Mastodon images and videos, saved (bookmarked) posts;
@@ -78,6 +79,7 @@ A program to download photo and video from [any site](#supported-sites) (e.g. Yo
- **YouTube Music** - **YouTube Music**
- **Reddit** - **Reddit**
- **Twitter** - **Twitter**
- **Bluesky**
- **OnlyFans** *(partial support)*[^1] - **OnlyFans** *(partial support)*[^1]
- **Instagram** - **Instagram**
- **Threads** - **Threads**
@@ -131,6 +133,7 @@ First, the program downloads the full profile. After the program downloads only
- **[SITES REQUIREMENTS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements)** - **[SITES REQUIREMENTS](https://github.com/AAndyProgram/SCrawler/wiki/Settings#sites-requirements)**
- [Reddit](https://github.com/AAndyProgram/SCrawler/wiki/Settings#reddit) - [Reddit](https://github.com/AAndyProgram/SCrawler/wiki/Settings#reddit)
- [Twitter](https://github.com/AAndyProgram/SCrawler/wiki/Settings#twitter) - [Twitter](https://github.com/AAndyProgram/SCrawler/wiki/Settings#twitter)
- [Bluesky](https://github.com/AAndyProgram/SCrawler/wiki/Settings#bluesky)
- [OnlyFans](https://github.com/AAndyProgram/SCrawler/wiki/Settings#onlyfans) - [OnlyFans](https://github.com/AAndyProgram/SCrawler/wiki/Settings#onlyfans)
- [Mastodon](https://github.com/AAndyProgram/SCrawler/wiki/Settings#mastodon) - [Mastodon](https://github.com/AAndyProgram/SCrawler/wiki/Settings#mastodon)
- [Instagram](https://github.com/AAndyProgram/SCrawler/wiki/Settings#instagram) - [Instagram](https://github.com/AAndyProgram/SCrawler/wiki/Settings#instagram)
@@ -215,16 +218,4 @@ F5-->[*]
Discord server: https://discord.gg/uFNUXvFFmg Discord server: https://discord.gg/uFNUXvFFmg
<!--
[e-mail](mailto:andyprogram@proton.me): andyprogram@proton.me
Matrix (Element): https://matrix.to/#/@andyprogram:matrix.org
Discord (contact the developer): andyprogram
Discord server: https://discord.gg/uFNUXvFFmg
[Wire](https://account.wire.com/user-profile/?id=93985052-cf2c-4b72-ac75-bbe3231cf544): @andyprogram
-->
[^1]: Partial support means that I don't have personal accounts on paid porn sites because I don't pay for porn. If this site has stopped downloading and you want me to fix it, please be ready to give me access to an account with at least one active subscription. Otherwise, the download from this site will not be fixed. [^1]: Partial support means that I don't have personal accounts on paid porn sites because I don't pay for porn. If this site has stopped downloading and you want me to fix it, please be ready to give me access to an account with at least one active subscription. Otherwise, the download from this site will not be fixed.

View File

@@ -17,6 +17,7 @@ Namespace Plugin
Property Settings As ISiteSettings Property Settings As ISiteSettings
Property AccountName As String Property AccountName As String
Property Name As String Property Name As String
Property NameTrue As String
Property ID As String Property ID As String
Property Options As String Property Options As String
Property ParseUserMediaOnly As Boolean Property ParseUserMediaOnly As Boolean

View File

@@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices
<Assembly: AssemblyDescription("Plugin provider for SCrawler")> <Assembly: AssemblyDescription("Plugin provider for SCrawler")>
<Assembly: AssemblyCompany("AndyProgram")> <Assembly: AssemblyCompany("AndyProgram")>
<Assembly: AssemblyProduct("SCrawler.PluginProvider")> <Assembly: AssemblyProduct("SCrawler.PluginProvider")>
<Assembly: AssemblyCopyright("Copyright © 2024")> <Assembly: AssemblyCopyright("Copyright © 2025")>
<Assembly: AssemblyTrademark("AndyProgram")> <Assembly: AssemblyTrademark("AndyProgram")>
<Assembly: ComVisible(False)> <Assembly: ComVisible(False)>
@@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices
' by using the '*' as shown below: ' by using the '*' as shown below:
' <Assembly: AssemblyVersion("1.0.*")> ' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("2024.5.18.0")> <Assembly: AssemblyVersion("2025.2.25.0")>
<Assembly: AssemblyFileVersion("2024.5.18.0")> <Assembly: AssemblyFileVersion("2025.2.25.0")>
<Assembly: NeutralResourcesLanguage("en")> <Assembly: NeutralResourcesLanguage("en")>

View File

@@ -168,9 +168,6 @@ Namespace API.YouTube.Base
<Browsable(True), GridVisible, XMLVN({"Info"}), Category("Info"), DisplayName("Create description files"), <Browsable(True), GridVisible, XMLVN({"Info"}), Category("Info"), DisplayName("Create description files"),
Description("Create video description files. Default: false.")> Description("Create video description files. Default: false.")>
Public ReadOnly Property CreateDescriptionFiles As XMLValue(Of Boolean) Public ReadOnly Property CreateDescriptionFiles As XMLValue(Of Boolean)
<Browsable(True), GridVisible, XMLVN({"Info"}, True), Category("Info"), DisplayName("Create description files: add upload date"),
Description("Add the upload date to the top of the description file. Default: true.")>
Public ReadOnly Property CreateDescriptionFiles_AddUploadDate As XMLValue(Of Boolean)
<Browsable(True), GridVisible, XMLVN({"Info"}, True), Category("Info"), DisplayName("Create description files: create without description"), <Browsable(True), GridVisible, XMLVN({"Info"}, True), Category("Info"), DisplayName("Create description files: create without description"),
Description("Create a description file with the upload date, even if the description does not exist. Default: true.")> Description("Create a description file with the upload date, even if the description does not exist. Default: true.")>
Public ReadOnly Property CreateDescriptionFiles_CreateWithNoDescription As XMLValue(Of Boolean) Public ReadOnly Property CreateDescriptionFiles_CreateWithNoDescription As XMLValue(Of Boolean)

View File

@@ -121,9 +121,10 @@ Namespace API.YouTube.Controls
Me.TXT_LIMIT.Location = New System.Drawing.Point(3, 3) Me.TXT_LIMIT.Location = New System.Drawing.Point(3, 3)
Me.TXT_LIMIT.Name = "TXT_LIMIT" Me.TXT_LIMIT.Name = "TXT_LIMIT"
Me.TXT_LIMIT.PlaceholderEnabled = True Me.TXT_LIMIT.PlaceholderEnabled = True
Me.TXT_LIMIT.PlaceholderText = "e.g. ABCDE" Me.TXT_LIMIT.PlaceholderText = "e.g. RDAMP"
Me.TXT_LIMIT.Size = New System.Drawing.Size(378, 22) Me.TXT_LIMIT.Size = New System.Drawing.Size(378, 22)
Me.TXT_LIMIT.TabIndex = 2 Me.TXT_LIMIT.TabIndex = 2
Me.TXT_LIMIT.Text = "RDAMP"
' '
'CONTAINER_MAIN 'CONTAINER_MAIN
' '

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("2025.1.12.0")> <Assembly: AssemblyVersion("2025.2.25.0")>
<Assembly: AssemblyFileVersion("2025.1.12.0")> <Assembly: AssemblyFileVersion("2025.2.25.0")>
<Assembly: NeutralResourcesLanguage("en")> <Assembly: NeutralResourcesLanguage("en")>

View File

@@ -1215,12 +1215,12 @@ Namespace API.YouTube.Objects
End If End If
With MyYouTubeSettings With MyYouTubeSettings
If .CreateDescriptionFiles And (Not Description.IsEmptyString Or If .CreateDescriptionFiles And (Not Description.IsEmptyString Or .CreateDescriptionFiles_CreateWithNoDescription) Then
(.CreateDescriptionFiles_CreateWithNoDescription And .CreateDescriptionFiles_AddUploadDate)) Then
Dim fileDesr As SFile = File Dim fileDesr As SFile = File
fileDesr.Extension = "txt" fileDesr.Extension = "txt"
Using fileDesrText As New TextSaver(fileDesr) Using fileDesrText As New TextSaver(fileDesr)
If .CreateDescriptionFiles_AddUploadDate Then fileDesrText.Append($"Uploaded: {DateAdded:yyyy-MM-dd HH:mm:ss}") fileDesrText.Append($"Uploaded: {DateAdded:yyyy-MM-dd HH:mm:ss}")
fileDesrText.AppendLine()
fileDesrText.AppendLine($"URL: {URL}") fileDesrText.AppendLine($"URL: {URL}")
fileDesrText.AppendLine($"Channel name: {AccountName}") fileDesrText.AppendLine($"Channel name: {AccountName}")
fileDesrText.AppendLine($"Channel ID: {UserID}") fileDesrText.AppendLine($"Channel ID: {UserID}")

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("2025.1.12.0")> <Assembly: AssemblyVersion("2025.2.25.0")>
<Assembly: AssemblyFileVersion("2025.1.12.0")> <Assembly: AssemblyFileVersion("2025.2.25.0")>
<Assembly: NeutralResourcesLanguage("en")> <Assembly: NeutralResourcesLanguage("en")>

View File

@@ -0,0 +1,22 @@
' Copyright (C) Andy https://github.com/AAndyProgram
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports SCrawler.Plugin.Attributes
Imports DN = SCrawler.API.Base.DeclaredNames
Namespace API.Base
Friend Class EditorExchangeOptionsBase
Friend Overridable Property SiteKey As String
<PSetting(Address:=SettingAddress.User, Caption:=DN.UserNameChangeCaption, ToolTip:=DN.UserNameChangeToolTip)>
Friend Overridable Property UserName As String = String.Empty
Friend Sub New(ByVal u As UserDataBase)
UserName = u.NameTrue(True)
End Sub
Friend Sub New()
End Sub
End Class
End Namespace

View File

@@ -6,66 +6,7 @@
' '
' This program is distributed in the hope that it will be useful, ' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY ' but WITHOUT ANY WARRANTY
Imports PersonalUtilities.Tools
Imports PersonalUtilities.Functions.RegularExpressions
Namespace API.Base.GDL Namespace API.Base.GDL
Friend Module Declarations
Private Structure GDLURL : Implements IRegExCreator
Private _URL As String
Friend ReadOnly Property URL As String
Get
Return _URL
End Get
End Property
Public Shared Widening Operator CType(ByVal u As String) As GDLURL
Return New GDLURL With {._URL = u}
End Operator
Public Shared Widening Operator CType(ByVal u As GDLURL) As String
Return u.URL
End Operator
Private Function CreateFromArray(ByVal ParamsArray() As String) As Object Implements IRegExCreator.CreateFromArray
If ParamsArray.ListExists(2) Then
Dim u$ = ParamsArray(0).StringTrim.StringTrimEnd("/"), u2$
If Not u.IsEmptyString Then
u2 = ParamsArray(1).StringTrim
If Not u2.IsEmptyString AndAlso u2.StartsWith("GET", StringComparison.OrdinalIgnoreCase) Then
u2 = u2.Remove(0, 3).StringTrim.StringTrimStart("/")
If Not u2.IsEmptyString Then _URL = $"{u}/{u2}"
End If
End If
End If
Return Me
End Function
Public Shared Operator =(ByVal x As GDLURL, ByVal y As GDLURL) As Boolean
Return x.URL = y.URL
End Operator
Public Shared Operator <>(ByVal x As GDLURL, ByVal y As GDLURL) As Boolean
Return Not x.URL = y.URL
End Operator
Public Overrides Function ToString() As String
Return URL
End Function
Public Overrides Function Equals(ByVal Obj As Object) As Boolean
Return URL = CType(Obj, String)
End Function
End Structure
Private ReadOnly Property GdlUrlPattern As RParams = RParams.DM(GDLBatch.UrlLibStart.Replace("[", "\[").Replace("]", "\]") &
"([^""]+?)""(GET [^""]+)""", 0, EDP.ReturnValue)
Friend Function GetUrlsFromGalleryDl(ByVal Batch As BatchExecutor, ByVal Command As String) As List(Of String)
Dim urls As New List(Of String)
Dim u As GDLURL
With Batch
.Execute(Command)
If .ErrorOutputData.Count > 0 Then
For Each eValue$ In .ErrorOutputData
u = RegexFields(Of GDLURL)(eValue, {GdlUrlPattern}, {1, 2}, EDP.ReturnValue).ListIfNothing.FirstOrDefault
If Not u.URL.IsEmptyString Then urls.ListAddValue(u, LNC)
Next
End If
End With
Return urls
End Function
End Module
Friend Class GDLBatch : Inherits TokenBatch Friend Class GDLBatch : Inherits TokenBatch
Friend Const UrlLibStart As String = "[urllib3.connectionpool][debug]" Friend Const UrlLibStart As String = "[urllib3.connectionpool][debug]"
Friend Const UrlTextStart As String = UrlLibStart & " https" Friend Const UrlTextStart As String = UrlLibStart & " https"

View File

@@ -18,6 +18,7 @@ Namespace API.Base
End Enum End Enum
ReadOnly Property Site As String ReadOnly Property Site As String
ReadOnly Property Name As String ReadOnly Property Name As String
Property NameTrue As String
Property ID As String Property ID As String
Property Options As String Property Options As String
Property FriendlyName As String Property FriendlyName As String

View File

@@ -33,7 +33,7 @@ Namespace API.Base
End Property End Property
Friend Property AccountName As String Implements ISiteSettings.AccountName Friend Property AccountName As String Implements ISiteSettings.AccountName
Friend Property Temporary As Boolean = False Implements ISiteSettings.Temporary Friend Property Temporary As Boolean = False Implements ISiteSettings.Temporary
Friend Property DefaultInstance As ISiteSettings = Nothing Implements ISiteSettings.DefaultInstance Friend Overridable Property DefaultInstance As ISiteSettings = Nothing Implements ISiteSettings.DefaultInstance
Protected _UserAgentDefault As String = String.Empty Protected _UserAgentDefault As String = String.Empty
Friend Overridable Property UserAgentDefault As String Implements ISiteSettings.UserAgentDefault Friend Overridable Property UserAgentDefault As String Implements ISiteSettings.UserAgentDefault
Get Get
@@ -55,6 +55,11 @@ Namespace API.Base
Friend Overridable ReadOnly Property Responser As Responser Friend Overridable ReadOnly Property Responser As Responser
Private _UserOptionsExists As Boolean = False Private _UserOptionsExists As Boolean = False
Private _UserOptionsType As Type = Nothing Private _UserOptionsType As Type = Nothing
Protected Overridable Function UserOptionsValid(ByVal Options As Object) As Boolean
Return True
End Function
Protected Overridable Sub UserOptionsSetParameters(ByRef Options As Object)
End Sub
Protected Property UserOptionsType As Type Protected Property UserOptionsType As Type
Get Get
Return _UserOptionsType Return _UserOptionsType
@@ -243,7 +248,7 @@ Namespace API.Base
#Region "User info" #Region "User info"
Protected UrlPatternUser As String = String.Empty Protected UrlPatternUser As String = String.Empty
Friend Overridable Function GetUserUrl(ByVal User As IPluginContentProvider) As String Implements ISiteSettings.GetUserUrl Friend Overridable Function GetUserUrl(ByVal User As IPluginContentProvider) As String Implements ISiteSettings.GetUserUrl
If Not UrlPatternUser.IsEmptyString Then Return String.Format(UrlPatternUser, User.Name) If Not UrlPatternUser.IsEmptyString Then Return String.Format(UrlPatternUser, User.NameTrue.IfNullOrEmpty(User.Name))
Return String.Empty Return String.Empty
End Function End Function
Private Function ISiteSettings_GetUserPostUrl(ByVal User As IPluginContentProvider, ByVal Media As IUserMedia) As String Implements ISiteSettings.GetUserPostUrl Private Function ISiteSettings_GetUserPostUrl(ByVal User As IPluginContentProvider, ByVal Media As IUserMedia) As String Implements ISiteSettings.GetUserPostUrl
@@ -380,11 +385,40 @@ Namespace API.Base
End Sub End Sub
Friend Overridable Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean) Implements ISiteSettings.UserOptions Friend Overridable Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean) Implements ISiteSettings.UserOptions
If _UserOptionsExists Then If _UserOptionsExists Then
If Options Is Nothing OrElse Not Options.GetType Is _UserOptionsType Then If Options Is Nothing OrElse (Not Options.GetType Is _UserOptionsType OrElse Not UserOptionsValid(Options)) Then
Options = AConvert(Me, AModes.Var, _UserOptionsType,, True, Nothing) Dim args% = 0
Dim constructor As ConstructorInfo = Nothing
With _UserOptionsType.GetTypeInfo.DeclaredConstructors
If .ListExists Then
With .Where(Function(ByVal c As ConstructorInfo) As Boolean
With c.GetParameters
If .ListExists Then
If .Count = 1 Then
Return .Self()(0).ParameterType.GetInterfaces.ListIfNothing.Where(Function(i) i Is Me.GetType).Count = 1
Else
Return False
End If
Else
Return True
End If
End With
Return If(c.GetParameters?.Count, 0).ValueBetween(0, 1)
End Function)
If .ListExists Then
args = .Max(Of Integer)(Function(c) If(c.GetParameters?.Count, 0))
constructor = .First(Function(c) If(c.GetParameters?.Count, 0) = args)
End If
End With
End If
End With
If Not constructor Is Nothing Then
If args > 0 AndAlso Not constructor.GetParameters()(0).ParameterType Is GetType(ISiteSettings) Then Throw New Exception
If args = 0 Then Options = constructor.Invoke(Nothing) Else Options = constructor.Invoke({Me})
End If
If Options Is Nothing Then Options = Activator.CreateInstance(_UserOptionsType) If Options Is Nothing Then Options = Activator.CreateInstance(_UserOptionsType)
If Not Options Is Nothing Then UserOptionsSetParameters(Options)
End If End If
If OpenForm Then If Not Options Is Nothing And OpenForm Then
Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using
End If End If
Else Else

View File

@@ -178,6 +178,8 @@ Namespace API.Base
#Region "Additional names" #Region "Additional names"
Protected Const Name_SiteMode As String = "SiteMode" Protected Const Name_SiteMode As String = "SiteMode"
Protected Const Name_TrueName As String = "TrueName" Protected Const Name_TrueName As String = "TrueName"
'TODELETE Name_TrueName2
<Obsolete> Protected Const Name_TrueName2 As String = "NameTrue"
Protected Const Name_Arguments As String = "Arguments" Protected Const Name_Arguments As String = "Arguments"
#End Region #End Region
#End Region #End Region
@@ -278,6 +280,21 @@ Namespace API.Base
Return User.Name Return User.Name
End Get End Get
End Property End Property
Private _NameTrue As String = String.Empty
Friend Overridable Overloads Property NameTrue As String Implements IUserData.NameTrue, IPluginContentProvider.NameTrue
Get
Return NameTrue(False)
End Get
Set(ByVal NewName As String)
If Not _NameTrue = NewName Then EnvirChanged(NewName)
_NameTrue = NewName
End Set
End Property
Friend Overloads ReadOnly Property NameTrue(ByVal Exact As Boolean) As String
Get
Return If(Exact, _NameTrue, _NameTrue.IfNullOrEmpty(Name))
End Get
End Property
Friend Overridable Property ID As String = String.Empty Implements IUserData.ID, IPluginContentProvider.ID Friend Overridable Property ID As String = String.Empty Implements IUserData.ID, IPluginContentProvider.ID
Protected _FriendlyName As String = String.Empty Protected _FriendlyName As String = String.Empty
Friend Overridable Property FriendlyName As String Implements IUserData.FriendlyName Friend Overridable Property FriendlyName As String Implements IUserData.FriendlyName
@@ -348,12 +365,20 @@ Namespace API.Base
Protected Function UserDescriptionNeedToUpdate() As Boolean Protected Function UserDescriptionNeedToUpdate() As Boolean
Return (UserDescription.IsEmptyString Or _DescriptionEveryTime) And Not _DescriptionChecked Return (UserDescription.IsEmptyString Or _DescriptionEveryTime) And Not _DescriptionChecked
End Function End Function
Protected Sub UserDescriptionUpdate(ByVal Descr As String) Protected Sub UserDescriptionUpdate(ByVal Descr As String, Optional ByVal Force As Boolean = False,
If UserDescriptionNeedToUpdate() Then Optional ByVal InsertFirst As Boolean = False, Optional ByVal AppendDate As Boolean = False)
If UserDescriptionNeedToUpdate() Or Force Then
If AppendDate Then Descr = $"{Now.ToStringDateDef}: {Descr}"
If UserDescription.IsEmptyString Then If UserDescription.IsEmptyString Then
UserDescription = Descr UserDescription = Descr
_ForceSaveUserInfo = True
ElseIf Not UserDescription.Contains(Descr) Then ElseIf Not UserDescription.Contains(Descr) Then
UserDescription &= $"{vbNewLine}----{vbNewLine}{Descr}" If InsertFirst Then
UserDescription = $"{Descr}{vbNewLine}{UserDescription}"
Else
UserDescription &= $"{vbNewLine}----{vbNewLine}{Descr}"
End If
_ForceSaveUserInfo = True
End If End If
_DescriptionChecked = True _DescriptionChecked = True
End If End If
@@ -907,6 +932,10 @@ BlockNullPicture:
FileExists = True FileExists = True
Using x As New XmlFile(MyFileSettings) With {.XmlReadOnly = True} Using x As New XmlFile(MyFileSettings) With {.XmlReadOnly = True}
If User.Name.IsEmptyString Then User.Name = x.Value(Name_UserName) If User.Name.IsEmptyString Then User.Name = x.Value(Name_UserName)
_NameTrue = x.Value(Name_TrueName)
#Disable Warning BC40008
If _NameTrue.IsEmptyString AndAlso x.Contains(Name_TrueName2) Then _NameTrue = x.Value(Name_TrueName2)
#Enable Warning
UserExists = x.Value(Name_UserExists).FromXML(Of Boolean)(True) UserExists = x.Value(Name_UserExists).FromXML(Of Boolean)(True)
UserSuspended = x.Value(Name_UserSuspended).FromXML(Of Boolean)(False) UserSuspended = x.Value(Name_UserSuspended).FromXML(Of Boolean)(False)
ID = x.Value(Name_UserID) ID = x.Value(Name_UserID)
@@ -967,6 +996,7 @@ BlockNullPicture:
x.Add(Name_Plugin, HOST.Key) x.Add(Name_Plugin, HOST.Key)
x.Add(Name_AccountName, AccountName) x.Add(Name_AccountName, AccountName)
x.Add(Name_UserName, User.Name) x.Add(Name_UserName, User.Name)
x.Add(Name_TrueName, _NameTrue)
x.Add(Name_Model_User, CInt(UserModel)) x.Add(Name_Model_User, CInt(UserModel))
x.Add(Name_Model_Collection, CInt(CollectionModel)) x.Add(Name_Model_Collection, CInt(CollectionModel))
x.Add(Name_SpecialPath, User.SpecialPath) x.Add(Name_SpecialPath, User.SpecialPath)
@@ -1162,6 +1192,7 @@ BlockNullPicture:
Select Case Caller Select Case Caller
Case NameOf(UserExists) : If Not _EnvirUserExists = CBool(NewValue) Then _EnvirChanged = True : _EnvirInvokeUserUpdated = True Case NameOf(UserExists) : If Not _EnvirUserExists = CBool(NewValue) Then _EnvirChanged = True : _EnvirInvokeUserUpdated = True
Case NameOf(UserSuspended) : If Not _EnvirUserSuspended = CBool(NewValue) Then _EnvirChanged = True : _EnvirInvokeUserUpdated = True Case NameOf(UserSuspended) : If Not _EnvirUserSuspended = CBool(NewValue) Then _EnvirChanged = True : _EnvirInvokeUserUpdated = True
Case NameOf(NameTrue) : _EnvirChanged = True : _EnvirInvokeUserUpdated = True : _ForceSaveUserInfo = True : _ForceSaveUserInfoOnException = True
Case Else : _EnvirChanged = True Case Else : _EnvirChanged = True
End Select End Select
End If End If
@@ -1282,9 +1313,9 @@ BlockNullPicture:
UpdateUserInformation_Ex() UpdateUserInformation_Ex()
If Not exit_ex.Silent Then If Not exit_ex.Silent Then
If exit_ex.SimpleLogLine Then If exit_ex.SimpleLogLine Then
MyMainLOG = $"{ToStringForLog()}: downloading interrupted (exit) ({exit_ex.Message})" LogError(Nothing, $"downloading interrupted (exit) ({exit_ex.Message})")
Else Else
ErrorsDescriber.Execute(EDP.SendToLog, exit_ex, $"{ToStringForLog()}: downloading interrupted (exit)") LogError(exit_ex, "downloading interrupted (exit)")
End If End If
End If End If
If _EnvirInvokeUserUpdated Then OnUserUpdated() If _EnvirInvokeUserUpdated Then OnUserUpdated()
@@ -1846,6 +1877,31 @@ BlockNullPicture:
Protected Overridable Function CreateFileFromUrl(ByVal URL As String) As SFile Protected Overridable Function CreateFileFromUrl(ByVal URL As String) As SFile
Return New SFile(URL) Return New SFile(URL)
End Function End Function
Protected Overridable Function SimpleDownloadAvatar(ByVal ImageAddress As String, Optional ByVal FileCreateFunc As Func(Of String, SFile) = Nothing,
Optional ByVal e As ErrorsDescriber = Nothing) As SFile
Try
If Not ImageAddress.IsEmptyString Then
Dim f As SFile
If FileCreateFunc Is Nothing Then
f = CreateFileFromUrl(ImageAddress)
Else
f = FileCreateFunc.Invoke(ImageAddress)
End If
If Not f.Name.IsEmptyString Then f.Name = f.Name.StringRemoveWinForbiddenSymbols.StringTrim
If Not f.Name.IsEmptyString Then
f.Path = DownloadContentDefault_GetRootDir()
f.Separator = "\"
If f.Extension.IsEmptyString Then f.Extension = "jpg"
If Not f.Exists Then GetWebFile(ImageAddress, f, EDP.ReturnValue)
If f.Exists Then IconBannerDownloaded = True : Return f
End If
End If
Return Nothing
Catch ex As Exception
If Not e.Exists Then e = New ErrorsDescriber(EDP.ReturnValue)
Return ErrorsDescriber.Execute(e, ex, $"SimpleDownloadAvatar({ImageAddress})", New SFile)
End Try
End Function
Protected Overridable Function ChangeFileNameByProvider(ByVal f As SFile, ByVal m As UserMedia) As SFile Protected Overridable Function ChangeFileNameByProvider(ByVal f As SFile, ByVal m As UserMedia) As SFile
Dim ff As SFile = Nothing Dim ff As SFile = Nothing
Try Try

View File

@@ -134,6 +134,7 @@ Namespace API.Base
m.GetMemberCustomAttributes(Of Provider).ListExists m.GetMemberCustomAttributes(Of Provider).ListExists
Dim m1 As MemberInfo, m2 As MemberInfo Dim m1 As MemberInfo, m2 As MemberInfo
Dim tmpObj As Object Dim tmpObj As Object
Dim maxOffset%
members = GetObjectMembers(MyObject, Function(m) (m.MemberType = MemberTypes.Field Or m.MemberType = MemberTypes.Property) AndAlso members = GetObjectMembers(MyObject, Function(m) (m.MemberType = MemberTypes.Field Or m.MemberType = MemberTypes.Property) AndAlso
Not m.GetCustomAttribute(Of PSettingAttribute) Is Nothing,, True, Not m.GetCustomAttribute(Of PSettingAttribute) Is Nothing,, True,
@@ -175,6 +176,9 @@ Namespace API.Base
If MyMembers.Count > 0 Then If MyMembers.Count > 0 Then
maxOffset = MyMembers.Max(Function(mm) mm.LeftOffset)
If maxOffset > 0 Then MyMembers.ForEach(Sub(mm) mm.LeftOffset = maxOffset)
Dim prov As IEnumerable(Of Provider) Dim prov As IEnumerable(Of Provider)
Dim _prov As Provider Dim _prov As Provider
Dim si% = -1 Dim si% = -1

View File

@@ -0,0 +1,18 @@
' 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.Functions.RegularExpressions
Namespace API.Bluesky
Friend Module Declarations
Friend Const BlueskySiteKey As String = "AndyProgram_Bluesky"
Friend ReadOnly DateProvider As New ADateTime("yyyy-MM-ddTHH:mm:ss.FFF%K")
Friend ReadOnly RegEx_PlayLists As RParams = RParams.DM("RESOLUTION=\d+x(\d+)\s*(\S+)", 0, RegexReturn.List, EDP.ReturnValue)
Friend ReadOnly RegEx_FilePattern As RParams = RParams.DM("(.+?)(\.|@)(gif|m3u8|[^/\?\&]+)", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
Friend ReadOnly RegEx_SinglePostPattern As RParams = RParams.DM("profile/([^/]+)/post/([^/\?\&]+)", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
End Module
End Namespace

View File

@@ -0,0 +1,51 @@
' 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 System.Threading
Imports SCrawler.API.Base
Imports PersonalUtilities.Forms.Toolbars
Imports PersonalUtilities.Tools.Web.Clients
Imports PersonalUtilities.Functions.RegularExpressions
Namespace API.Bluesky
Friend NotInheritable Class M3U8
Private Sub New()
End Sub
Private Shared Function GetUrlsList(ByVal URL As String) As List(Of String)
Using resp As New Responser With {.AllowAutoRedirect = False}
Dim r$ = resp.GetResponse(URL)
If Not r.IsEmptyString Then
Dim file$ = String.Empty, appender$
Dim files As List(Of Sizes) = RegexFields(Of Sizes)(r, {RegEx_PlayLists}, {1, 2})
If files.ListExists Then files.RemoveAll(Function(ff) ff.Value = 0 Or ff.Data.IsEmptyString)
If files.ListExists Then
files.Sort()
file = files(0).Data
appender = URL.Replace(URL.Split("/").Last, String.Empty)
file = M3U8Base.CreateUrl(appender, file)
If Not file.IsEmptyString Then
r = resp.GetResponse(file)
If Not r.IsEmptyString Then
Dim l As List(Of String) = RegexReplace(r, M3U8Declarations.TsFilesRegEx)
If l.ListExists Then
appender = file.Replace(file.Split("/").Last, String.Empty)
For i% = 0 To l.Count - 1 : l(i) = M3U8Base.CreateUrl(appender, l(i)) : Next
Return l
End If
End If
End If
End If
End If
End Using
Return Nothing
End Function
Friend Shared Function Download(ByVal URL As String, ByVal Destination As SFile, ByVal Token As CancellationToken,
ByVal Progress As MyProgress, ByVal UsePreProgress As Boolean) As SFile
Return M3U8Base.Download(GetUrlsList(URL), Destination,, Token, Progress, UsePreProgress)
End Function
End Class
End Namespace

View File

@@ -0,0 +1,100 @@
' Copyright (C) Andy https://github.com/AAndyProgram
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports SCrawler.API.Base
Imports SCrawler.Plugin
Imports SCrawler.Plugin.Attributes
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.RegularExpressions
Imports PersonalUtilities.Tools.Web.Clients
Imports PersonalUtilities.Tools.Web.Documents.JSON
Namespace API.Bluesky
<Manifest(BlueskySiteKey), SpecialForm(False)>
Friend Class SiteSettings : Inherits SiteSettingsBase
<PropertyOption(ControlText:="Cookies enabled", ControlToolTip:="If checked, cookies will be used in requests", IsAuth:=True), PXML, PClonable, HiddenControl>
Friend ReadOnly Property CookiesEnabled As PropertyValue
<PropertyOption(ControlText:="User name", IsAuth:=True, AllowNull:=False), PXML>
Friend ReadOnly Property UserHandle As PropertyValue
<PropertyOption(ControlText:="Password", IsAuth:=True, AllowNull:=False), PXML>
Friend ReadOnly Property UserPassword As PropertyValue
<PXML> Friend ReadOnly Property Token As PropertyValue
<PXML> Friend ReadOnly Property TokenUpdateTime As PropertyValue
<PropertyOption(ControlText:="Token update", ControlToolTip:="Token refresh interval (in minutes)." & vbCr & "Default: 120.", IsAuth:=True), PXML, PClonable, HiddenControl>
Friend ReadOnly Property TokenRefreshInterval As PropertyValue
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
MyBase.New("Bluesky", "bsky.app", AccName, Temp, My.Resources.SiteResources.BlueskyIcon_32, My.Resources.SiteResources.BlueskyPic_32)
Responser.ContentType = "application/json"
CookiesEnabled = New PropertyValue(False)
UserHandle = New PropertyValue(String.Empty, GetType(String))
UserPassword = New PropertyValue(String.Empty, GetType(String))
Token = New PropertyValue(String.Empty, GetType(String))
TokenUpdateTime = New PropertyValue(Now.AddYears(-1))
TokenRefreshInterval = New PropertyValue(120)
_AllowUserAgentUpdate = False
UrlPatternUser = "https://bsky.app/profile/{0}"
ImageVideoContains = "bsky.app"
UserRegex = RParams.DMS("bsky.app/profile/([^/\?]+)", 1, EDP.ReturnValue)
UserOptionsType = GetType(EditorExchangeOptionsBase)
End Sub
Protected Overrides Function UserOptionsValid(ByVal Options As Object) As Boolean
Return DirectCast(Options, EditorExchangeOptionsBase).SiteKey = BlueskySiteKey
End Function
Protected Overrides Sub UserOptionsSetParameters(ByRef Options As Object)
DirectCast(Options, EditorExchangeOptionsBase).SiteKey = BlueskySiteKey
End Sub
Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider
Return New UserData
End Function
Friend Overrides Function BaseAuthExists() As Boolean
Return Not CStr(UserHandle.Value).IsEmptyString And Not CStr(UserPassword.Value).IsEmptyString
End Function
Friend Overrides Function Available(ByVal What As ISiteSettings.Download, ByVal Silent As Boolean) As Boolean
Return MyBase.Available(What, Silent) AndAlso UpdateToken()
End Function
Private _TokenUpdating As Boolean = False
Friend Function UpdateToken(Optional ByVal Force As Boolean = False) As Boolean
Try
While _TokenUpdating : Threading.Thread.Sleep(100) : End While
_TokenUpdating = True
If BaseAuthExists() Then
If CDate(TokenUpdateTime.Value).AddMinutes(TokenRefreshInterval.Value) < Now Or Force Then
Using resp As Responser = Responser.Copy
With resp
.Mode = Responser.Modes.Curl
.Method = "POST"
.CurlSslNoRevoke = True
.CurlInsecure = True
.CurlArgumentsLeft = "-d ""{\" & $"""identifier\"": \""{UserHandle.Value}\"", \""password\"": \""{UserPassword.Value}\""" & "}"""
Dim r$ = .GetResponse("https://bsky.social/xrpc/com.atproto.server.createSession")
If Not r.IsEmptyString Then
Using j As EContainer = JsonDocument.Parse(r, EDP.ReturnValue)
If j.ListExists Then
Dim t$ = j.Value("accessJwt")
If Not t.IsEmptyString Then Token.Value = $"Bearer {t}" : TokenUpdateTime.Value = Now : Return True
End If
End Using
End If
End With
End Using
Else
Return True
End If
End If
Return False
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.SendToLog + EDP.ReturnValue, ex, "Bluesky.SiteSettings.UpdateToken", False)
Finally
_TokenUpdating = False
End Try
End Function
End Class
End Namespace

View File

@@ -0,0 +1,330 @@
' 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 System.Threading
Imports SCrawler.API.Base
Imports SCrawler.API.YouTube.Objects
Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.RegularExpressions
Imports PersonalUtilities.Tools.Web.Documents.JSON
Imports UTypes = SCrawler.API.Base.UserMedia.Types
Imports UStates = SCrawler.API.Base.UserMedia.States
Namespace API.Bluesky
Friend Class UserData : Inherits UserDataBase
#Region "Declarations"
Private ReadOnly Property MySettings As SiteSettings
Get
Return HOST.Source
End Get
End Property
Private ReadOnly Property ID_Encoded As String
Get
Return If(ID.IsEmptyString, String.Empty, SymbolsConverter.ASCII.EncodeSymbolsOnly(ID))
End Get
End Property
#End Region
#Region "Loader"
Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean)
End Sub
Friend Overrides Function ExchangeOptionsGet() As Object
Return New EditorExchangeOptionsBase(Me) With {.SiteKey = BlueskySiteKey}
End Function
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
If Not Obj Is Nothing AndAlso TypeOf Obj Is EditorExchangeOptionsBase AndAlso
DirectCast(Obj, EditorExchangeOptionsBase).SiteKey = BlueskySiteKey Then NameTrue = DirectCast(Obj, EditorExchangeOptionsBase).UserName
End Sub
#End Region
#Region "Initializer"
Friend Sub New()
UseInternalM3U8Function = True
End Sub
#End Region
#Region "Token"
Private Function UpdateToken(Optional ByVal Force As Boolean = False, Optional ByVal OnlyAddHeader As Boolean = False) As Boolean
Dim process As Boolean = True
If CDate(MySettings.TokenUpdateTime.Value).AddHours(2) <= Now Or Force Then
process = MySettings.UpdateToken(Force)
If process Then _TokenUpdateCount += 1
End If
If process Or OnlyAddHeader Then Responser.Headers.Add("authorization", MySettings.Token.Value)
Return Not Responser.Headers.Value("authorization").IsEmptyString
End Function
Private _TokenUpdateCount As Integer = 0
Private Sub TokenUpdateCountReset()
_TokenUpdateCount = 0
End Sub
#End Region
#Region "Download"
Private _PostCount As Integer = 0
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
If Not CBool(MySettings.CookiesEnabled.Value) Then Responser.Cookies.Clear()
UpdateToken(, True)
_TokenUpdateCount = 0
_PostCount = 0
DownloadData(String.Empty, Token)
End Sub
Private Overloads Sub DownloadData(ByVal Cursor As String, ByVal Token As CancellationToken)
Dim URL$ = String.Empty
Try
If ID.IsEmptyString Then GetProfileInfo(Token)
If ID.IsEmptyString Then Throw New ArgumentNullException("ID", "ID is null")
If UpdateToken() Then
Dim nextCursor$ = String.Empty
Dim c%
URL = $"https://bsky.social/xrpc/app.bsky.feed.getAuthorFeed?actor={ID_Encoded}&filter=posts_and_author_threads&includePins=false&limit=99"
If Not Cursor.IsEmptyString Then URL &= $"&cursor={SymbolsConverter.ASCII.EncodeSymbolsOnly(Cursor)}"
Dim r$ = Responser.GetResponse(URL)
TokenUpdateCountReset()
If Not r.IsEmptyString Then
Using j As EContainer = JsonDocument.Parse(r)
If j.ListExists Then
With j("feed")
If .ListExists Then
For Each post As EContainer In .Self
With post({"post"})
c = DefaultParser(.Self,, nextCursor)
Select Case c
Case CInt(DateResult.Skip) * -1 : Continue For
Case CInt(DateResult.Exit) * -1 : Exit Sub
Case Is > 0 : _PostCount += c
End Select
If DownloadTopCount.HasValue AndAlso DownloadTopCount.Value <= _PostCount Then Exit Sub
End With
Next
End If
End With
End If
End Using
If Not nextCursor.IsEmptyString Then DownloadData(nextCursor, Token)
End If
End If
Catch ex As Exception
ProcessException(ex, Token, $"DownloadData({URL})")
End Try
End Sub
#End Region
#Region "DefaultParser"
Private Const Down_ImageAddress As String = "https://cdn.bsky.app/img/feed_fullsize/plain/{0}/{1}"
Private Function GetPostID(ByVal PostUri As String) As String
Return If(PostUri.IsEmptyString, String.Empty, PostUri.Split("/").LastOrDefault)
End Function
Private Function DefaultParser(ByVal e As EContainer, Optional ByVal CheckDateLimits As Boolean = True, Optional ByRef NextCursor As String = Nothing,
Optional ByVal CheckTempPosts As Boolean = True, Optional ByVal State As UStates = UStates.Unknown) As Integer
Const exitReturn% = CInt(DateResult.Exit) * -1
Dim postID$, postDate$, __url$, __urlBase$
Dim updateUrl As Boolean
Dim c% = 0
Dim m As UserMedia
Dim d As EContainer
With e
If .ListExists Then
postID = GetPostID(.Value("uri"))
postDate = String.Empty
__urlBase = String.Empty
With .Item({"record"})
If .ListExists Then
'2025-01-28T02:42:12.415Z
postDate = .Value("createdAt")
NextCursor = postDate
If CheckDateLimits Then
Select Case CheckDatesLimit(postDate, DateProvider)
Case DateResult.Skip : Return CInt(DateResult.Skip) * -1 'Continue For
Case DateResult.Exit : Return exitReturn 'Exit Sub
End Select
End If
If CheckTempPosts Then
If _TempPostsList.Contains(postID) Then Return exitReturn Else _TempPostsList.Add(postID)
End If
__urlBase = $"https://bsky.app/profile/{NameTrue}/post/{postID}"
End If
End With
Dim createMedia As Func(Of String, UTypes, UserMedia) =
Function(ByVal url As String, ByVal type As UTypes) As UserMedia
m = New UserMedia(url, type) With {
.URL_BASE = __urlBase,
.File = CreateFileFromUrl(url, type),
.Post = New UserPost(postID, If(AConvert(Of Date)(postDate, DateProvider, Nothing, EDP.ReturnValue), Nothing)),
.State = State
}
_TempMediaList.ListAddValue(m, LNC)
c += 1
Return m
End Function
For Each SecondExtraction As Boolean In {False, True}
With If(SecondExtraction, .Item({"record", "embed"}), .Item("embed"))
If .ListExists Then
If If(.Item("images")?.Count, 0) > 0 Then
With .Item("images")
For Each d In .Self
updateUrl = False
__url = d.Value("fullsize")
If __url.IsEmptyString Then __url = d.Value({"image", "ref"}, "$link") : updateUrl = True
If __url.IsEmptyString And SecondExtraction Then updateUrl = False : __url = e.Value({"embed"}, "thumb")
If Not __url.IsEmptyString Then createMedia(__url, UTypes.Picture)
Next
End With
End If
If Not .Value("playlist").IsEmptyString Then createMedia(.Value("playlist"), UTypes.m3u8)
If If(.Item("external")?.Count, 0) > 0 Then createMedia(.Value({"external"}, "uri"), UTypes.GIF)
End If
End With
If c > 0 Then Exit For
Next
End If
End With
Return c
End Function
#End Region
#Region "GetProfileInfo"
Private Sub GetProfileInfo(ByVal Token As CancellationToken)
Try
If UpdateToken() Then
Dim r$ = Responser.GetResponse($"https://bsky.social/xrpc/app.bsky.actor.getProfile?actor={ID.IfNullOrEmpty(NameTrue)}")
TokenUpdateCountReset()
If Not r.IsEmptyString Then
Using j As EContainer = JsonDocument.Parse(r)
If j.ListExists Then
ID = j.Value("did")
UserSiteNameUpdate(j.Value("displayName"))
UserDescriptionUpdate(j.Value("description"))
NameTrue = j.Value("handle")
SimpleDownloadAvatar(j.Value("avatar"))
SimpleDownloadAvatar(j.Value("banner"))
End If
End Using
End If
Else
Throw New ArgumentException("Token is null", "Token")
End If
Catch ex As Exception
ProcessException(ex, Token, "GetProfileInfo")
End Try
End Sub
#End Region
#Region "ReparseMissing"
Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken)
Const uriPattern$ = "at://{0}/app.bsky.feed.post/{1}"
Dim rList As New List(Of Integer)
Try
If ContentMissingExists AndAlso UpdateToken() Then
Dim r$, url$, uri$
Dim tu As Byte
Dim m As UserMedia
Dim j As EContainer
For i% = 0 To _ContentList.Count - 1
m = _ContentList(i)
If m.State = UStates.Missing Then
uri = SymbolsConverter.ASCII.EncodeSymbolsOnly(String.Format(uriPattern, NameTrue, m.Post.ID))
url = $"https://bsky.social/xrpc/app.bsky.feed.getPostThread?uri={uri}&depth=10"
For tu = 0 To 1
Try
Responser.ResetStatus()
r = Responser.GetResponse(url)
TokenUpdateCountReset()
If Not r.IsEmptyString Then
j = JsonDocument.Parse(r)
If j.ListExists Then
If DefaultParser(j({"thread", "post"}), False,, False, UStates.Missing) > 0 Then rList.Add(i)
j.Dispose()
End If
End If
Exit For
Catch eex As Exception
If ProcessException(eex, Token, $"ReparseMissing({url})",,, False) <> 1 Then Throw eex
End Try
Next
End If
Next
Else
Throw New ArgumentException("Token is null", "Token")
End If
Catch ex As Exception
ProcessException(ex, Token, "ReparseMissing error")
Finally
If rList.Count > 0 Then
For i% = rList.Count - 1 To 0 Step -1 : _ContentList.RemoveAt(rList(i)) : Next
rList.Clear()
End If
End Try
End Sub
#End Region
#Region "CreateFileFromUrl"
Protected Overloads Overrides Function CreateFileFromUrl(ByVal URL As String) As SFile
Return CreateFileFromUrl(URL, UTypes.Undefined)
End Function
Protected Overloads Function CreateFileFromUrl(ByVal URL As String, ByVal Type As UTypes) As SFile
Dim f As SFile = MyBase.CreateFileFromUrl(URL)
Dim force As Boolean = False
f.Separator = "\"
With URL.Split("/")
If .ListExists Then
With DirectCast(RegexReplace(.Last, RegEx_FilePattern), List(Of String))
If .ListExists(4) Then
f.Name = .Item(1).IfNullOrEmpty(f.Name)
f.Extension = .Item(3)
End If
End With
End If
End With
If Not f.Extension.IsEmptyString AndAlso f.Extension.ToLower = "m3u8" Then force = True : Type = UTypes.m3u8
If f.Extension.IsEmptyString Or force Then
Select Case Type
Case UTypes.Picture : f.Extension = "jpg"
Case UTypes.GIF : f.Extension = "gif"
Case UTypes.m3u8 : f.Name = "Video" : f.Extension = "mp4"
End Select
End If
Return f
End Function
#End Region
#Region "DownloadContent"
Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
DownloadContentDefault(Token)
End Sub
Protected Overrides Function DownloadM3U8(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile, ByVal Token As CancellationToken) As SFile
Return M3U8.Download(URL, DestinationFile, Token, Progress, Not IsSingleObjectDownload)
End Function
#End Region
#Region "DownloadSingleObject"
Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)
_TokenUpdateCount = 0
UpdateToken()
Dim l As List(Of String) = RegexReplace(Data.URL, RegEx_SinglePostPattern)
If l.ListExists(3) Then
NameTrue = l(1)
_ContentList.Add(New UserMedia(Data.URL) With {.State = UStates.Missing, .Post = l(2)})
ReparseMissing(Token)
End If
MyBase.DownloadSingleObject_GetPosts(Data, Token)
End Sub
#End Region
#Region "Exception"
Protected Overrides Function DownloadingException(ByVal ex As Exception, ByVal Message As String, Optional ByVal FromPE As Boolean = False,
Optional ByVal EObj As Object = Nothing) As Integer
If Responser.StatusCode = Net.HttpStatusCode.BadRequest Then '400
If _TokenUpdateCount = 0 AndAlso UpdateToken(True) Then
Return 1
Else
Return 0
End If
Else
Return 0
End If
End Function
#End Region
End Class
End Namespace

View File

@@ -18,6 +18,8 @@ Namespace API.Facebook
Friend ReadOnly Regex_FileName As RParams = RParams.DM("([^/\?]+\..{3,4})(?=(\?|\Z))", 0, EDP.ReturnValue) Friend ReadOnly Regex_FileName As RParams = RParams.DM("([^/\?]+\..{3,4})(?=(\?|\Z))", 0, EDP.ReturnValue)
Friend ReadOnly Regex_ProfileUrlID As RParams = RParams.DMS("profile.php\?id=(\d+)", 1, EDP.ReturnValue) Friend ReadOnly Regex_ProfileUrlID As RParams = RParams.DMS("profile.php\?id=(\d+)", 1, EDP.ReturnValue)
Friend ReadOnly Regex_VideoPageID As RParams = RParams.DMS("pageid.:.(\d+)", 1, RegexOptions.IgnoreCase, EDP.ReturnValue) Friend ReadOnly Regex_VideoPageID As RParams = RParams.DMS("pageid.:.(\d+)", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
Friend ReadOnly Regex_ReelsPageID As RParams = RParams.DMS("\{[^\}]*""tab_key"":""owner_reels"",?[^\}]*""id"":""([^\}""]+)""", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
Friend ReadOnly Regex_ReelsFilePattern As RParams = RParams.DM("[^/]+\.mp4", 0, EDP.ReturnValue)
Friend ReadOnly Regex_StoryBucket As RParams = RParams.DMS("story_bucket[^\>]*?(\d+)", 1, EDP.ReturnValue) Friend ReadOnly Regex_StoryBucket As RParams = RParams.DMS("story_bucket[^\>]*?(\d+)", 1, EDP.ReturnValue)
Friend ReadOnly Regex_VideoIDFromURL As RParams = RParams.DMS("facebook.com/([^/]+/videos/|watch/\D*[\?&]{1}v=)(\d+)", 2, EDP.ReturnValue) Friend ReadOnly Regex_VideoIDFromURL As RParams = RParams.DMS("facebook.com/([^/]+/videos/|watch/\D*[\?&]{1}v=)(\d+)", 2, EDP.ReturnValue)

View File

@@ -36,6 +36,8 @@ Namespace API.Facebook
Friend ReadOnly Property ParsePhotoBlock As PropertyValue Friend ReadOnly Property ParsePhotoBlock As PropertyValue
<PropertyOption(ControlText:="Download videos", IsAuth:=False, Category:=DN.CAT_UserDefs), PXML, PClonable> <PropertyOption(ControlText:="Download videos", IsAuth:=False, Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property ParseVideoBlock As PropertyValue Friend ReadOnly Property ParseVideoBlock As PropertyValue
<PropertyOption(ControlText:="Download reels", IsAuth:=False, Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property ParseReelsBlock As PropertyValue
<PropertyOption(ControlText:="Download stories", IsAuth:=False, Category:=DN.CAT_UserDefs), PXML, PClonable> <PropertyOption(ControlText:="Download stories", IsAuth:=False, Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property ParseStoriesBlock As PropertyValue Friend ReadOnly Property ParseStoriesBlock As PropertyValue
#End Region #End Region
@@ -52,6 +54,7 @@ Namespace API.Facebook
Header_Accept = New PropertyValue(String.Empty, GetType(String)) Header_Accept = New PropertyValue(String.Empty, GetType(String))
ParsePhotoBlock = New PropertyValue(True) ParsePhotoBlock = New PropertyValue(True)
ParseVideoBlock = New PropertyValue(True) ParseVideoBlock = New PropertyValue(True)
ParseReelsBlock = New PropertyValue(False)
ParseStoriesBlock = New PropertyValue(True) ParseStoriesBlock = New PropertyValue(True)
UrlPatternUser = "https://www.facebook.com/{0}" UrlPatternUser = "https://www.facebook.com/{0}"

View File

@@ -23,9 +23,11 @@ Namespace API.Facebook
Private Const Name_IsNoNameProfile As String = "IsNoNameProfile" Private Const Name_IsNoNameProfile As String = "IsNoNameProfile"
Private Const Name_OptionsParsed As String = "OptionsParsed" Private Const Name_OptionsParsed As String = "OptionsParsed"
Private Const Name_VideoPageID As String = "VideoPageID" Private Const Name_VideoPageID As String = "VideoPageID"
Private Const Name_ReelsPageID As String = "ReelsPageID"
Private Const Name_StoryBucket As String = "StoryBucket" Private Const Name_StoryBucket As String = "StoryBucket"
Private Const Name_ParsePhotoBlock As String = "ParsePhotoBlock" Private Const Name_ParsePhotoBlock As String = "ParsePhotoBlock"
Private Const Name_ParseVideoBlock As String = "ParseVideoBlock" Private Const Name_ParseVideoBlock As String = "ParseVideoBlock"
Private Const Name_ParseReelsBlock As String = "ParseReelsBlock"
Private Const Name_ParseStoriesBlock As String = "ParseStoriesBlock" Private Const Name_ParseStoriesBlock As String = "ParseStoriesBlock"
#End Region #End Region
#Region "Declarations" #Region "Declarations"
@@ -37,15 +39,18 @@ Namespace API.Facebook
Private IsNoNameProfile As Boolean = False Private IsNoNameProfile As Boolean = False
Private OptionsParsed As Boolean = False Private OptionsParsed As Boolean = False
Private Property VideoPageID As String = String.Empty Private Property VideoPageID As String = String.Empty
Private Property ReelsPageID As String = String.Empty
Private Property StoryBucket As String = String.Empty Private Property StoryBucket As String = String.Empty
Friend Property ParsePhotoBlock As Boolean = True Friend Property ParsePhotoBlock As Boolean = True
Friend Property ParseVideoBlock As Boolean = True Friend Property ParseVideoBlock As Boolean = True
Friend Property ParseReelsBlock As Boolean = False
Friend Property ParseStoriesBlock As Boolean = True Friend Property ParseStoriesBlock As Boolean = True
Private Enum PageBlock As Integer Private Enum PageBlock As Integer
Timeline = Sections.Timeline Timeline = Sections.Timeline
Stories = Sections.Stories Stories = Sections.Stories
Photos = 100 Photos = 100
Videos = 101 Videos = 101
Reels = Sections.Reels
Undefined = -1 Undefined = -1
End Enum End Enum
#End Region #End Region
@@ -67,6 +72,7 @@ Namespace API.Facebook
With DirectCast(Obj, UserExchangeOptions) With DirectCast(Obj, UserExchangeOptions)
ParsePhotoBlock = .ParsePhotoBlock ParsePhotoBlock = .ParsePhotoBlock
ParseVideoBlock = .ParseVideoBlock ParseVideoBlock = .ParseVideoBlock
ParseReelsBlock = .ParseReelsBlock
ParseStoriesBlock = .ParseStoriesBlock ParseStoriesBlock = .ParseStoriesBlock
End With End With
End If End If
@@ -90,18 +96,22 @@ Namespace API.Facebook
End If End If
OptionsParsed = .Value(Name_OptionsParsed).FromXML(Of Boolean)(False) OptionsParsed = .Value(Name_OptionsParsed).FromXML(Of Boolean)(False)
VideoPageID = .Value(Name_VideoPageID) VideoPageID = .Value(Name_VideoPageID)
ReelsPageID = .Value(Name_ReelsPageID)
StoryBucket = .Value(Name_StoryBucket) StoryBucket = .Value(Name_StoryBucket)
ParsePhotoBlock = .Value(Name_ParsePhotoBlock).FromXML(Of Boolean)(True) ParsePhotoBlock = .Value(Name_ParsePhotoBlock).FromXML(Of Boolean)(True)
ParseVideoBlock = .Value(Name_ParseVideoBlock).FromXML(Of Boolean)(True) ParseVideoBlock = .Value(Name_ParseVideoBlock).FromXML(Of Boolean)(True)
ParseReelsBlock = .Value(Name_ParseReelsBlock).FromXML(Of Boolean)(False)
ParseStoriesBlock = .Value(Name_ParseStoriesBlock).FromXML(Of Boolean)(True) ParseStoriesBlock = .Value(Name_ParseStoriesBlock).FromXML(Of Boolean)(True)
Else Else
updateNames.Invoke updateNames.Invoke
.Add(Name_IsNoNameProfile, IsNoNameProfile.BoolToInteger) .Add(Name_IsNoNameProfile, IsNoNameProfile.BoolToInteger)
.Add(Name_OptionsParsed, OptionsParsed.BoolToInteger) .Add(Name_OptionsParsed, OptionsParsed.BoolToInteger)
.Add(Name_VideoPageID, VideoPageID) .Add(Name_VideoPageID, VideoPageID)
.Add(Name_ReelsPageID, ReelsPageID)
.Add(Name_StoryBucket, StoryBucket) .Add(Name_StoryBucket, StoryBucket)
.Add(Name_ParsePhotoBlock, ParsePhotoBlock.BoolToInteger) .Add(Name_ParsePhotoBlock, ParsePhotoBlock.BoolToInteger)
.Add(Name_ParseVideoBlock, ParseVideoBlock.BoolToInteger) .Add(Name_ParseVideoBlock, ParseVideoBlock.BoolToInteger)
.Add(Name_ParseReelsBlock, ParseReelsBlock.BoolToInteger)
.Add(Name_ParseStoriesBlock, ParseStoriesBlock.BoolToInteger) .Add(Name_ParseStoriesBlock, ParseStoriesBlock.BoolToInteger)
End If End If
End With End With
@@ -146,6 +156,7 @@ Namespace API.Facebook
Else Else
If DownloadImages And ParsePhotoBlock Then DownloadData_Photo(String.Empty, Token) If DownloadImages And ParsePhotoBlock Then DownloadData_Photo(String.Empty, Token)
If DownloadVideos And ParseVideoBlock Then DownloadData_Video(String.Empty, Token) If DownloadVideos And ParseVideoBlock Then DownloadData_Video(String.Empty, Token)
If DownloadVideos And ParseReelsBlock Then DownloadData_Reels(String.Empty, Token)
If (DownloadImages Or DownloadVideos) And ParseStoriesBlock Then DownloadData_Stories(Token) If (DownloadImages Or DownloadVideos) And ParseStoriesBlock Then DownloadData_Stories(Token)
End If End If
LoadSavePostsKV(False) LoadSavePostsKV(False)
@@ -158,10 +169,12 @@ Namespace API.Facebook
Private Const Header_fb_fr_name_Video As String = "PagesCometChannelTabAllVideosCardImplPaginationQuery" Private Const Header_fb_fr_name_Video As String = "PagesCometChannelTabAllVideosCardImplPaginationQuery"
Private Const Header_fb_fr_name_Stories As String = "StoriesSuspenseContentPaneRootWithEntryPointQuery" Private Const Header_fb_fr_name_Stories As String = "StoriesSuspenseContentPaneRootWithEntryPointQuery"
Private Const Header_fb_fr_name_SavedPosts As String = "CometSaveDashboardAllItemsPaginationQuery" Private Const Header_fb_fr_name_SavedPosts As String = "CometSaveDashboardAllItemsPaginationQuery"
Private Const Header_fb_fr_name_Reels As String = "ProfileCometAppCollectionReelsRendererPaginationQuery"
Private Const DocID_Photo As String = "6684543058255697" Private Const DocID_Photo As String = "6684543058255697"
Private Const DocID_Video As String = "24545934291687581" Private Const DocID_Video As String = "24545934291687581"
Private Const DocID_Stories As String = "6771064226315961" Private Const DocID_Stories As String = "6771064226315961"
Private Const DocID_SavedPosts As String = "7112228098805003" Private Const DocID_SavedPosts As String = "7112228098805003"
Private Const DocID_Reels As String = "28517740954539304"
Private Const Graphql_UrlPattern As String = "https://www.facebook.com/api/graphql?lsd={0}&doc_id={1}&server_timestamps=true&fb_dtsg={3}&fb_api_req_friendly_name={2}&variables={4}" Private Const Graphql_UrlPattern As String = "https://www.facebook.com/api/graphql?lsd={0}&doc_id={1}&server_timestamps=true&fb_dtsg={3}&fb_api_req_friendly_name={2}&variables={4}"
Private Const VideoHtmlUrlPattern As String = "https://www.facebook.com/watch/?v={0}" Private Const VideoHtmlUrlPattern As String = "https://www.facebook.com/watch/?v={0}"
Private Sub DownloadData_Photo(ByVal Cursor As String, ByVal Token As CancellationToken) Private Sub DownloadData_Photo(ByVal Cursor As String, ByVal Token As CancellationToken)
@@ -238,7 +251,7 @@ Namespace API.Facebook
Dim newPostsDetected As Boolean = False Dim newPostsDetected As Boolean = False
Dim pid As PostKV Dim pid As PostKV
If VideoPageID.IsEmptyString Then GetVideoPageID(Token) If VideoPageID.IsEmptyString Then GetVideoPageID(False, Token)
If VideoPageID.IsEmptyString Then Throw New TokensException("Unable to obtain 'VideoPageID'", False) If VideoPageID.IsEmptyString Then Throw New TokensException("Unable to obtain 'VideoPageID'", False)
ValidateBaseTokens() ValidateBaseTokens()
@@ -355,6 +368,123 @@ Namespace API.Facebook
ProcessException(ex, Token, $"data (stories) downloading error [{URL}]",, Responser) ProcessException(ex, Token, $"data (stories) downloading error [{URL}]",, Responser)
End Try End Try
End Sub End Sub
Private Sub DownloadData_Reels(ByVal Cursor As String, ByVal Token As CancellationToken)
Dim URL$ = String.Empty
Const VarPattern$ = """count"":10,""cursor"":{0},""feedLocation"":""COMET_MEDIA_VIEWER"",""feedbackSource"":65,""focusCommentID"":null,""renderLocation"":null,""scale"":1,""useDefaultActor"":true,""id"":""{1}"",""__relay_internal__pv__FBReelsMediaFooter_comet_enable_reels_ads_gkrelayprovider"":true,""__relay_internal__pv__IsWorkUserrelayprovider"":false"
Try
Dim nextCursor$ = String.Empty
Dim newPostsDetected As Boolean = False
Dim nodeFound As Boolean = False
Dim pid As PostKV = Nothing
Dim __urlBase$ = String.Empty
Dim lines As List(Of String)
Dim j As EContainer, rr As EContainer
Dim jDataRoot As EContainer = Nothing
Dim indx% = -1
Dim s As New List(Of Sizes)
Dim videoIdNode$() = {"profile_reel_node", "node", "video", "id"}
Dim obtainBasePostData As Action = Sub()
If indx.ValueBetween(0, jDataRoot.Count - 1) Then
With jDataRoot(indx)
pid = New PostKV(String.Empty, .Item(videoIdNode).XmlIfNothingValue.
IfNullOrEmpty(.Value({"node"}, "id")), PageBlock.Reels)
pid.Code = $"Reels:{pid.ID}"
nextCursor = .Value("cursor")
If Not .Item(videoIdNode).XmlIfNothing.IsEmptyString Then
__urlBase = $"https://www.facebook.com/reel/{pid.ID}"
Else
__urlBase = String.Empty
End If
End With
Else
pid = Nothing
nextCursor = String.Empty
__urlBase = String.Empty
End If
End Sub
Dim createFile As Func(Of String, SFile, SFile) = Function(ByVal __url As String, ByVal cFile As SFile) As SFile
Dim f As New SFile(RegexReplace(__url, Regex_ReelsFilePattern))
If Not f.IsEmptyString Then Return f Else Return cFile
End Function
If ReelsPageID.IsEmptyString Then GetVideoPageID(True, Token)
If ReelsPageID.IsEmptyString Then Throw New TokensException("Unable to obtain 'ReelsPageID'", False)
ValidateBaseTokens()
URL = String.Format(Graphql_UrlPattern, Token_lsd, DocID_Reels, Header_fb_fr_name_Reels, Token_dtsg_Var,
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(VarPattern, If(Cursor.IsEmptyString, "null", $"""{Cursor}"""), ReelsPageID) & "}"))
ResponserApplyDefs(Header_fb_fr_name_Reels)
ThrowAny(Token)
WaitTimer()
Dim r$ = Responser.GetResponse(URL)
If Not r.IsEmptyString Then
lines = r.StringToList(Of String)(vbCrLf).ListIfNothing
If lines.ListExists Then
For Each line$ In lines
j = JsonDocument.Parse(line, EDP.ReturnValue)
If j.ListExists Then
jDataRoot = j({"data", "node", "aggregated_fb_shorts", "edges"})
If jDataRoot.ListExists Then
With j({"extensions", "all_video_dash_prefetch_representations"})
If .ListExists Then
ProgressPre.ChangeMax(.Count)
For indx = 0 To .Count - 1
ProgressPre.Perform()
obtainBasePostData()
If Not pid.ID.IsEmptyString AndAlso Not PostKvExists(pid) Then
newPostsDetected = True
PostsKVIDs.ListAddValue(pid, LNC)
_TempPostsList.Add(pid.Code)
With .ItemF({indx, "representations"})
If .ListExists Then
s.Clear()
For Each rr In .Self : s.Add(New Sizes(rr.Value("width"), rr.Value("base_url"))) : Next
If s.Count > 0 Then s.RemoveAll(Function(ss) ss.Value = 0 Or ss.Data.IsEmptyString)
If s.Count > 0 Then
s.Sort()
_TempMediaList.ListAddValue(New UserMedia(s(0).Data, UTypes.Video) With {
.URL_BASE = __urlBase.IfNullOrEmpty(.URL_BASE),
.Post = pid.ID,
.File = createFile(s(0).Data, .File),
.SpecialFolder = "Reels*"
}, LNC)
s.Clear()
End If
End If
End With
If Limit > 0 And _TempMediaList.Count >= Limit Then j.Dispose() : Exit Sub
Else
j.Dispose()
Exit Sub
End If
Next
End If
End With
End If
j.Dispose()
End If
Next
End If
End If
If newPostsDetected And Not nextCursor.IsEmptyString Then DownloadData_Reels(nextCursor, Token)
Catch tex As TokensException When Not tex.BasicTokens
TokensException.SendToLog(Me, tex, "data (reels)")
Catch ex As Exception
ProcessException(ex, Token, $"data (reels) downloading error [{URL}]",, Responser)
End Try
End Sub
Private Sub DownloadData_SavedPosts(ByVal Cursor As String, ByVal Token As CancellationToken) Private Sub DownloadData_SavedPosts(ByVal Cursor As String, ByVal Token As CancellationToken)
Dim URL$ = String.Empty Dim URL$ = String.Empty
Const VarPattern$ = """content_filter"":[],""count"":10,""cursor"":{0},""scale"":1,""use_case"":""SAVE_DEFAULT""" Const VarPattern$ = """content_filter"":[],""count"":10,""cursor"":{0},""scale"":1,""use_case"":""SAVE_DEFAULT"""
@@ -507,13 +637,19 @@ Namespace API.Facebook
Return True Return True
End If End If
End Function End Function
Private Sub GetVideoPageID(ByVal Token As CancellationToken) Private Sub GetVideoPageID(ByVal GetReels As Boolean, ByVal Token As CancellationToken)
Dim URL$ = $"{GetProfileUrl()}\videos" Dim URL$ = $"{GetProfileUrl()}\{IIf(GetReels, "reels", "videos")}"
Dim resp As Responser = HtmlResponserCreate() Dim resp As Responser = HtmlResponserCreate()
Try Try
WaitTimer() WaitTimer()
Dim r$ = resp.GetResponse(URL) Dim r$ = resp.GetResponse(URL)
If Not r.IsEmptyString Then VideoPageID = RegexReplace(r, Regex_VideoPageID) If Not r.IsEmptyString Then
If GetReels Then
ReelsPageID = RegexReplace(r, Regex_ReelsPageID)
Else
VideoPageID = RegexReplace(r, Regex_VideoPageID)
End If
End If
Catch ex As Exception Catch ex As Exception
ProcessException(ex, Token, "get video page ID",, resp) ProcessException(ex, Token, "get video page ID",, resp)
Finally Finally
@@ -658,17 +794,39 @@ Namespace API.Facebook
HtmlResponserDispose(resp) HtmlResponserDispose(resp)
End Try End Try
End Sub End Sub
Private Structure VideoResolution : Implements IComparable(Of VideoResolution)
Friend W As Integer
Friend H As Integer
Friend B As Integer
Friend U As String
Friend ReadOnly Property Wrong As Boolean
Get
Return W = 0 Or H = 0 Or B = 0 Or U.IsEmptyString
End Get
End Property
Private Function CompareTo(ByVal Other As VideoResolution) As Integer Implements IComparable(Of VideoResolution).CompareTo
Return CLng(Math.Max(W, H) * B).CompareTo(CLng(Math.Max(Other.W, Other.H) * Other.B)) * -1
End Function
End Structure
Protected Function ReparseSingleVideo(ByVal m As UserMedia, ByVal resp As Responser, ByRef result As Boolean) As UserMedia Protected Function ReparseSingleVideo(ByVal m As UserMedia, ByVal resp As Responser, ByRef result As Boolean) As UserMedia
Const nameSD$ = "browser_native_sd_url" Const nameSD$ = "browser_native_sd_url"
Const nameHD$ = "browser_native_hd_url" Const nameHD$ = "browser_native_hd_url"
Const nameDPR$ = "all_video_dash_prefetch_representations"
Const pattern$ = "<script type=""application/json""[^\>]*data-sjs>([^<]+?{0}[^<]+)<" Const pattern$ = "<script type=""application/json""[^\>]*data-sjs>([^<]+?{0}[^<]+)<"
Dim URL$ = String.Empty Dim URL$ = String.Empty
Dim j As EContainer = Nothing Dim j As EContainer = Nothing
Try Try
Dim r$, script$, __url$ Dim r$ = String.Empty, script$ = String.Empty, __url$ = String.Empty
Dim isNewNodes As Boolean = False
Dim __date As Date? = Nothing
Dim jNode As EContainer Dim jNode As EContainer
Dim jf As Predicate(Of EContainer) = Function(ee) Not ee.Name.IsEmptyString AndAlso (ee.Name.ToLower = nameSD Or ee.Name.ToLower = nameHD) Dim jf As Predicate(Of EContainer) = Function(ee) Not ee.Name.IsEmptyString AndAlso (ee.Name.ToLower = nameSD Or ee.Name.ToLower = nameHD)
Dim re As RParams = RParams.DMS("", 1, RegexOptions.IgnoreCase, EDP.ReturnValue) Dim re As RParams = RParams.DMS("", 1, RegexOptions.IgnoreCase, EDP.ReturnValue)
Dim nf As New XML.Base.NodeParams(nameDPR, True, True, True, True, 20)
Dim __extractScript As Action(Of String) = Sub(ByVal inputName As String)
re.Pattern = String.Format(pattern, inputName)
script = RegexReplace(r, re)
End Sub
If m.Post.ID.IsEmptyString Then If m.Post.ID.IsEmptyString Then
URL = m.URL_BASE URL = m.URL_BASE
Else Else
@@ -677,30 +835,47 @@ Namespace API.Facebook
WaitTimer() WaitTimer()
r = resp.GetResponse(URL) r = resp.GetResponse(URL)
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
re.Pattern = String.Format(pattern, nameHD) __extractScript(nameHD)
script = RegexReplace(r, re) If script.IsEmptyString Then __extractScript(nameSD)
If script.IsEmptyString Then If script.IsEmptyString Then __extractScript(nameDPR) : isNewNodes = True
re.Pattern = String.Format(pattern, nameSD)
script = RegexReplace(r, re)
End If
If Not script.IsEmptyString Then If Not script.IsEmptyString Then
j = JsonDocument.Parse(script) j = JsonDocument.Parse(script)
If j.ListExists Then If j.ListExists Then
j.SetSourceReferences() j.SetSourceReferences()
jNode = j.Find(jf, True) If isNewNodes Then
If Not jNode Is Nothing Then jNode = j.GetNode({nf})
With DirectCast(jNode.Source, EContainer) If Not jNode Is Nothing Then
__url = .Value(nameHD).IfNullOrEmpty(.Value(nameSD)) With jNode.ItemF({0, "representations"})
If Not __url.IsEmptyString Then If .ListExists Then
m.URL = __url Dim intE As New ErrorsDescriber(False, False, False, 0)
m.URL_BASE = URL Dim intC As Func(Of String, Integer) = Function(__input) AConvert(Of Integer)(__input, intE)
m.Type = UTypes.Video Dim dataV As List(Of VideoResolution) = .Select(Function(jj) New VideoResolution With {
m.File = CreateFileFromUrl(__url) .W = intC(jj.Value("width")),
m.Post.Date = AConvert(Of Date)(.Value("publish_time"), UnixDate32Provider, Nothing) .H = intC(jj.Value("height")),
result = True .B = intC(jj.Value("bandwidth")),
Return m .U = jj.Value("base_url")}).ListIfNothing
End If If dataV.ListExists Then dataV.RemoveAll(Function(dd) dd.Wrong)
End With If dataV.ListExists Then dataV.Sort() : __url = dataV(0).U : dataV.Clear() : __date = m.Post.Date
End If
End With
End If
Else
jNode = j.Find(jf, True)
If Not jNode Is Nothing Then
With DirectCast(jNode.Source, EContainer)
__url = .Value(nameHD).IfNullOrEmpty(.Value(nameSD))
If Not __url.IsEmptyString Then __date = AConvert(Of Date)(.Value("publish_time"), UnixDate32Provider, Nothing)
End With
End If
End If
If Not __url.IsEmptyString Then
m.URL = __url
m.URL_BASE = URL
m.Type = UTypes.Video
m.File = CreateFileFromUrl(__url)
m.Post.Date = __date
result = True
Return m
End If End If
End If End If
End If End If
@@ -738,7 +913,10 @@ Namespace API.Facebook
#End Region #End Region
#Region "DownloadSingleObject" #Region "DownloadSingleObject"
Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken) Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)
_ContentList.Add(New UserMedia(Data.URL, UTypes.VideoPre) With {.Post = CStr(AConvert(Of String)(Data.URL, Regex_VideoIDFromURL, String.Empty))}) _ContentList.Add(New UserMedia(Data.URL, UTypes.VideoPre) With {
.Post = CStr(AConvert(Of String)(Data.URL, Regex_VideoIDFromURL, String.Empty)),
.State = UStates.Missing
})
ReparseMissing(Token) ReparseMissing(Token)
End Sub End Sub
#End Region #End Region

View File

@@ -13,6 +13,8 @@ Namespace API.Facebook
Friend Property ParsePhotoBlock As Boolean = True Friend Property ParsePhotoBlock As Boolean = True
<PSetting(NameOf(SiteSettings.ParseVideoBlock), NameOf(MySettings))> <PSetting(NameOf(SiteSettings.ParseVideoBlock), NameOf(MySettings))>
Friend Property ParseVideoBlock As Boolean = True Friend Property ParseVideoBlock As Boolean = True
<PSetting(NameOf(SiteSettings.ParseReelsBlock), NameOf(MySettings))>
Friend Property ParseReelsBlock As Boolean = False
<PSetting(NameOf(SiteSettings.ParseStoriesBlock), NameOf(MySettings))> <PSetting(NameOf(SiteSettings.ParseStoriesBlock), NameOf(MySettings))>
Friend Property ParseStoriesBlock As Boolean = True Friend Property ParseStoriesBlock As Boolean = True
Private ReadOnly Property MySettings As SiteSettings Private ReadOnly Property MySettings As SiteSettings
@@ -20,12 +22,14 @@ Namespace API.Facebook
MySettings = u.HostCollection.Default.Source MySettings = u.HostCollection.Default.Source
ParsePhotoBlock = u.ParsePhotoBlock ParsePhotoBlock = u.ParsePhotoBlock
ParseVideoBlock = u.ParseVideoBlock ParseVideoBlock = u.ParseVideoBlock
ParseReelsBlock = u.ParseReelsBlock
ParseStoriesBlock = u.ParseStoriesBlock ParseStoriesBlock = u.ParseStoriesBlock
End Sub End Sub
Friend Sub New(ByVal s As SiteSettings) Friend Sub New(ByVal s As SiteSettings)
MySettings = s MySettings = s
ParsePhotoBlock = s.ParsePhotoBlock.Value ParsePhotoBlock = s.ParsePhotoBlock.Value
ParseVideoBlock = s.ParseVideoBlock.Value ParseVideoBlock = s.ParseVideoBlock.Value
ParseReelsBlock = s.ParseReelsBlock.Value
ParseStoriesBlock = s.ParseStoriesBlock.Value ParseStoriesBlock = s.ParseStoriesBlock.Value
End Sub End Sub
End Class End Class

View File

@@ -7,9 +7,8 @@
' This program is distributed in the hope that it will be useful, ' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY ' but WITHOUT ANY WARRANTY
Imports SCrawler.Plugin.Attributes Imports SCrawler.Plugin.Attributes
Imports DN = SCrawler.API.Base.DeclaredNames
Namespace API.Instagram Namespace API.Instagram
Friend NotInheritable Class EditorExchangeOptions Friend NotInheritable Class EditorExchangeOptions : Inherits Base.EditorExchangeOptionsBase
#Region "Download" #Region "Download"
<PSetting(Caption:="Get timeline", ToolTip:="Download user timeline")> <PSetting(Caption:="Get timeline", ToolTip:="Download user timeline")>
Friend Property GetTimeline As Boolean Friend Property GetTimeline As Boolean
@@ -36,13 +35,13 @@ Namespace API.Instagram
#End Region #End Region
<PSetting(Caption:="Place the extracted image into the video folder")> <PSetting(Caption:="Place the extracted image into the video folder")>
Friend Property PutImageVideoFolder As Boolean Friend Property PutImageVideoFolder As Boolean
<PSetting(Address:=SettingAddress.User, Caption:=DN.UserNameChangeCaption, ToolTip:=DN.UserNameChangeToolTip)> Friend Overrides Property UserName As String
Friend Property UserName As String = String.Empty
<PSetting(Address:=SettingAddress.User, Caption:="Force update UserName", ToolTip:="Try to force update UserName if it is not found on the site")> <PSetting(Address:=SettingAddress.User, Caption:="Force update UserName", ToolTip:="Try to force update UserName if it is not found on the site")>
Friend Property ForceUpdateUserName As Boolean = False Friend Property ForceUpdateUserName As Boolean = False
<PSetting(Address:=SettingAddress.User, Caption:="Force update user information")> <PSetting(Address:=SettingAddress.User, Caption:="Force update user information")>
Friend Property ForceUpdateUserInfo As Boolean = False Friend Property ForceUpdateUserInfo As Boolean = False
Friend Sub New(ByVal u As UserData) Friend Sub New(ByVal u As UserData)
MyBase.New(u)
With u With u
GetTimeline = .GetTimeline GetTimeline = .GetTimeline
GetReels = .GetReels GetReels = .GetReels
@@ -58,7 +57,6 @@ Namespace API.Instagram
PutImageVideoFolder = .PutImageVideoFolder PutImageVideoFolder = .PutImageVideoFolder
UserName = .NameTrue(True)
ForceUpdateUserName = .ForceUpdateUserName ForceUpdateUserName = .ForceUpdateUserName
ForceUpdateUserInfo = .ForceUpdateUserInfo ForceUpdateUserInfo = .ForceUpdateUserInfo
End With End With

View File

@@ -732,9 +732,6 @@ Namespace API.Instagram
Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using
End If End If
End Sub End Sub
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
Return String.Format(UrlPatternUser, DirectCast(User, UserData).NameTrue)
End Function
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
Try Try
Dim code$ = DirectCast(User, UserData).GetPostCodeById(Media.Post.ID) Dim code$ = DirectCast(User, UserData).GetPostCodeById(Media.Post.ID)

View File

@@ -37,7 +37,6 @@ Namespace API.Instagram
Private Const Name_GetTagged_VideoPic As String = "GetTaggedData_VideoPic" Private Const Name_GetTagged_VideoPic As String = "GetTaggedData_VideoPic"
Private Const Name_PutImageVideoFolder As String = "PutImageVideoFolder" Private Const Name_PutImageVideoFolder As String = "PutImageVideoFolder"
Private Const Name_TaggedChecked As String = "TaggedChecked" Private Const Name_TaggedChecked As String = "TaggedChecked"
Private Const Name_NameTrue As String = "NameTrue"
Private Const Name_ForceUpdateUserName As String = "ForceUpdateUserName" Private Const Name_ForceUpdateUserName As String = "ForceUpdateUserName"
Private Const Name_ForceUpdateUserInfo As String = "ForceUpdateUserInfo" Private Const Name_ForceUpdateUserInfo As String = "ForceUpdateUserInfo"
#End Region #End Region
@@ -113,12 +112,6 @@ Namespace API.Instagram
Case Else : Return True Case Else : Return True
End Select End Select
End Function End Function
Protected _NameTrue As String = String.Empty
Friend ReadOnly Property NameTrue(Optional ByVal Exact As Boolean = False) As String
Get
Return If(Exact, _NameTrue, _NameTrue.IfNullOrEmpty(Name))
End Get
End Property
Private UserNameRequested As Boolean = False Private UserNameRequested As Boolean = False
Friend Property ForceUpdateUserName As Boolean = False Friend Property ForceUpdateUserName As Boolean = False
Friend Property ForceUpdateUserInfo As Boolean = False Friend Property ForceUpdateUserInfo As Boolean = False
@@ -141,7 +134,6 @@ Namespace API.Instagram
GetTaggedData = .Value(Name_GetTagged).FromXML(Of Boolean)(CBool(MySiteSettings.GetTagged.Value)) GetTaggedData = .Value(Name_GetTagged).FromXML(Of Boolean)(CBool(MySiteSettings.GetTagged.Value))
GetTaggedData_VideoPic = .Value(Name_GetTagged_VideoPic).FromXML(Of Boolean)(CBool(MySiteSettings.GetTagged_VideoPic.Value)) GetTaggedData_VideoPic = .Value(Name_GetTagged_VideoPic).FromXML(Of Boolean)(CBool(MySiteSettings.GetTagged_VideoPic.Value))
TaggedChecked = .Value(Name_TaggedChecked).FromXML(Of Boolean)(False) TaggedChecked = .Value(Name_TaggedChecked).FromXML(Of Boolean)(False)
_NameTrue = .Value(Name_NameTrue)
ForceUpdateUserName = .Value(Name_ForceUpdateUserName).FromXML(Of Boolean)(False) ForceUpdateUserName = .Value(Name_ForceUpdateUserName).FromXML(Of Boolean)(False)
ForceUpdateUserInfo = .Value(Name_ForceUpdateUserInfo).FromXML(Of Boolean)(False) ForceUpdateUserInfo = .Value(Name_ForceUpdateUserInfo).FromXML(Of Boolean)(False)
Else Else
@@ -159,7 +151,6 @@ Namespace API.Instagram
.Add(Name_GetTagged_VideoPic, GetTaggedData_VideoPic.BoolToInteger) .Add(Name_GetTagged_VideoPic, GetTaggedData_VideoPic.BoolToInteger)
.Add(Name_PutImageVideoFolder, PutImageVideoFolder.BoolToInteger) .Add(Name_PutImageVideoFolder, PutImageVideoFolder.BoolToInteger)
.Add(Name_TaggedChecked, TaggedChecked.BoolToInteger) .Add(Name_TaggedChecked, TaggedChecked.BoolToInteger)
.Add(Name_NameTrue, _NameTrue)
.Add(Name_ForceUpdateUserName, ForceUpdateUserName.BoolToInteger) .Add(Name_ForceUpdateUserName, ForceUpdateUserName.BoolToInteger)
.Add(Name_ForceUpdateUserInfo, ForceUpdateUserInfo.BoolToInteger) .Add(Name_ForceUpdateUserInfo, ForceUpdateUserInfo.BoolToInteger)
End If End If
@@ -187,7 +178,7 @@ Namespace API.Instagram
PutImageVideoFolder = .PutImageVideoFolder PutImageVideoFolder = .PutImageVideoFolder
_NameTrue = .UserName NameTrue = .UserName
ForceUpdateUserName = .ForceUpdateUserName ForceUpdateUserName = .ForceUpdateUserName
ForceUpdateUserInfo = .ForceUpdateUserInfo ForceUpdateUserInfo = .ForceUpdateUserInfo
End With End With
@@ -480,17 +471,24 @@ Namespace API.Instagram
End Try End Try
End Sub End Sub
Protected Sub ValidateExtension() Protected Sub ValidateExtension()
Dim tmpList As List(Of UserMedia) = Nothing
Try Try
Const heic$ = "heic" Const heic$ = "heic"
If _TempMediaList.Count > 0 AndAlso _TempMediaList.Exists(Function(mm) mm.File.Extension = heic) Then If _TempMediaList.Count > 0 AndAlso _TempMediaList.Exists(Function(mm) mm.File.Extension = heic) Then
Dim m As UserMedia Dim m As UserMedia
For i% = 0 To _TempMediaList.Count - 1 tmpList = New List(Of UserMedia)
m = _TempMediaList(i) tmpList.ListAddList(_TempMediaList)
_TempMediaList.Clear()
For i% = 0 To tmpList.Count - 1
m = tmpList(i)
_TempMediaList.Add(m)
If m.Type = UTypes.Picture AndAlso Not m.File.Extension.IsEmptyString AndAlso m.File.Extension = heic Then _ If m.Type = UTypes.Picture AndAlso Not m.File.Extension.IsEmptyString AndAlso m.File.Extension = heic Then _
m.File.Extension = "jpg" : _TempMediaList(i) = m m.File.Extension = "jpg" : _TempMediaList.Add(m)
Next Next
tmpList.Clear()
End If End If
Catch ex As Exception Catch ex As Exception
If tmpList.ListExists Then _TempMediaList.Clear() : _TempMediaList.ListAddList(tmpList) : tmpList.Clear()
End Try End Try
End Sub End Sub
Protected Overridable Sub UpdateResponser() Protected Overridable Sub UpdateResponser()
@@ -1212,11 +1210,8 @@ NextPageBlock:
Dim f As New SFile With {.Path = DownloadContentDefault_GetRootDir(), .Name = "ProfilePicture", .Extension = "jpg"} Dim f As New SFile With {.Path = DownloadContentDefault_GetRootDir(), .Name = "ProfilePicture", .Extension = "jpg"}
f = SFile.IndexReindex(f) f = SFile.IndexReindex(f)
If Not f.Exists Then If Not f.Exists Then
Dim profilePicture$ = .Value("profile_pic_url_hd") If SimpleDownloadAvatar(.Value("profile_pic_url_hd"), Function(ff) f).IsEmptyString Then _
If profilePicture.IsEmptyString OrElse Not GetWebFile(profilePicture, f, EDP.ReturnValue) Then SimpleDownloadAvatar(.Value("profile_pic_url"), Function(ff) f)
profilePicture = .Value("profile_pic_url")
If Not profilePicture.IsEmptyString Then GetWebFile(profilePicture, f, EDP.ReturnValue)
End If
End If End If
End With End With
End If End If
@@ -1249,11 +1244,10 @@ NextPageBlock:
If Not newName.IsEmptyString Then If Not newName.IsEmptyString Then
Dim oldName$ = NameTrue Dim oldName$ = NameTrue
If Not newName = oldName Then If Not newName = oldName Then
MyMainLOG = $"{ToStringForLog()}: username changed from '{oldName}' to '{newName}'" Dim uStr$ = $"username changed from '{oldName}' to '{newName}'"
_NameTrue = newName LogError(Nothing, uStr)
Dim descr$ = $"Username changed from '{oldName}' to '{newName}' ({Now.ToStringDate(ADateTime.Formats.BaseDateTime)})!" NameTrue = newName
descr.StringAppendLine(UserDescription) UserDescriptionUpdate(uStr, True, True, True)
UserDescription = descr
_ForceSaveUserInfo = True _ForceSaveUserInfo = True
End If End If
Return True Return True

View File

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

View File

@@ -171,12 +171,12 @@ Namespace API.Mastodon
With DirectCast(User, UserData) With DirectCast(User, UserData)
If UserRelatedToMyDomain.Value Then If UserRelatedToMyDomain.Value Then
If MyDomain.Value = .UserDomain Then If MyDomain.Value = .UserDomain Then
Return $"https://{ .UserDomain}/@{ .TrueName}" Return $"https://{ .UserDomain}/@{ .NameTrue}"
Else Else
Return $"https://{MyDomain.Value}/@{ .TrueName}@{ .UserDomain}" Return $"https://{MyDomain.Value}/@{ .NameTrue}@{ .UserDomain}"
End If End If
Else Else
Return $"https://{ .UserDomain}/@{ .TrueName}" Return $"https://{ .UserDomain}/@{ .NameTrue}"
End If End If
End With End With
End Function End Function

View File

@@ -29,7 +29,6 @@ Namespace API.Mastodon
_UserDomain = d _UserDomain = d
End Set End Set
End Property End Property
Friend Property TrueName As String = String.Empty
Private ReadOnly Property MySettings As SiteSettings Private ReadOnly Property MySettings As SiteSettings
Get Get
Return HOST.Source Return HOST.Source
@@ -52,22 +51,21 @@ Namespace API.Mastodon
Dim l$() = Name.Split("@") Dim l$() = Name.Split("@")
If l.ListExists(2) Then If l.ListExists(2) Then
_UserDomain = l(0) _UserDomain = l(0)
TrueName = l(1) NameTrue = l(1)
Else Else
_UserDomain = MySettings.MyDomain.Value _UserDomain = MySettings.MyDomain.Value
TrueName = Name NameTrue = Name
End If End If
If FriendlyName.IsEmptyString Then FriendlyName = TrueName If FriendlyName.IsEmptyString Then FriendlyName = NameTrue
End If End If
End Sub End Sub
If Loading Then If Loading Then
_UserDomain = Container.Value(Name_UserDomain) _UserDomain = Container.Value(Name_UserDomain)
TrueName = Container.Value(Name_TrueName)
obtainNames.Invoke obtainNames.Invoke
Else Else
obtainNames.Invoke obtainNames.Invoke
Container.Add(Name_UserDomain, _UserDomain) Container.Add(Name_UserDomain, _UserDomain)
Container.Add(Name_TrueName, TrueName) Container.Add(Name_TrueName, NameTrue(True))
Container.Value(Name_FriendlyName) = FriendlyName Container.Value(Name_FriendlyName) = FriendlyName
End If End If
End Sub End Sub
@@ -208,12 +206,12 @@ Namespace API.Mastodon
Dim url$ = $"https://{MyCredentials.Domain}/api/v1/accounts/lookup?acct=" Dim url$ = $"https://{MyCredentials.Domain}/api/v1/accounts/lookup?acct="
If Not UserDomain.IsEmptyString Then If Not UserDomain.IsEmptyString Then
If UserDomain = MyCredentials.Domain Then If UserDomain = MyCredentials.Domain Then
url &= $"@{TrueName}" url &= $"@{NameTrue}"
Else Else
url &= $"@{TrueName}@{UserDomain}" url &= $"@{NameTrue}@{UserDomain}"
End If End If
Else Else
url &= $"@{TrueName}" url &= $"@{NameTrue}"
End If End If
Dim r$ = Responser.GetResponse(url) Dim r$ = Responser.GetResponse(url)
If Not r.IsEmptyString Then If Not r.IsEmptyString Then

View File

@@ -36,12 +36,18 @@ Namespace API.OnlyFans
Private Const HeaderUserID As String = "User-Id" Private Const HeaderUserID As String = "User-Id"
Friend Const HeaderXBC As String = "X-Bc" Friend Const HeaderXBC As String = "X-Bc"
Friend Const HeaderAppToken As String = "App-Token" Friend Const HeaderAppToken As String = "App-Token"
Private Const AppTokenDefault As String = "33d57ade8c02dbc5a333db99ff9ae26a"
<PropertyOption(ControlText:=HeaderUserID, AllowNull:=False, IsAuth:=True), PClonable(Clone:=False)> <PropertyOption(ControlText:=HeaderUserID, AllowNull:=False, IsAuth:=True), PClonable(Clone:=False)>
Friend ReadOnly Property HH_USER_ID As PropertyValue Friend ReadOnly Property HH_USER_ID As PropertyValue
<PropertyOption(ControlText:=HeaderXBC, AllowNull:=False, IsAuth:=True), PClonable(Clone:=False)> <PropertyOption(ControlText:=HeaderXBC, AllowNull:=False, IsAuth:=True), PClonable(Clone:=False)>
Private ReadOnly Property HH_X_BC As PropertyValue Private ReadOnly Property HH_X_BC As PropertyValue
<PropertyOption(ControlText:=HeaderAppToken, AllowNull:=False, IsAuth:=True), PClonable(Clone:=False)> <PropertyOption(ControlText:=HeaderAppToken, AllowNull:=False, IsAuth:=True), PClonable(Clone:=False)>
Private ReadOnly Property HH_APP_TOKEN As PropertyValue Private ReadOnly Property HH_APP_TOKEN As PropertyValue
<PropertyUpdater(NameOf(HH_APP_TOKEN))>
Private Function UpdateAppToken() As Boolean
HH_APP_TOKEN.Value = AppTokenDefault
Return True
End Function
<PropertyOption(ControlText:=HeaderBrowser, ControlToolTip:="Can be null", AllowNull:=True, <PropertyOption(ControlText:=HeaderBrowser, ControlToolTip:="Can be null", AllowNull:=True,
InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua, IsAuth:=True), PClonable, PXML(OnlyForChecked:=True)> InheritanceName:=SettingsCLS.HEADER_DEF_sec_ch_ua, IsAuth:=True), PClonable, PXML(OnlyForChecked:=True)>
Private ReadOnly Property HH_BROWSER As PropertyValue Private ReadOnly Property HH_BROWSER As PropertyValue
@@ -225,13 +231,13 @@ Namespace API.OnlyFans
.Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.AcceptEncoding)) .Add(HttpHeaderCollection.GetSpecialHeader(MyHeaderTypes.AcceptEncoding))
HH_USER_ID = New PropertyValue(.Value(HeaderUserID), GetType(String), Sub(v) UpdateHeader(NameOf(HH_USER_ID), v)) HH_USER_ID = New PropertyValue(.Value(HeaderUserID), GetType(String), Sub(v) UpdateHeader(NameOf(HH_USER_ID), v))
HH_X_BC = New PropertyValue(.Value(HeaderXBC), GetType(String), Sub(v) UpdateHeader(NameOf(HH_X_BC), v)) HH_X_BC = New PropertyValue(.Value(HeaderXBC), GetType(String), Sub(v) UpdateHeader(NameOf(HH_X_BC), v))
HH_APP_TOKEN = New PropertyValue(.Value(HeaderAppToken), GetType(String), Sub(v) UpdateHeader(NameOf(HH_APP_TOKEN), v)) HH_APP_TOKEN = New PropertyValue(.Value(HeaderAppToken).IfNullOrEmpty(AppTokenDefault), GetType(String), Sub(v) UpdateHeader(NameOf(HH_APP_TOKEN), v))
HH_BROWSER = New PropertyValue(.Value(HeaderBrowser), GetType(String), Sub(v) UpdateHeader(NameOf(HH_BROWSER), v)) HH_BROWSER = New PropertyValue(.Value(HeaderBrowser), GetType(String), Sub(v) UpdateHeader(NameOf(HH_BROWSER), v))
End With End With
UserAgent = New PropertyValue(IIf(.UserAgentExists, .UserAgent, String.Empty), GetType(String), Sub(v) UpdateHeader(NameOf(UserAgent), v)) UserAgent = New PropertyValue(IIf(.UserAgentExists, .UserAgent, String.Empty), GetType(String), Sub(v) UpdateHeader(NameOf(UserAgent), v))
End With End With
EnableCookiesUpdate = New PropertyValue(True) EnableCookiesUpdate = New PropertyValue(False)
DownloadTimeline = New PropertyValue(True) DownloadTimeline = New PropertyValue(True)
DownloadStories = New PropertyValue(True) DownloadStories = New PropertyValue(True)
@@ -262,6 +268,15 @@ Namespace API.OnlyFans
UrlPatternUser = "https://onlyfans.com/{0}" UrlPatternUser = "https://onlyfans.com/{0}"
ImageVideoContains = "onlyfans.com" ImageVideoContains = "onlyfans.com"
End Sub End Sub
Private Const SettingsVersionCurrent As Integer = 1
Friend Overrides Sub EndInit()
If CInt(SettingsVersion.Value) < SettingsVersionCurrent Then
If CStr(HH_APP_TOKEN.Value).IsEmptyString Then HH_APP_TOKEN.Value = AppTokenDefault
EnableCookiesUpdate.Value = False
SettingsVersion.Value = SettingsVersionCurrent
End If
MyBase.EndInit()
End Sub
#End Region #End Region
#Region "GetInstance" #Region "GetInstance"
Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider
@@ -312,7 +327,7 @@ Namespace API.OnlyFans
#Region "GetUserUrl, GetUserPostUrl, UserOptions" #Region "GetUserUrl, GetUserPostUrl, UserOptions"
Friend Const UserPostPattern As String = "https://onlyfans.com/{0}/{1}" Friend Const UserPostPattern As String = "https://onlyfans.com/{0}/{1}"
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
Return String.Format(UrlPatternUser, If(User.ID.IsEmptyString, User.Name, $"u{User.ID}")) Return String.Format(UrlPatternUser, If(User.ID.IsEmptyString, User.NameTrue.IfNullOrEmpty(User.Name), $"u{User.ID}"))
End Function End Function
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
If Not Media.Post.ID.IsEmptyString Then If Not Media.Post.ID.IsEmptyString Then

View File

@@ -467,16 +467,8 @@ Namespace API.OnlyFans
Dim descr$ = j.Value("about") Dim descr$ = j.Value("about")
If Not descr.IsEmptyString Then descr = descr.Replace(brTag, String.Empty) If Not descr.IsEmptyString Then descr = descr.Replace(brTag, String.Empty)
UserDescriptionUpdate(descr) UserDescriptionUpdate(descr)
Dim a As Action(Of String) = Sub(ByVal address As String) SimpleDownloadAvatar(j.Value("avatar"))
If Not address.IsEmptyString Then SimpleDownloadAvatar(j.Value("header"))
Dim f As SFile = address
f.Separator = "\"
f.Path = DownloadContentDefault_GetRootDir()
If Not f.Exists Then GetWebFile(address, f, EDP.None)
End If
End Sub
a.Invoke(j.Value("avatar"))
a.Invoke(j.Value("header"))
End If End If
End Using End Using
End If End If

View File

@@ -7,11 +7,18 @@
' This program is distributed in the hope that it will be useful, ' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY ' but WITHOUT ANY WARRANTY
Imports System.Globalization Imports System.Globalization
Imports System.Text.RegularExpressions
Imports PersonalUtilities.Tools.Web.Clients Imports PersonalUtilities.Tools.Web.Clients
Imports PersonalUtilities.Functions.RegularExpressions
Namespace API.Pinterest Namespace API.Pinterest
Friend Module Declarations Friend Module Declarations
Friend ReadOnly DateProvider As ADateTime = GetDateProvider() Friend ReadOnly DateProvider As ADateTime = GetDateProvider()
Friend ReadOnly PwsHeader As New HttpHeader("x-pinterest-pws-handler", "www/[username]/pins.js") Friend ReadOnly PwsHeader As New HttpHeader("x-pinterest-pws-handler", "www/[username]/pins.js")
Friend ReadOnly GdlUrlPattern As RParams = RParams.DM(Base.GDL.GDLBatch.UrlLibStart.Replace("[", "\[").Replace("]", "\]") &
"([^""]+?)""(GET [^""]+)""", 0, EDP.ReturnValue)
Friend ReadOnly SubBoardRegEx As RParams = RParams.DMS("\[pinterest\]\[debug\] Using PinterestSectionExtractor for '[^']+id:(\d+)'", 1,
RegexOptions.IgnoreCase, EDP.ReturnValue)
Friend ReadOnly BoardInfoRootNode As String() = {"resource_response", "data"}
Private Function GetDateProvider() As ADateTime Private Function GetDateProvider() As ADateTime
Dim n As DateTimeFormatInfo = CultureInfo.GetCultureInfo("en-us").DateTimeFormat.Clone Dim n As DateTimeFormatInfo = CultureInfo.GetCultureInfo("en-us").DateTimeFormat.Clone
n.FullDateTimePattern = "ddd dd MMM yyyy HH:mm:ss" n.FullDateTimePattern = "ddd dd MMM yyyy HH:mm:ss"

View File

@@ -0,0 +1,20 @@
' Copyright (C) Andy https://github.com/AAndyProgram
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports SCrawler.Plugin.Attributes
Namespace API.Pinterest
Friend Class EditorExchangeOptions
<PSetting(Caption:="Get Sub-Boards", ToolTip:="Extract the Sub-Boards from the boards and download them")>
Friend Property ExtractSubBoards As Boolean = True
Friend Sub New(ByVal u As UserData)
ExtractSubBoards = u.ExtractSubBoards
End Sub
Friend Sub New()
End Sub
End Class
End Namespace

View File

@@ -11,7 +11,7 @@ Imports SCrawler.Plugin
Imports SCrawler.Plugin.Attributes Imports SCrawler.Plugin.Attributes
Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Functions.RegularExpressions
Namespace API.Pinterest Namespace API.Pinterest
<Manifest("AndyProgram_Pinterest"), SavedPosts, SeparatedTasks> <Manifest("AndyProgram_Pinterest"), SavedPosts, SeparatedTasks, SpecialForm(False)>
Friend Class SiteSettings : Inherits SiteSettingsBase Friend Class SiteSettings : Inherits SiteSettingsBase
#Region "Declarations" #Region "Declarations"
<PropertyOption(ControlText:=DeclaredNames.ConcurrentDownloadsCaption, <PropertyOption(ControlText:=DeclaredNames.ConcurrentDownloadsCaption,
@@ -30,7 +30,7 @@ Namespace API.Pinterest
MyConcurrentDownloadsProvider = New ConcurrentDownloadsProvider MyConcurrentDownloadsProvider = New ConcurrentDownloadsProvider
CheckNetscapeCookiesOnEndInit = True CheckNetscapeCookiesOnEndInit = True
UseNetscapeCookies = True UseNetscapeCookies = True
UserRegex = RParams.DMS("https?://w{0,3}.?[^/]*?.?pinterest.com/([^/]+)/?(?(_)|([^/]*))", 0, RegexReturn.ListByMatch, EDP.ReturnValue) UserRegex = RParams.DMS("https?://w{0,3}.?[^/]*?.?pinterest.com/([^/]+)/?(?(_)|([^/]*))/?([^/\?]*)", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
End Sub End Sub
#End Region #End Region
#Region "GetInstance, Available" #Region "GetInstance, Available"
@@ -41,13 +41,14 @@ Namespace API.Pinterest
Return Settings.GalleryDLFile.Exists And (Not What = ISiteSettings.Download.SavedPosts OrElse ACheck(SavedPostsUserName.Value)) Return Settings.GalleryDLFile.Exists And (Not What = ISiteSettings.Download.SavedPosts OrElse ACheck(SavedPostsUserName.Value))
End Function End Function
#End Region #End Region
#Region "IsMyUser, IsMyImageVideo, GetUserUrl, GetUserPostUrl" #Region "IsMyUser, IsMyImageVideo, GetUserUrl, GetUserPostUrl, UserOptions"
Friend Overrides Function IsMyUser(ByVal UserURL As String) As ExchangeOptions Friend Overrides Function IsMyUser(ByVal UserURL As String) As ExchangeOptions
If Not UserURL.IsEmptyString Then If Not UserURL.IsEmptyString Then
Dim l As List(Of String) = RegexReplace(UserURL, UserRegex) Dim l As List(Of String) = RegexReplace(UserURL, UserRegex)
If l.ListExists(3) Then If l.ListExists(3) Then
Dim n$ = l(1) Dim n$ = l(1)
If Not l(2).IsEmptyString Then n &= $"@{l(2)}" If Not l(2).IsEmptyString Then n &= $"@{l(2)}"
If l.Count > 3 AndAlso Not l(3).IsEmptyString Then n &= $"@{l(3)}"
Return New ExchangeOptions(Site, n) With {.Exists = True} Return New ExchangeOptions(Site, n) With {.Exists = True}
End If End If
End If End If
@@ -71,6 +72,12 @@ Namespace API.Pinterest
Return String.Empty Return String.Empty
End If End If
End Function End Function
Friend Overrides Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean)
If Options Is Nothing Then Options = New EditorExchangeOptions
If OpenForm Then
Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using
End If
End Sub
#End Region #End Region
End Class End Class
End Namespace End Namespace

View File

@@ -7,10 +7,12 @@
' This program is distributed in the hope that it will be useful, ' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY ' but WITHOUT ANY WARRANTY
Imports System.Threading Imports System.Threading
Imports System.Text.RegularExpressions
Imports SCrawler.API.Base Imports SCrawler.API.Base
Imports SCrawler.API.Base.GDL Imports SCrawler.API.Base.GDL
Imports SCrawler.API.YouTube.Objects Imports SCrawler.API.YouTube.Objects
Imports PersonalUtilities.Functions.XML Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.RegularExpressions
Imports PersonalUtilities.Tools.Web.Documents.JSON Imports PersonalUtilities.Tools.Web.Documents.JSON
Namespace API.Pinterest Namespace API.Pinterest
Friend Class UserData : Inherits UserDataBase Friend Class UserData : Inherits UserDataBase
@@ -18,6 +20,8 @@ Namespace API.Pinterest
Private Const Name_IsUser As String = "IsUser" Private Const Name_IsUser As String = "IsUser"
Private Const Name_TrueUserName As String = "TrueUserName" Private Const Name_TrueUserName As String = "TrueUserName"
Private Const Name_TrueBoardName As String = "TrueBoardName" Private Const Name_TrueBoardName As String = "TrueBoardName"
Private Const Name_ExtractSubBoards As String = "ExtractSubBoards"
Private Const Name_IsSubBoard As String = "IsSubBoard"
#End Region #End Region
#Region "Structures" #Region "Structures"
Private Structure BoardInfo Private Structure BoardInfo
@@ -38,6 +42,8 @@ Namespace API.Pinterest
Friend Property TrueUserName As String Friend Property TrueUserName As String
Friend Property TrueBoardName As String Friend Property TrueBoardName As String
Friend Property IsUser_NB As Boolean Friend Property IsUser_NB As Boolean
Private Property IsSubBoard As Boolean = False
Friend Property ExtractSubBoards As Boolean = True
Private Const BoardLabelName As String = "Board" Private Const BoardLabelName As String = "Board"
Friend Overrides ReadOnly Property SpecialLabels As IEnumerable(Of String) Friend Overrides ReadOnly Property SpecialLabels As IEnumerable(Of String)
Get Get
@@ -45,14 +51,18 @@ Namespace API.Pinterest
End Get End Get
End Property End Property
#End Region #End Region
#Region "Load" #Region "Load, Exchange"
Private Function ReconfUserName() As Boolean Private Function ReconfUserName() As Boolean
If TrueUserName.IsEmptyString Then If TrueUserName.IsEmptyString Then
Dim n$() = Name.Split("@") Dim n$() = Name.Split("@")
If n.ListExists Then If n.ListExists Then
TrueUserName = n(0) TrueUserName = n(0)
IsUser_NB = True IsUser_NB = True
If n.Length > 1 Then TrueBoardName = n(1) : IsUser_NB = False If n.Length > 1 Then
TrueBoardName = n(1)
If n.Length > 2 AndAlso Not n(2).IsEmptyString Then TrueBoardName &= $"/{n(2)}" : IsSubBoard = True
IsUser_NB = False
End If
If Not IsSavedPosts And Not IsSingleObjectDownload Then If Not IsSavedPosts And Not IsSingleObjectDownload Then
Dim l$ = IIf(IsUser_NB, UserLabelName, BoardLabelName) Dim l$ = IIf(IsUser_NB, UserLabelName, BoardLabelName)
Settings.Labels.Add(l) Settings.Labels.Add(l)
@@ -70,15 +80,25 @@ Namespace API.Pinterest
TrueUserName = .Value(Name_TrueUserName) TrueUserName = .Value(Name_TrueUserName)
TrueBoardName = .Value(Name_TrueBoardName) TrueBoardName = .Value(Name_TrueBoardName)
IsUser_NB = .Value(Name_IsUser).FromXML(Of Boolean)(False) IsUser_NB = .Value(Name_IsUser).FromXML(Of Boolean)(False)
ExtractSubBoards = .Value(Name_ExtractSubBoards).FromXML(Of Boolean)(True)
IsSubBoard = .Value(Name_IsSubBoard).FromXML(Of Boolean)(False)
ReconfUserName() ReconfUserName()
Else Else
If ReconfUserName() Then .Value(Name_LabelsName) = LabelsString If ReconfUserName() Then .Value(Name_LabelsName) = LabelsString
.Add(Name_TrueUserName, TrueUserName) .Add(Name_TrueUserName, TrueUserName)
.Add(Name_TrueBoardName, TrueBoardName) .Add(Name_TrueBoardName, TrueBoardName)
.Add(Name_IsUser, IsUser_NB.BoolToInteger) .Add(Name_IsUser, IsUser_NB.BoolToInteger)
.Add(Name_ExtractSubBoards, ExtractSubBoards.BoolToInteger)
.Add(Name_IsSubBoard, IsSubBoard.BoolToInteger)
End If End If
End With End With
End Sub End Sub
Friend Overrides Function ExchangeOptionsGet() As Object
Return New EditorExchangeOptions(Me)
End Function
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
If Not Obj Is Nothing AndAlso TypeOf Obj Is EditorExchangeOptions Then ExtractSubBoards = DirectCast(Obj, EditorExchangeOptions).ExtractSubBoards
End Sub
#End Region #End Region
#Region "Download overrides" #Region "Download overrides"
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
@@ -125,6 +145,19 @@ Namespace API.Pinterest
End Sub End Sub
#End Region #End Region
#Region "Get boards, images" #Region "Get boards, images"
Private Function GetBoardInfo(ByVal e As EContainer) As BoardInfo
If Not e Is Nothing Then
Dim b As New BoardInfo With {
.URL = e.Value("url"),
.Title = TitleHtmlConverter(e.Value("name")).IfNullOrEmpty(TitleHtmlConverter(e.Value("title"))),
.ID = e.Value("id")
}
If Not b.URL.IsEmptyString Then b.URL = $"https://www.pinterest.com/{b.URL.StringTrimStart("/").StringTrimEnd("/")}/"
Return b
Else
Return Nothing
End If
End Function
Private Function GetBoards(ByVal Token As CancellationToken) As List(Of BoardInfo) Private Function GetBoards(ByVal Token As CancellationToken) As List(Of BoardInfo)
Dim URL$ = $"https://www.pinterest.com/{TrueUserName}/" Dim URL$ = $"https://www.pinterest.com/{TrueUserName}/"
Try Try
@@ -132,9 +165,9 @@ Namespace API.Pinterest
Dim b As BoardInfo Dim b As BoardInfo
Dim r$ Dim r$
Dim j As EContainer, jj As EContainer Dim j As EContainer, jj As EContainer
Dim rootNode$() = {"resource_response", "data"}
Dim jErr As New ErrorsDescriber(EDP.SendToLog + EDP.ReturnValue) Dim jErr As New ErrorsDescriber(EDP.SendToLog + EDP.ReturnValue)
Dim urls As List(Of String) = GetDataFromGalleryDL(URL, True, Token) Dim urls As New List(Of String)
urls.ListAddList(GetDataFromGalleryDL(URL, True, Token), LNC)
If urls.ListExists Then urls.RemoveAll(Function(__url) Not __url.Contains("BoardsResource/get/")) If urls.ListExists Then urls.RemoveAll(Function(__url) Not __url.Contains("BoardsResource/get/"))
If urls.ListExists Then If urls.ListExists Then
ProgressPre.ChangeMax(urls.Count) ProgressPre.ChangeMax(urls.Count)
@@ -145,17 +178,10 @@ Namespace API.Pinterest
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
j = JsonDocument.Parse(r, jErr) j = JsonDocument.Parse(r, jErr)
If Not j Is Nothing Then If Not j Is Nothing Then
If If(j(rootNode)?.Count, 0) > 0 Then If If(j(BoardInfoRootNode)?.Count, 0) > 0 Then
For Each jj In j(rootNode) For Each jj In j(BoardInfoRootNode)
b = New BoardInfo With { b = GetBoardInfo(jj)
.URL = jj.Value("url"), If Not b.URL.IsEmptyString Then boards.Add(b)
.Title = TitleHtmlConverter(jj.Value("name")),
.ID = jj.Value("id")
}
If Not b.URL.IsEmptyString Then
b.URL = $"https://www.pinterest.com/{b.URL.StringTrimStart("/").StringTrimEnd("/")}/"
boards.Add(b)
End If
Next Next
End If End If
j.Dispose() j.Dispose()
@@ -170,95 +196,156 @@ Namespace API.Pinterest
End Try End Try
End Function End Function
Private Sub DownloadBoardImages(ByRef Board As BoardInfo, ByVal Token As CancellationToken) Private Sub DownloadBoardImages(ByRef Board As BoardInfo, ByVal Token As CancellationToken)
Dim bUrl$ = String.Empty Dim bUrl As GDLURL = Nothing
Try Try
Dim r$ Dim r$
Dim j As EContainer, jj As EContainer Dim j As EContainer, jj As EContainer
Dim u As UserMedia Dim u As UserMedia
Dim folder$ = If(IsUser_NB, Board.Title.IfNullOrEmpty(Board.ID), String.Empty) Dim __getBoardTitle As Func(Of BoardInfo, String) = Function(__board) __board.Title.IfNullOrEmpty(__board.ID)
Dim folderDef$ = If(IsUser_NB, __getBoardTitle(Board), String.Empty)
Dim titleExists As Boolean = Not Board.Title.IsEmptyString Dim titleExists As Boolean = Not Board.Title.IsEmptyString
Dim i% = -1 Dim i% = -1
Dim jErr As New ErrorsDescriber(EDP.SendToLog + EDP.ReturnValue) Dim jErr As New ErrorsDescriber(EDP.SendToLog + EDP.ReturnValue)
Dim rootNode$() = {"resource_response", "data"} Dim rErr As New ErrorsDescriber(EDP.ReturnValue)
Dim images As List(Of Sizes) Dim images As List(Of Sizes)
Dim imgSelector As Func(Of EContainer, Sizes) = Function(img) New Sizes(img.Value("width"), img.Value("url")) Dim imgSelector As Func(Of EContainer, Sizes) = Function(img) New Sizes(img.Value("width"), img.Value("url"))
Dim fullData As Predicate(Of EContainer) = Function(e) e.Count > 5 Dim fullData As Predicate(Of EContainer) = Function(e) e.Count > 5
Dim l As List(Of String) = GetDataFromGalleryDL(Board.URL, False, Token) Dim subBoard As BoardInfo = Nothing
If l.ListExists Then l.RemoveAll(Function(ll) Not ll.Contains("BoardFeedResource/get/")) Dim subBoardAppender As Func(Of String) = Function() _
If(Not __getBoardTitle(subBoard).IsEmptyString,
$"{IIf(folderDef.IsEmptyString, String.Empty, "\")}{__getBoardTitle(subBoard)}",
String.Empty)
Dim __getSubBoard As Func(Of Boolean) = Function() ExtractSubBoards Or (IsSubBoard And i = -1)
Dim sbCount% = 0
Dim __getBoardInfo As Action(Of GDLURL) = Sub(ByVal sb As GDLURL)
sbCount += 1
r = Responser.GetResponse(sb.URL,, rErr)
If Not r.IsEmptyString Then
Using jsb As EContainer = JsonDocument.Parse(r, jErr)
If jsb.ListExists Then subBoard = GetBoardInfo(jsb(BoardInfoRootNode)) : Exit Sub
End Using
End If
subBoard = Nothing
End Sub
Dim l As List(Of GDLURL) = GetDataFromGalleryDL(Board.URL, False, Token)
If l.ListExists Then l.RemoveAll(Function(ll) ll.URL.IsEmptyString)
If l.ListExists Then If l.ListExists Then
Responser.Headers.Add(PwsHeader) Responser.Headers.Add(PwsHeader)
ProgressPre.ChangeMax(l.Count) ProgressPre.ChangeMax(l.Count)
For Each bUrl In l For Each bUrl In l
ProgressPre.Perform() ProgressPre.Perform()
ThrowAny(Token) ThrowAny(Token)
r = Responser.GetResponse(bUrl,, EDP.ReturnValue)
If Not r.IsEmptyString Then
j = JsonDocument.Parse(r, jErr)
If Not j Is Nothing Then
If If(j(rootNode)?.Count, 0) > 0 Then
ProgressPre.ChangeMax(j(rootNode).Count)
For Each jj In j(rootNode)
ProgressPre.Perform()
With jj
If .Contains("images") Then
images = .Item("images").Select(imgSelector).ToList
If images.Count > 0 Then
images.Sort()
i += 1
u = New UserMedia(images(0).Data) With {
.Post = New UserPost(jj.Value("id"), AConvert(Of Date)(jj.Value("created_at"), DateProvider, Nothing)),
.Type = UserMedia.Types.Picture,
.SpecialFolder = folder
}
If i = 0 Then
If Board.Title.IsEmptyString Or Board.ID.IsEmptyString Then
Board.Title = TitleHtmlConverter(.Value({"board"}, "name"))
Board.ID = .Value({"board"}, "id")
End If
Board.UserID = .Value({"board", "owner"}, "id")
Board.UserTitle = TitleHtmlConverter(.Value({"board", "owner"}, "full_name"))
If Not titleExists And IsUser_NB Then
If Not Board.Title.IsEmptyString Then
folder = Board.Title
ElseIf Not Board.ID.IsEmptyString Then
folder = Board.ID
End If
u.SpecialFolder = folder
End If
End If
If Not u.URL.IsEmptyString Then If bUrl.URL.Contains("BoardFeedResource/get/") Or (bUrl.URL.Contains("BoardSectionPinsResource/get/") And (ExtractSubBoards Or (IsSubBoard And sbCount = 1))) Then
If u.Post.Date.HasValue Then r = Responser.GetResponse(bUrl.URL,, rErr)
Select Case CheckDatesLimit(u.Post.Date.Value, Nothing) If Not r.IsEmptyString Then
Case DateResult.Skip : _TempPostsList.ListAddValue(u.Post.ID, LNC) : Continue For j = JsonDocument.Parse(r, jErr)
Case DateResult.Exit : Exit Sub If Not j Is Nothing Then
End Select If If(j(BoardInfoRootNode)?.Count, 0) > 0 Then
ProgressPre.ChangeMax(j(BoardInfoRootNode).Count)
For Each jj In j(BoardInfoRootNode)
ProgressPre.Perform()
With jj
If .Contains("images") Then
images = .Item("images").Select(imgSelector).ToList
If images.Count > 0 Then
images.Sort()
i += 1
u = New UserMedia(images(0).Data) With {
.Post = New UserPost(jj.Value("id"), AConvert(Of Date)(jj.Value("created_at"), DateProvider, Nothing)),
.Type = UserMedia.Types.Picture,
.SpecialFolder = folderDef & subBoardAppender.Invoke
}
If i = 0 Then
If Board.Title.IsEmptyString Or Board.ID.IsEmptyString Then
Board.Title = TitleHtmlConverter(.Value({"board"}, "name"))
Board.ID = .Value({"board"}, "id")
End If
Board.UserID = .Value({"board", "owner"}, "id")
Board.UserTitle = TitleHtmlConverter(.Value({"board", "owner"}, "full_name"))
If Not titleExists And IsUser_NB Then
folderDef = Board.Title.IfNullOrEmpty(Board.ID).IfNullOrEmpty(folderDef)
u.SpecialFolder = folderDef & subBoardAppender.Invoke
End If
End If End If
If Not _TempPostsList.Contains(u.Post.ID) Then
_TempPostsList.ListAddValue(u.Post.ID, LNC) If Not u.URL.IsEmptyString Then
_TempMediaList.ListAddValue(u, LNC) If u.Post.Date.HasValue Then
Else Select Case CheckDatesLimit(u.Post.Date.Value, Nothing)
Exit For Case DateResult.Skip : _TempPostsList.ListAddValue(u.Post.ID, LNC) : Continue For
Case DateResult.Exit : Exit Sub
End Select
End If
If Not _TempPostsList.Contains(u.Post.ID) Then
_TempPostsList.ListAddValue(u.Post.ID, LNC)
_TempMediaList.ListAddValue(u, LNC)
Else
Exit For
End If
End If End If
End If End If
End If End If
End If End With
End With Next
Next End If
j.Dispose()
End If End If
j.Dispose() End If
ElseIf bUrl.URL.Contains("BoardSectionResource/get/") And (ExtractSubBoards Or (IsSubBoard And i = -1)) Then
__getBoardInfo(bUrl)
If IsSubBoard And i = -1 And Board.Title.IsEmptyString Then
Board.Title = subBoard.Title
If Board.ID.IsEmptyString Then Board.ID = subBoard.ID
subBoard = Nothing
folderDef = String.Empty
End If End If
End If End If
Next Next
End If End If
Catch ex As Exception Catch ex As Exception
ProcessException(ex, Token, $"data (gallery-dl images) downloading error [{bUrl}]") ProcessException(ex, Token, $"data (gallery-dl images) downloading error [{bUrl.URL}]")
Finally Finally
Responser.Headers.Remove(PwsHeader) Responser.Headers.Remove(PwsHeader)
End Try End Try
End Sub End Sub
#End Region #End Region
#Region "Gallery-DL Support" #Region "Gallery-DL Support"
Private Structure GDLURL : Implements IRegExCreator
Friend URL As String
Friend BoardId As String
Public Shared Widening Operator CType(ByVal u As String) As GDLURL
Return New GDLURL With {.URL = u}
End Operator
Public Shared Widening Operator CType(ByVal u As GDLURL) As String
Return u.URL
End Operator
Private Function CreateFromArray(ByVal ParamsArray() As String) As Object Implements IRegExCreator.CreateFromArray
If ParamsArray.ListExists(2) Then
Dim u$ = ParamsArray(0).StringTrim.StringTrimEnd("/"), u2$
If Not u.IsEmptyString Then
u2 = ParamsArray(1).StringTrim
If Not u2.IsEmptyString AndAlso u2.StartsWith("GET", StringComparison.OrdinalIgnoreCase) Then
u2 = u2.Remove(0, 3).StringTrim.StringTrimStart("/")
If Not u2.IsEmptyString Then URL = $"{u}/{u2}"
End If
End If
End If
Return Me
End Function
Public Shared Operator =(ByVal x As GDLURL, ByVal y As GDLURL) As Boolean
Return x.URL = y.URL
End Operator
Public Shared Operator <>(ByVal x As GDLURL, ByVal y As GDLURL) As Boolean
Return Not x.URL = y.URL
End Operator
Public Overrides Function ToString() As String
Return URL
End Function
Public Overrides Function Equals(ByVal Obj As Object) As Boolean
Return URL = CType(Obj, String)
End Function
End Structure
Private Class GDLBatch : Inherits GDL.GDLBatch Private Class GDLBatch : Inherits GDL.GDLBatch
Private ReadOnly Property Source As UserData Private ReadOnly Property Source As UserData
Private ReadOnly IsBoardsRequested As Boolean Private ReadOnly IsBoardsRequested As Boolean
@@ -289,14 +376,30 @@ Namespace API.Pinterest
End If End If
End Function End Function
End Class End Class
Private Function GetDataFromGalleryDL(ByVal URL As String, ByVal IsBoardsRequested As Boolean, ByVal Token As CancellationToken) As List(Of String) Private Function GetDataFromGalleryDL(ByVal URL As String, ByVal IsBoardsRequested As Boolean, ByVal Token As CancellationToken) As List(Of GDLURL)
Dim command$ = $"""{Settings.GalleryDLFile.File}"" --verbose --simulate " Dim command$ = $"""{Settings.GalleryDLFile.File}"" --verbose --simulate "
Try Try
If Not URL.IsEmptyString Then If Not URL.IsEmptyString Then
Dim urls As New List(Of GDLURL)
Dim u As GDLURL
Dim s$ = String.Empty
If MySettings.CookiesNetscapeFile.Exists Then command &= $"--cookies ""{MySettings.CookiesNetscapeFile}"" " If MySettings.CookiesNetscapeFile.Exists Then command &= $"--cookies ""{MySettings.CookiesNetscapeFile}"" "
command &= URL command &= URL
Using batch As New GDLBatch(Me, IsBoardsRequested, Token) Using batch As New GDLBatch(Me, IsBoardsRequested, Token)
Return GetUrlsFromGalleryDl(batch, command) With batch
.Execute(command)
If .ErrorOutputData.Count > 0 Then
For Each eValue$ In .ErrorOutputData
s = CStr(RegexReplace(eValue, SubBoardRegEx)).IfNullOrEmpty(s)
u = RegexFields(Of GDLURL)(eValue, {GdlUrlPattern}, {1, 2}, EDP.ReturnValue).ListIfNothing.FirstOrDefault
If Not u.URL.IsEmptyString Then
If Not s.IsEmptyString Then u.BoardId = s
urls.Add(u)
End If
Next
Return urls
End If
End With
End Using End Using
End If End If
Return Nothing Return Nothing

View File

@@ -36,11 +36,12 @@ Namespace API.PornHub
Friend ReadOnly Regex_Gif_UrlName As RParams = RParams.DMS("""name"":.*?""([^""]*)""[^\}]+?""contentUrl"":.*?""([^""]+)""", 0, RegexReturn.ListByMatch, EDP.ReturnValue) Friend ReadOnly Regex_Gif_UrlName As RParams = RParams.DMS("""name"":.*?""([^""]*)""[^\}]+?""contentUrl"":.*?""([^""]+)""", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
#End Region #End Region
#Region "Declarations photo" #Region "Declarations photo"
Friend ReadOnly Regex_Photo_ModelHub_PhotoBlocks As RParams = RParams.DM("var PHOTOS_ARRAY_(\d+) = \{[\r\n\s]*?(urls:.*?\[[^]]*\])", 0, RegexReturn.List, EDP.ReturnValue)
Friend ReadOnly Regex_Photo_PornHub_PhotoBlocks As RParams = RParams.DM("photoAlbumListContainer[\r\n\s\S]+?title=""([^""]+)""[\r\n\s\S]+?a href=""(/album/\d+)""", 0, RegexReturn.List) Friend ReadOnly Regex_Photo_PornHub_PhotoBlocks As RParams = RParams.DM("photoAlbumListContainer[\r\n\s\S]+?title=""([^""]+)""[\r\n\s\S]+?a href=""(/album/\d+)""", 0, RegexReturn.List)
Friend ReadOnly Regex_Photo_PornHub_AlbumPhotoArr As RParams = RParams.DMS("\<a href=""(/photo/\d+)""", 1, RegexReturn.List, EDP.ReturnValue, Friend ReadOnly Regex_Photo_PornHub_PhotoBlocks2 As RParams = RParams.DM("albumInfoTitle"" href=""([^""]+)""\>([^\<]+)", 0, RegexReturn.List)
Friend ReadOnly Regex_Photo_PornHub_AlbumPhotoArr As RParams = RParams.DMS("href=""(/photo/\d+)""", 1, RegexReturn.List, EDP.ReturnValue,
CType(Function(Input$) If(Input.IsEmptyString, String.Empty, $"https://www.pornhub.com{Input.Trim}"), Func(Of String, String))) CType(Function(Input$) If(Input.IsEmptyString, String.Empty, $"https://www.pornhub.com{Input.Trim}"), Func(Of String, String)))
Friend ReadOnly Regex_Photo_PornHub_SinglePhoto As RParams = RParams.DMS("(?<!thumbImage.+?)<img src=""(https://[^""]+\d+[^""]+)""", 1, EDP.ReturnValue) Friend ReadOnly Regex_Photo_PornHub_SinglePhoto As RParams = RParams.DM("data-image=""([^""]+)""\s*src=""([^""]+)""", 0, RegexReturn.ListByMatch, EDP.ReturnValue)
Friend ReadOnly Regex_Photo_PornHub_SinglePhoto2 As RParams = RParams.DMS("image:src"" content=""([^""]+)""", 1, EDP.ReturnValue)
Friend ReadOnly Regex_Photo_File As RParams = RParams.DM("\d+\.[\w]{3,4}", 0, EDP.ReturnValue) Friend ReadOnly Regex_Photo_File As RParams = RParams.DM("\d+\.[\w]{3,4}", 0, EDP.ReturnValue)
#End Region #End Region
End Module End Module

View File

@@ -29,10 +29,6 @@ Namespace API.PornHub
Friend ReadOnly Property DownloadGifs As PropertyValue Friend ReadOnly Property DownloadGifs As PropertyValue
<PropertyOption(ControlText:="Download GIFs as mp4", ControlToolTip:="Download gifs in 'mp4' format instead of native 'webm'"), PXML, PClonable> <PropertyOption(ControlText:="Download GIFs as mp4", ControlToolTip:="Download gifs in 'mp4' format instead of native 'webm'"), PXML, PClonable>
Friend ReadOnly Property DownloadGifsAsMp4 As PropertyValue Friend ReadOnly Property DownloadGifsAsMp4 As PropertyValue
<PropertyOption(ControlText:="Photo ModelHub only",
ControlToolTip:="Download photo only from ModelHub. Prornstar photos hosted on PornHub itself will not be downloaded." & vbCr &
"Attention! Downloading photos hosted on PornHub is a very heavy job."), PXML, PClonable>
Friend ReadOnly Property DownloadPhotoOnlyFromModelHub As PropertyValue
<PropertyOption(ControlText:=DeclaredNames.SavedPostsUserNameCaption, ControlToolTip:=DeclaredNames.SavedPostsUserNameToolTip), PXML, PClonable(Clone:=False)> <PropertyOption(ControlText:=DeclaredNames.SavedPostsUserNameCaption, ControlToolTip:=DeclaredNames.SavedPostsUserNameToolTip), PXML, PClonable(Clone:=False)>
Friend ReadOnly Property SavedPostsUserName As PropertyValue Friend ReadOnly Property SavedPostsUserName As PropertyValue
#End Region #End Region
@@ -48,7 +44,6 @@ Namespace API.PornHub
DownloadFavorite = New PropertyValue(False) DownloadFavorite = New PropertyValue(False)
DownloadGifsAsMp4 = New PropertyValue(True) DownloadGifsAsMp4 = New PropertyValue(True)
DownloadGifs = New PropertyValue(CInt(CheckState.Indeterminate), GetType(Integer)) DownloadGifs = New PropertyValue(CInt(CheckState.Indeterminate), GetType(Integer))
DownloadPhotoOnlyFromModelHub = New PropertyValue(True)
SavedPostsUserName = New PropertyValue(String.Empty, GetType(String)) SavedPostsUserName = New PropertyValue(String.Empty, GetType(String))
_SubscriptionsAllowed = True _SubscriptionsAllowed = True

View File

@@ -20,15 +20,12 @@ Namespace API.PornHub
#Region "Declarations" #Region "Declarations"
#Region "XML names" #Region "XML names"
Private Const Name_PersonType As String = "PersonType" Private Const Name_PersonType As String = "PersonType"
Private Const Name_NameTrue As String = "NameTrue"
Private Const Name_PhotoPageModel As String = "PhotoPageModel"
Private Const Name_DownloadUHD As String = "DownloadUHD" Private Const Name_DownloadUHD As String = "DownloadUHD"
Private Const Name_DownloadUploaded As String = "DownloadUploaded" Private Const Name_DownloadUploaded As String = "DownloadUploaded"
Private Const Name_DownloadTagged As String = "DownloadTagged" Private Const Name_DownloadTagged As String = "DownloadTagged"
Private Const Name_DownloadPrivate As String = "DownloadPrivate" Private Const Name_DownloadPrivate As String = "DownloadPrivate"
Private Const Name_DownloadFavorite As String = "DownloadFavorite" Private Const Name_DownloadFavorite As String = "DownloadFavorite"
Private Const Name_DownloadGifs As String = "DownloadGifs" Private Const Name_DownloadGifs As String = "DownloadGifs"
Private Const Name_DownloadPhotoOnlyFromModelHub As String = "DownloadPhotoOnlyFromModelHub"
#End Region #End Region
#Region "Structures" #Region "Structures"
Private Structure FlashVar : Implements IRegExCreator Private Structure FlashVar : Implements IRegExCreator
@@ -98,11 +95,6 @@ Namespace API.PornHub
End Structure End Structure
#End Region #End Region
#Region "Enums" #Region "Enums"
Private Enum PhotoPageModels As Integer
Undefined = 0
PornHubPage = 1
ModelHubPage = 2
End Enum
Private Enum VideoTypes Private Enum VideoTypes
Undefined Undefined
Uploaded Uploaded
@@ -121,7 +113,6 @@ Namespace API.PornHub
#End Region #End Region
#Region "Person" #Region "Person"
Friend Property PersonType As String Friend Property PersonType As String
Friend Property NameTrue As String
Friend Overrides Property FriendlyName As String Friend Overrides Property FriendlyName As String
Get Get
If _FriendlyName.IsEmptyString Then Return NameTrue Else Return _FriendlyName If _FriendlyName.IsEmptyString Then Return NameTrue Else Return _FriendlyName
@@ -137,14 +128,12 @@ Namespace API.PornHub
Return IsUser Or SiteMode = SiteModes.Playlists Return IsUser Or SiteMode = SiteModes.Playlists
End Get End Get
End Property End Property
Private Property PhotoPageModel As PhotoPageModels = PhotoPageModels.Undefined
Friend Property DownloadUHD As Boolean = False Friend Property DownloadUHD As Boolean = False
Friend Property DownloadUploaded As Boolean = True Friend Property DownloadUploaded As Boolean = True
Friend Property DownloadTagged As Boolean = False Friend Property DownloadTagged As Boolean = False
Friend Property DownloadPrivate As Boolean = False Friend Property DownloadPrivate As Boolean = False
Friend Property DownloadFavorite As Boolean = False Friend Property DownloadFavorite As Boolean = False
Friend Property DownloadGifs As Boolean Friend Property DownloadGifs As Boolean
Friend Property DownloadPhotoOnlyFromModelHub As Boolean = True
Friend Overrides ReadOnly Property IsUser As Boolean Friend Overrides ReadOnly Property IsUser As Boolean
Get Get
Return SiteMode = SiteModes.User Return SiteMode = SiteModes.User
@@ -182,7 +171,6 @@ Namespace API.PornHub
DownloadPrivate = .DownloadPrivate DownloadPrivate = .DownloadPrivate
DownloadFavorite = .DownloadFavorite DownloadFavorite = .DownloadFavorite
DownloadGifs = .DownloadGifs DownloadGifs = .DownloadGifs
DownloadPhotoOnlyFromModelHub = .DownloadPhotoOnlyFromModelHub
QueryString = .QueryString QueryString = .QueryString
End With End With
End If End If
@@ -244,29 +232,23 @@ Namespace API.PornHub
With Container With Container
If Loading Then If Loading Then
PersonType = .Value(Name_PersonType) PersonType = .Value(Name_PersonType)
NameTrue = .Value(Name_NameTrue)
PhotoPageModel = .Value(Name_PhotoPageModel).FromXML(Of Integer)(PhotoPageModels.Undefined)
DownloadUHD = .Value(Name_DownloadUHD).FromXML(Of Boolean)(False) DownloadUHD = .Value(Name_DownloadUHD).FromXML(Of Boolean)(False)
DownloadUploaded = .Value(Name_DownloadUploaded).FromXML(Of Boolean)(True) DownloadUploaded = .Value(Name_DownloadUploaded).FromXML(Of Boolean)(True)
DownloadTagged = .Value(Name_DownloadTagged).FromXML(Of Boolean)(False) DownloadTagged = .Value(Name_DownloadTagged).FromXML(Of Boolean)(False)
DownloadPrivate = .Value(Name_DownloadPrivate).FromXML(Of Boolean)(False) DownloadPrivate = .Value(Name_DownloadPrivate).FromXML(Of Boolean)(False)
DownloadFavorite = .Value(Name_DownloadFavorite).FromXML(Of Boolean)(False) DownloadFavorite = .Value(Name_DownloadFavorite).FromXML(Of Boolean)(False)
DownloadGifs = .Value(Name_DownloadGifs).FromXML(Of Integer)(False) DownloadGifs = .Value(Name_DownloadGifs).FromXML(Of Integer)(False)
DownloadPhotoOnlyFromModelHub = .Value(Name_DownloadPhotoOnlyFromModelHub).FromXML(Of Boolean)(True)
SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User) SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User)
UpdateUserOptions() UpdateUserOptions()
Else Else
If UpdateUserOptions() Then .Value(Name_LabelsName) = LabelsString If UpdateUserOptions() Then .Value(Name_LabelsName) = LabelsString
.Add(Name_PersonType, PersonType) .Add(Name_PersonType, PersonType)
.Add(Name_NameTrue, NameTrue)
.Add(Name_PhotoPageModel, CInt(PhotoPageModel))
.Add(Name_DownloadUHD, DownloadUHD.BoolToInteger) .Add(Name_DownloadUHD, DownloadUHD.BoolToInteger)
.Add(Name_DownloadUploaded, DownloadUploaded.BoolToInteger) .Add(Name_DownloadUploaded, DownloadUploaded.BoolToInteger)
.Add(Name_DownloadTagged, DownloadTagged.BoolToInteger) .Add(Name_DownloadTagged, DownloadTagged.BoolToInteger)
.Add(Name_DownloadPrivate, DownloadPrivate.BoolToInteger) .Add(Name_DownloadPrivate, DownloadPrivate.BoolToInteger)
.Add(Name_DownloadFavorite, DownloadFavorite.BoolToInteger) .Add(Name_DownloadFavorite, DownloadFavorite.BoolToInteger)
.Add(Name_DownloadGifs, DownloadGifs.BoolToInteger) .Add(Name_DownloadGifs, DownloadGifs.BoolToInteger)
.Add(Name_DownloadPhotoOnlyFromModelHub, DownloadPhotoOnlyFromModelHub.BoolToInteger)
.Add(Name_SiteMode, CInt(SiteMode)) .Add(Name_SiteMode, CInt(SiteMode))
'Debug.WriteLine(GetNonUserUrl(0)) 'Debug.WriteLine(GetNonUserUrl(0))
@@ -283,6 +265,7 @@ Namespace API.PornHub
Private _PageVideosRepeat As Integer = 0 Private _PageVideosRepeat As Integer = 0
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
Try Try
UpdateM3U8URLS = False
PlaylistToken = String.Empty PlaylistToken = String.Empty
Responser.ResetStatus() Responser.ResetStatus()
_PageVideosRepeat = 0 _PageVideosRepeat = 0
@@ -295,7 +278,6 @@ Namespace API.PornHub
Dim limit% = If(DownloadTopCount, -1) Dim limit% = If(DownloadTopCount, -1)
If DownloadVideos Then If DownloadVideos Then
If SiteMode = SiteModes.Playlists Then If SiteMode = SiteModes.Playlists Then
Responser.Mode = Responser.Modes.Default Responser.Mode = Responser.Modes.Default
GetPlaylistToken(Token) GetPlaylistToken(Token)
@@ -519,25 +501,12 @@ Namespace API.PornHub
Dim pFile$ = RegexReplace(URL, Regex_Photo_File) Dim pFile$ = RegexReplace(URL, Regex_Photo_File)
If Not pFile.IsEmptyString Then Return New SFile(pFile) Else Return File If Not pFile.IsEmptyString Then Return New SFile(pFile) Else Return File
End Function End Function
Private Const PhotoUrlPattern_ModelHub As String = "https://www.modelhub.com/{0}/photos"
Private Const PhotoUrlPattern_PornHub As String = "https://www.pornhub.com/{0}/{1}/photos" Private Const PhotoUrlPattern_PornHub As String = "https://www.pornhub.com/{0}/{1}/photos"
Private Sub DownloadUserPhotos(ByVal Token As CancellationToken) Private Sub DownloadUserPhotos(ByVal Token As CancellationToken)
Try Try
If IsSavedPosts Then If IsSavedPosts Then
DownloadUserPhotos_SavedPosts(Token) DownloadUserPhotos_SavedPosts(Token)
ElseIf PersonType = PersonTypeModel Then Else
If PhotoPageModel = PhotoPageModels.Undefined Then
If DownloadUserPhotos_ModelHub(Token) Then PhotoPageModel = PhotoPageModels.ModelHubPage
ThrowAny(Token)
If PhotoPageModel = PhotoPageModels.Undefined AndAlso Not DownloadPhotoOnlyFromModelHub AndAlso
DownloadUserPhotos_PornHub(Token) Then PhotoPageModel = PhotoPageModels.PornHubPage
Else
Select Case PhotoPageModel
Case PhotoPageModels.ModelHubPage : DownloadUserPhotos_ModelHub(Token)
Case PhotoPageModels.PornHubPage : If Not DownloadPhotoOnlyFromModelHub Then DownloadUserPhotos_PornHub(Token)
End Select
End If
ElseIf Not DownloadPhotoOnlyFromModelHub Then
DownloadUserPhotos_PornHub(Token) DownloadUserPhotos_PornHub(Token)
End If End If
ThrowAny(Token) ThrowAny(Token)
@@ -545,48 +514,6 @@ Namespace API.PornHub
ProcessException(ex, Token, "photos downloading error") ProcessException(ex, Token, "photos downloading error")
End Try End Try
End Sub End Sub
Private Function DownloadUserPhotos_ModelHub(ByVal Token As CancellationToken) As Boolean
Dim URL$ = String.Empty
Try
Dim j As EContainer
Dim jErr As New ErrorsDescriber(EDP.SendToLog + EDP.ReturnValue)
Dim albumName$
If PersonType = PersonTypeModel Then
URL = String.Format(PhotoUrlPattern_ModelHub, NameTrue)
Dim r$ = Responser.GetResponse(URL)
If Not r.IsEmptyString Then
Dim l As List(Of PhotoBlock) = RegexFields(Of PhotoBlock)(r, {Regex_Photo_ModelHub_PhotoBlocks}, {1, 2}, EDP.ReturnValue)
If l.ListExists Then l.RemoveAll(Function(ll) ll.Data.IsEmptyString)
If l.ListExists Then
ProgressPre.ChangeMax(l.Count)
Dim albumRegex As RParams = RParams.DMS("", 1, EDP.ReturnValue)
For Each block As PhotoBlock In l
ProgressPre.Perform()
If Not _TempPostsList.Contains(block.AlbumID) Then _TempPostsList.Add(block.AlbumID) Else Continue For
albumRegex.Pattern = "<li id=""" & block.AlbumID & """ class=""modelBox"">[\r\n\s]*?<div class=""modelPhoto"">[\r\n\s]*?\<[^\>]*?alt=""([^""]*)"""
albumName = StringTrim(RegexReplace(r, albumRegex))
If albumName.IsEmptyString Then albumName = block.AlbumID
j = JsonDocument.Parse("{" & block.Data & "}", jErr)
If Not j Is Nothing Then
If If(j("urls")?.Count, 0) > 0 Then
_TempMediaList.ListAddList(j("urls").Select(Function(jj) _
New UserMedia(jj.ItemF({0}).XmlIfNothingValue, UTypes.Picture) With {
.SpecialFolder = $"Albums\{albumName}\",
.File = CreatePhotoFile(.URL, .File)}), LNC)
End If
j.Dispose()
End If
Next
l.Clear()
End If
End If
End If
Return True
Catch ex As Exception
ThrowAny(Token)
Return False
End Try
End Function
Private Overloads Function DownloadUserPhotos_PornHub(ByVal Token As CancellationToken) As Boolean Private Overloads Function DownloadUserPhotos_PornHub(ByVal Token As CancellationToken) As Boolean
Try Try
Dim albumName$ Dim albumName$
@@ -594,6 +521,7 @@ Namespace API.PornHub
Dim r$ = Responser.GetResponse(String.Format(PhotoUrlPattern_PornHub, PersonType, NameTrue)) Dim r$ = Responser.GetResponse(String.Format(PhotoUrlPattern_PornHub, PersonType, NameTrue))
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
Dim l As List(Of PhotoBlock) = RegexFields(Of PhotoBlock)(r, {Regex_Photo_PornHub_PhotoBlocks}, {2, 1}, EDP.ReturnValue) Dim l As List(Of PhotoBlock) = RegexFields(Of PhotoBlock)(r, {Regex_Photo_PornHub_PhotoBlocks}, {2, 1}, EDP.ReturnValue)
l.ListAddList(RegexFields(Of PhotoBlock)(r, {Regex_Photo_PornHub_PhotoBlocks2}, {1, 2}, EDP.ReturnValue))
If l.ListExists Then l.RemoveAll(Function(ll) ll.AlbumID.IsEmptyString) If l.ListExists Then l.RemoveAll(Function(ll) ll.AlbumID.IsEmptyString)
If l.ListExists Then If l.ListExists Then
ProgressPre.ChangeMax(l.Count) ProgressPre.ChangeMax(l.Count)
@@ -618,6 +546,14 @@ Namespace API.PornHub
Return False Return False
End Try End Try
End Function End Function
Private Function DownloadUserPhotos_PornHub_ParseSinglePhoto(ByVal r As String) As String
Dim url$ = String.Empty
With DirectCast(RegexReplace(r, Regex_Photo_PornHub_SinglePhoto), List(Of String))
If .ListExists(3) Then url = .Item(2).IfNullOrEmpty(.Item(1)).StringTrim
End With
If url.IsEmptyString Then url = RegexReplace(r, Regex_Photo_PornHub_SinglePhoto2)
Return url
End Function
Private Overloads Function DownloadUserPhotos_PornHub(ByVal Page As Integer, ByVal AlbumID As String, ByVal AlbumName As String, Private Overloads Function DownloadUserPhotos_PornHub(ByVal Page As Integer, ByVal AlbumID As String, ByVal AlbumName As String,
ByVal Token As CancellationToken) As Boolean ByVal Token As CancellationToken) As Boolean
Try Try
@@ -633,7 +569,7 @@ Namespace API.PornHub
Try Try
r = Responser.GetResponse(url) r = Responser.GetResponse(url)
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
url = RegexReplace(r, Regex_Photo_PornHub_SinglePhoto) url = DownloadUserPhotos_PornHub_ParseSinglePhoto(r)
If Not url.IsEmptyString Then _ If Not url.IsEmptyString Then _
_TempMediaList.ListAddValue(New UserMedia(url, UTypes.Picture) With { _TempMediaList.ListAddValue(New UserMedia(url, UTypes.Picture) With {
.SpecialFolder = $"Albums\{AlbumName}\", .SpecialFolder = $"Albums\{AlbumName}\",
@@ -679,7 +615,7 @@ Namespace API.PornHub
Try Try
r = Responser.GetResponse(m.URL) r = Responser.GetResponse(m.URL)
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
NewUrl = RegexReplace(r, Regex_Photo_PornHub_SinglePhoto) NewUrl = DownloadUserPhotos_PornHub_ParseSinglePhoto(r)
If Not NewUrl.IsEmptyString Then If Not NewUrl.IsEmptyString Then
m.URL = NewUrl m.URL = NewUrl
pFile = RegexReplace(NewUrl, Regex_Photo_File) pFile = RegexReplace(NewUrl, Regex_Photo_File)
@@ -852,11 +788,34 @@ Namespace API.PornHub
End Sub End Sub
#End Region #End Region
#Region "Download content" #Region "Download content"
Private UpdateM3U8URLS As Boolean = False
Private UpdateM3U8URLS_Error As Boolean = False
Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken) Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
DownloadContentDefault(Token) Try : DownloadContentDefault(Token) : Finally : UpdateM3U8URLS = False : End Try
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 Overloads Overrides Function DownloadM3U8(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile,
Return M3U8.Download(URL, Responser, DestinationFile, DownloadUHD, Token, Progress, Not IsSingleObjectDownload) ByVal Token As CancellationToken) As SFile
UpdateM3U8URLS_Error = False
Return DownloadM3U8(URL, Media, DestinationFile, Token, UpdateM3U8URLS)
End Function
Private Overloads Function DownloadM3U8(ByVal URL As String, ByVal Media As UserMedia, ByVal DestinationFile As SFile,
ByVal Token As CancellationToken, ByVal Second As Boolean) As SFile
Try
If Second Then
Dim r$ = Responser.Curl(Media.URL_BASE,, EDP.ReturnValue)
If Not r.IsEmptyString Then Media.URL = CreateVideoURL(r).IfNullOrEmpty(URL) : URL = Media.URL
End If
Dim f As SFile = M3U8.Download(URL, Responser, DestinationFile, DownloadUHD, Token, Progress, Not IsSingleObjectDownload)
If Not f.Exists And Not Second Then UpdateM3U8URLS = True : f = DownloadM3U8(URL, Media, DestinationFile, Token, True)
Return f
Catch ex As Exception
If Not UpdateM3U8URLS_Error Then
UpdateM3U8URLS_Error = True
Thread.Sleep(1000)
Return DownloadM3U8(URL, Media, DestinationFile, Token, True)
End If
Return Nothing
End Try
End Function End Function
#End Region #End Region
#Region "CreateVideoURL" #Region "CreateVideoURL"
@@ -953,6 +912,7 @@ Namespace API.PornHub
#End Region #End Region
#Region "DownloadSingleObject" #Region "DownloadSingleObject"
Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken) Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)
UpdateM3U8URLS = False
_TempMediaList.Add(New UserMedia(Data.URL, UTypes.VideoPre)) _TempMediaList.Add(New UserMedia(Data.URL, UTypes.VideoPre))
ReparseVideo(Token, True, Data) ReparseVideo(Token, True, Data)
End Sub End Sub

View File

@@ -21,8 +21,6 @@ Namespace API.PornHub
Friend Property DownloadFavorite As Boolean Friend Property DownloadFavorite As Boolean
<PSetting(Caption:="Download gifs")> <PSetting(Caption:="Download gifs")>
Friend Property DownloadGifs As Boolean Friend Property DownloadGifs As Boolean
<PSetting(NameOf(SiteSettings.DownloadPhotoOnlyFromModelHub), NameOf(MySettings), Caption:="Download photo only from ModelHub")>
Friend Property DownloadPhotoOnlyFromModelHub As Boolean
Private ReadOnly Property MySettings As SiteSettings Private ReadOnly Property MySettings As SiteSettings
Friend Sub New(ByVal u As UserData) Friend Sub New(ByVal u As UserData)
DownloadUHD = u.DownloadUHD DownloadUHD = u.DownloadUHD
@@ -31,7 +29,6 @@ Namespace API.PornHub
DownloadPrivate = u.DownloadPrivate DownloadPrivate = u.DownloadPrivate
DownloadFavorite = u.DownloadFavorite DownloadFavorite = u.DownloadFavorite
DownloadGifs = u.DownloadGifs DownloadGifs = u.DownloadGifs
DownloadPhotoOnlyFromModelHub = u.DownloadPhotoOnlyFromModelHub
QueryString = u.QueryString QueryString = u.QueryString
MySettings = u.HOST.Source MySettings = u.HOST.Source
End Sub End Sub
@@ -43,7 +40,6 @@ Namespace API.PornHub
DownloadPrivate = s.DownloadPrivate.Value DownloadPrivate = s.DownloadPrivate.Value
DownloadFavorite = s.DownloadFavorite.Value DownloadFavorite = s.DownloadFavorite.Value
DownloadGifs = Not v = CheckState.Unchecked DownloadGifs = Not v = CheckState.Unchecked
DownloadPhotoOnlyFromModelHub = s.DownloadPhotoOnlyFromModelHub.Value
MySettings = s MySettings = s
End Sub End Sub
End Class End Class

View File

@@ -172,7 +172,7 @@ Namespace API.Reddit
End If End If
End Function End Function
Friend Overrides Function Available(ByVal What As Download, ByVal Silent As Boolean) As Boolean Friend Overrides Function Available(ByVal What As Download, ByVal Silent As Boolean) As Boolean
Return AvailableTrueValue(What) Return AvailableTrueValue(What) AndAlso UpdateTokenIfRequired()
End Function End Function
Private Function AvailableTrueValue(ByVal What As Download) As Boolean Private Function AvailableTrueValue(ByVal What As Download) As Boolean
Return Not What = Download.SavedPosts OrElse (Responser.CookiesExists And ACheck(SavedPostsUserName.Value)) Return Not What = Download.SavedPosts OrElse (Responser.CookiesExists And ACheck(SavedPostsUserName.Value))
@@ -199,7 +199,7 @@ Namespace API.Reddit
End If End If
End Function End Function
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
With DirectCast(User, UserData) : Return String.Format(UrlPatternUser, IIf(.IsChannel, ChannelOption, "user"), .TrueName) : End With With DirectCast(User, UserData) : Return String.Format(UrlPatternUser, IIf(.IsChannel, ChannelOption, "user"), .NameTrue) : End With
End Function End Function
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
If Not Media.Post.ID.IsEmptyString Then If Not Media.Post.ID.IsEmptyString Then
@@ -250,6 +250,7 @@ Namespace API.Reddit
Return False Return False
End Function End Function
Private Function UpdateTokenIfRequired() As Boolean Private Function UpdateTokenIfRequired() As Boolean
UpdateRedGifsToken()
If (CBool(UseTokenForTimelines.Value) Or CBool(UseTokenForSavedPosts.Value)) AndAlso CredentialsExists Then If (CBool(UseTokenForTimelines.Value) Or CBool(UseTokenForSavedPosts.Value)) AndAlso CredentialsExists Then
If CDate(BearerTokenDateUpdate.Value).AddMinutes(TokenUpdateInterval.Value) <= Now Then Return UpdateToken() If CDate(BearerTokenDateUpdate.Value).AddMinutes(TokenUpdateInterval.Value) <= Now Then Return UpdateToken()
End If End If

View File

@@ -42,7 +42,6 @@ Namespace API.Reddit
End Get End Get
End Property End Property
Friend Property IsChannel As Boolean = False Friend Property IsChannel As Boolean = False
Friend Property TrueName As String = String.Empty
Friend Overrides ReadOnly Property SpecialLabels As IEnumerable(Of String) Friend Overrides ReadOnly Property SpecialLabels As IEnumerable(Of String)
Get Get
Return {CannelsLabelName, CannelsLabelName_ChannelsForm, UserLabelName} Return {CannelsLabelName, CannelsLabelName_ChannelsForm, UserLabelName}
@@ -173,16 +172,16 @@ Namespace API.Reddit
#End Region #End Region
#Region "Load and Update user info" #Region "Load and Update user info"
Private Function UpdateNames() As Boolean Private Function UpdateNames() As Boolean
If TrueName.IsEmptyString Then If NameTrue(True).IsEmptyString Then
Dim n$() = Name.Split("@") Dim n$() = Name.Split("@")
If n.ListExists Then If n.ListExists Then
If n.Length = 2 Then If n.Length = 2 Then
TrueName = n(0) NameTrue = n(0)
IsChannel = True IsChannel = True
ElseIf IsChannel Then ElseIf IsChannel Then
TrueName = Name NameTrue = Name
Else Else
TrueName = n(0) NameTrue = n(0)
End If End If
End If End If
If Not IsSavedPosts Then If Not IsSavedPosts Then
@@ -201,7 +200,6 @@ Namespace API.Reddit
ViewMode = .Value(Name_ViewMode).FromXML(Of Integer)(CInt(CView.New)) ViewMode = .Value(Name_ViewMode).FromXML(Of Integer)(CInt(CView.New))
ViewPeriod = .Value(Name_ViewPeriod).FromXML(Of Integer)(CInt(CPeriod.All)) ViewPeriod = .Value(Name_ViewPeriod).FromXML(Of Integer)(CInt(CPeriod.All))
IsChannel = .Value(Name_IsChannel).FromXML(Of Boolean)(False) IsChannel = .Value(Name_IsChannel).FromXML(Of Boolean)(False)
TrueName = .Value(Name_TrueName)
RedGifsAccount = .Value(Name_RedGifsAccount) RedGifsAccount = .Value(Name_RedGifsAccount)
RedditAccount = .Value(Name_RedditAccount) RedditAccount = .Value(Name_RedditAccount)
UpdateNames() UpdateNames()
@@ -210,7 +208,7 @@ Namespace API.Reddit
.Add(Name_ViewMode, CInt(ViewMode)) .Add(Name_ViewMode, CInt(ViewMode))
.Add(Name_ViewPeriod, CInt(ViewPeriod)) .Add(Name_ViewPeriod, CInt(ViewPeriod))
.Add(Name_IsChannel, IsChannel.BoolToInteger) .Add(Name_IsChannel, IsChannel.BoolToInteger)
.Add(Name_TrueName, TrueName) .Add(Name_TrueName, NameTrue(True))
.Add(Name_RedGifsAccount, RedGifsAccount) .Add(Name_RedGifsAccount, RedGifsAccount)
.Add(Name_RedditAccount, RedditAccount) .Add(Name_RedditAccount, RedditAccount)
End If End If
@@ -230,7 +228,7 @@ Namespace API.Reddit
If CreatedByChannel And Settings.FromChannelDownloadTopUse And Settings.FromChannelDownloadTop > 0 Then _ If CreatedByChannel And Settings.FromChannelDownloadTopUse And Settings.FromChannelDownloadTop > 0 Then _
DownloadTopCount = Settings.FromChannelDownloadTop.Value DownloadTopCount = Settings.FromChannelDownloadTop.Value
If IsChannel Or IsSavedPosts Then UseMD5Comparison = False If IsChannel Or IsSavedPosts Then UseMD5Comparison = False
If IsSavedPosts Then TrueName = MySiteSettings.SavedPostsUserName.Value If IsSavedPosts Then NameTrue = MySiteSettings.SavedPostsUserName.Value
UpdateNames() UpdateNames()
If IsChannelForm Then If IsChannelForm Then
UseMD5Comparison = False UseMD5Comparison = False
@@ -310,10 +308,10 @@ Namespace API.Reddit
Dim NewPostDetected As Boolean = False Dim NewPostDetected As Boolean = False
Dim ExistsDetected As Boolean = False Dim ExistsDetected As Boolean = False
Dim IsCrossPost As Predicate(Of EContainer) = Function(e) Not e.Value(Node_CrosspostRootId).IsEmptyString Or Not e.Value(Node_CrosspostParentId).IsEmptyString Or Not e.Value(Node_CrosspostParent).IsEmptyString Dim IsCrossPost As Predicate(Of EContainer) = Function(e) Not e.Value(Node_CrosspostRootId).IsEmptyString Or Not e.Value(Node_CrosspostParentId).IsEmptyString Or Not e.Value(Node_CrosspostParent).IsEmptyString
Dim CheckNode As Predicate(Of EContainer) = Function(e) Not ParseUserMediaOnly OrElse If(e("author")?.Value, "/").ToLower.Equals(TrueName.StringToLower) Dim CheckNode As Predicate(Of EContainer) = Function(e) Not ParseUserMediaOnly OrElse If(e("author")?.Value, "/").ToLower.Equals(NameTrue.StringToLower)
Dim _PostID As Func(Of String) = Function() PostTmp.IfNullOrEmpty(PostID) Dim _PostID As Func(Of String) = Function() PostTmp.IfNullOrEmpty(PostID)
URL = $"https://gateway.reddit.com/desktopapi/v1/user/{TrueName}/posts?rtj=only&allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort={View}&t={Period}&layout=classic" URL = $"https://gateway.reddit.com/desktopapi/v1/user/{NameTrue}/posts?rtj=only&allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort={View}&t={Period}&layout=classic"
ThrowAny(Token) ThrowAny(Token)
Dim r$ = Responser.GetResponse(URL) Dim r$ = Responser.GetResponse(URL)
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
@@ -394,10 +392,10 @@ Namespace API.Reddit
Dim lDate As Date? Dim lDate As Date?
If IsSavedPosts Then If IsSavedPosts Then
URL = $"https://www.reddit.com/user/{TrueName}/saved.json?after={POST}" URL = $"https://www.reddit.com/user/{NameTrue}/saved.json?after={POST}"
If Not POST.IsEmptyString Then Thread.Sleep(savedPostsSleepTimer) If Not POST.IsEmptyString Then Thread.Sleep(savedPostsSleepTimer)
Else Else
URL = $"https://reddit.com/r/{TrueName}/{View}.json?allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort={View}&t={Period}&layout=classic" URL = $"https://reddit.com/r/{NameTrue}/{View}.json?allow_quarantined=true&allow_over18=1&include=identity&after={POST}&dist=25&sort={View}&t={Period}&layout=classic"
End If End If
ThrowAny(Token) ThrowAny(Token)
@@ -480,7 +478,7 @@ Namespace API.Reddit
Private Sub GetUserInfo() Private Sub GetUserInfo()
Try Try
If Not IsSavedPosts And ChannelInfo Is Nothing Then If Not IsSavedPosts And ChannelInfo Is Nothing Then
Dim r$ = Responser.GetResponse($"https://reddit.com/{IIf(IsChannel, "r", "user")}/{TrueName}/about.json",, EDP.ReturnValue) Dim r$ = Responser.GetResponse($"https://reddit.com/{IIf(IsChannel, "r", "user")}/{NameTrue}/about.json",, EDP.ReturnValue)
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
Using j As EContainer = JsonDocument.Parse(r) Using j As EContainer = JsonDocument.Parse(r)
If Not j Is Nothing AndAlso j.Contains({"data", "subreddit"}) Then If Not j Is Nothing AndAlso j.Contains({"data", "subreddit"}) Then
@@ -489,20 +487,10 @@ Namespace API.Reddit
UserSiteNameUpdate(.Value("title")) UserSiteNameUpdate(.Value("title"))
UserDescriptionUpdate(.Value("public_description")) UserDescriptionUpdate(.Value("public_description"))
Dim dir As SFile = MyFile.CutPath Dim dir As SFile = MyFile.CutPath
Dim __getFile As Action(Of String) = Sub(ByVal img As String) Dim fileCrFunc As Func(Of String, SFile) = Function(img) CreateFileFromUrl(img)
If Not img.IsEmptyString Then
Dim f As SFile = CreateFileFromUrl(img)
If Not f.Name.IsEmptyString Then
If f.Extension.IsEmptyString Then f.Extension = "jpg"
f.Path = dir.Path
If Not f.Exists Then GetWebFile(img, f, EDP.ReturnValue)
If f.Exists Then IconBannerDownloaded = True
End If
End If
End Sub
If DownloadIconBanner Then If DownloadIconBanner Then
__getFile.Invoke(.Value("icon_img")) SimpleDownloadAvatar(.Value("icon_img"), fileCrFunc)
__getFile.Invoke(.Value("banner_img")) SimpleDownloadAvatar(.Value("banner_img"), fileCrFunc)
End If End If
End With End With
End If End If

View File

@@ -44,7 +44,6 @@ Namespace API.ThisVid
Friend Property DownloadPrivate As Boolean = True Friend Property DownloadPrivate As Boolean = True
Friend Property DownloadFavourite As Boolean = False Friend Property DownloadFavourite As Boolean = False
Friend Property DifferentFolders As Boolean = True Friend Property DifferentFolders As Boolean = True
Friend Property TrueName As String = String.Empty
Friend Property SiteMode As SiteModes = SiteModes.User Friend Property SiteMode As SiteModes = SiteModes.User
Private Property Arguments As String = String.Empty Private Property Arguments As String = String.Empty
Friend Overrides ReadOnly Property SpecialLabels As IEnumerable(Of String) Friend Overrides ReadOnly Property SpecialLabels As IEnumerable(Of String)
@@ -80,7 +79,7 @@ Namespace API.ThisVid
If Not Force OrElse (Not SiteMode = SiteModes.User AndAlso Not NewUrl.IsEmptyString AndAlso MyFileSettings.Exists) Then If Not Force OrElse (Not SiteMode = SiteModes.User AndAlso Not NewUrl.IsEmptyString AndAlso MyFileSettings.Exists) Then
Dim eObj As Plugin.ExchangeOptions = Nothing Dim eObj As Plugin.ExchangeOptions = Nothing
If Force Then eObj = MySettings.IsMyUser(NewUrl) If Force Then eObj = MySettings.IsMyUser(NewUrl)
If (Force And Not eObj.UserName.IsEmptyString) Or (Not Force And TrueName.IsEmptyString) Then If (Force And Not eObj.UserName.IsEmptyString) Or (Not Force And NameTrue(True).IsEmptyString) Then
Dim n$() = If(Force, eObj.UserName, Name).Split("@") Dim n$() = If(Force, eObj.UserName, Name).Split("@")
If n.ListExists(2) Then If n.ListExists(2) Then
@@ -98,8 +97,8 @@ Namespace API.ThisVid
End If End If
__TrueName = n(1) __TrueName = n(1)
If Force AndAlso (Not TrueName = __TrueName Or Not SiteMode = __Mode) Then If Force AndAlso (Not NameTrue(True) = __TrueName Or Not SiteMode = __Mode) Then
If ValidateChangeSearchOptions(ToStringForLog, $"{__Mode}: {__TrueName}", $"{SiteMode}: {TrueName}") Then If ValidateChangeSearchOptions(ToStringForLog, $"{__Mode}: {__TrueName}", $"{SiteMode}: {NameTrue(True)}") Then
__ForceApply = True __ForceApply = True
Else Else
Return False Return False
@@ -109,21 +108,21 @@ Namespace API.ThisVid
Arguments = __Arguments Arguments = __Arguments
Options = If(Force, eObj.Options, Options) Options = If(Force, eObj.Options, Options)
If Not Force Then If Not Force Then
TrueName = __TrueName NameTrue = __TrueName
SiteMode = __Mode SiteMode = __Mode
Settings.Labels.Add(SearchRequestLabelName) Settings.Labels.Add(SearchRequestLabelName)
Labels.ListAddValue(SearchRequestLabelName, LNC) Labels.ListAddValue(SearchRequestLabelName, LNC)
Labels.Sort() Labels.Sort()
UserSiteName = $"{SiteMode}: {TrueName}" UserSiteName = $"{SiteMode}: {NameTrue}"
If FriendlyName.IsEmptyString Then FriendlyName = UserSiteName If FriendlyName.IsEmptyString Then FriendlyName = UserSiteName
ElseIf Force And __ForceApply Then ElseIf Force And __ForceApply Then
TrueName = __TrueName NameTrue = __TrueName
SiteMode = __Mode SiteMode = __Mode
End If End If
Return True Return True
Else Else
SiteMode = SiteModes.User SiteMode = SiteModes.User
TrueName = Name NameTrue = Name
End If End If
End If End If
End If End If
@@ -136,7 +135,6 @@ Namespace API.ThisVid
DownloadPrivate = .Value(Name_DownloadPrivate).FromXML(Of Boolean)(True) DownloadPrivate = .Value(Name_DownloadPrivate).FromXML(Of Boolean)(True)
DownloadFavourite = .Value(Name_DownloadFavourite).FromXML(Of Boolean)(False) DownloadFavourite = .Value(Name_DownloadFavourite).FromXML(Of Boolean)(False)
DifferentFolders = .Value(Name_DifferentFolders).FromXML(Of Boolean)(True) DifferentFolders = .Value(Name_DifferentFolders).FromXML(Of Boolean)(True)
TrueName = .Value(Name_TrueName)
SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User) SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User)
Arguments = .Value(Name_Arguments) Arguments = .Value(Name_Arguments)
UpdateUserOptions() UpdateUserOptions()
@@ -150,7 +148,7 @@ Namespace API.ThisVid
.Add(Name_DownloadPrivate, DownloadPrivate.BoolToInteger) .Add(Name_DownloadPrivate, DownloadPrivate.BoolToInteger)
.Add(Name_DownloadFavourite, DownloadFavourite.BoolToInteger) .Add(Name_DownloadFavourite, DownloadFavourite.BoolToInteger)
.Add(Name_DifferentFolders, DifferentFolders.BoolToInteger) .Add(Name_DifferentFolders, DifferentFolders.BoolToInteger)
.Add(Name_TrueName, TrueName) .Add(Name_TrueName, NameTrue(True))
.Add(Name_SiteMode, CInt(SiteMode)) .Add(Name_SiteMode, CInt(SiteMode))
.Add(Name_Arguments, Arguments) .Add(Name_Arguments, Arguments)
@@ -259,18 +257,18 @@ Namespace API.ThisVid
Dim url$ = String.Empty Dim url$ = String.Empty
Select Case SiteMode Select Case SiteMode
Case SiteModes.Tags Case SiteModes.Tags
url = $"https://thisvid.com/{SiteSettings.P_Tags}/{TrueName}/" url = $"https://thisvid.com/{SiteSettings.P_Tags}/{NameTrue}/"
If Not Arguments.IsEmptyString Then url &= $"{Arguments}/" If Not Arguments.IsEmptyString Then url &= $"{Arguments}/"
If Page > 1 Then url &= $"{Page}/" If Page > 1 Then url &= $"{Page}/"
Case SiteModes.Categories Case SiteModes.Categories
url = $"https://thisvid.com/{SiteSettings.P_Categories}/{TrueName}/" url = $"https://thisvid.com/{SiteSettings.P_Categories}/{NameTrue}/"
If Not Arguments.IsEmptyString Then url &= $"{Arguments}/" If Not Arguments.IsEmptyString Then url &= $"{Arguments}/"
If Page > 1 Then url &= $"{Page}/" If Page > 1 Then url &= $"{Page}/"
Case SiteModes.Search Case SiteModes.Search
If Not Arguments.IsEmptyString Then If Not Arguments.IsEmptyString Then
url = $"https://thisvid.com/{Arguments}/" url = $"https://thisvid.com/{Arguments}/"
If Page > 1 Then url &= $"{Page}/" If Page > 1 Then url &= $"{Page}/"
url &= $"?q={TrueName}/" url &= $"?q={NameTrue}/"
End If End If
End Select End Select
Return url Return url

View File

@@ -15,7 +15,7 @@ Imports PersonalUtilities.Functions.RegularExpressions
Imports IG = SCrawler.API.Instagram.SiteSettings Imports IG = SCrawler.API.Instagram.SiteSettings
Imports DN = SCrawler.API.Base.DeclaredNames Imports DN = SCrawler.API.Base.DeclaredNames
Namespace API.ThreadsNet Namespace API.ThreadsNet
<Manifest("AndyProgram_ThreadsNet"), SavedPosts, SeparatedTasks(1)> <Manifest("AndyProgram_ThreadsNet"), SavedPosts, SeparatedTasks(1), SpecialForm(False)>
Friend Class SiteSettings : Inherits SiteSettingsBase Friend Class SiteSettings : Inherits SiteSettingsBase
#Region "Declarations" #Region "Declarations"
#Region "Authorization" #Region "Authorization"
@@ -155,6 +155,7 @@ Namespace API.ThreadsNet
UrlPatternUser = "https://www.threads.net/@{0}" UrlPatternUser = "https://www.threads.net/@{0}"
UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "threads.net/@"), 1) UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, "threads.net/@"), 1)
ImageVideoContains = "threads.net" ImageVideoContains = "threads.net"
UserOptionsType = GetType(EditorExchangeOptionsBase)
End Sub End Sub
#End Region #End Region
#Region "UpdateResponserData" #Region "UpdateResponserData"
@@ -180,9 +181,6 @@ Namespace API.ThreadsNet
Friend Overrides Function BaseAuthExists() As Boolean Friend Overrides Function BaseAuthExists() As Boolean
Return Responser.CookiesExists And {HH_CSRF_TOKEN, HH_IG_APP_ID}.All(Function(v) ACheck(Of String)(v.Value)) And CBool(DownloadData_Impl.Value) Return Responser.CookiesExists And {HH_CSRF_TOKEN, HH_IG_APP_ID}.All(Function(v) ACheck(Of String)(v.Value)) And CBool(DownloadData_Impl.Value)
End Function End Function
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
Return String.Format(UrlPatternUser, DirectCast(User, UserData).NameTrue)
End Function
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
Try Try
Dim code$ = DirectCast(User, UserData).GetPostCodeById(Media.Post.ID) Dim code$ = DirectCast(User, UserData).GetPostCodeById(Media.Post.ID)

View File

@@ -7,6 +7,7 @@
' This program is distributed in the hope that it will be useful, ' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY ' but WITHOUT ANY WARRANTY
Imports System.Threading Imports System.Threading
Imports SCrawler.Plugin
Imports SCrawler.API.Base Imports SCrawler.API.Base
Imports SCrawler.API.YouTube.Objects Imports SCrawler.API.YouTube.Objects
Imports PersonalUtilities.Functions.XML Imports PersonalUtilities.Functions.XML
@@ -51,9 +52,10 @@ Namespace API.ThreadsNet
#End Region #End Region
#Region "Exchange" #Region "Exchange"
Friend Overrides Function ExchangeOptionsGet() As Object Friend Overrides Function ExchangeOptionsGet() As Object
Return Nothing Return New EditorExchangeOptionsBase(Me)
End Function End Function
Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object) Friend Overrides Sub ExchangeOptionsSet(ByVal Obj As Object)
If Not Obj Is Nothing AndAlso TypeOf Obj Is EditorExchangeOptionsBase Then NameTrue = DirectCast(Obj, EditorExchangeOptionsBase).UserName
End Sub End Sub
#End Region #End Region
#Region "Initializer" #Region "Initializer"
@@ -73,12 +75,13 @@ Namespace API.ThreadsNet
End Sub End Sub
Private Sub DisableDownload() Private Sub DisableDownload()
MySettings.DownloadData_Impl.Value = False MySettings.DownloadData_Impl.Value = False
MyMainLOG = $"{Site} downloading is disabled until you update your credentials" LogError(Nothing, $"{Site} downloading is disabled until you update your credentials")
End Sub End Sub
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
If CBool(MySettings.DownloadData_Impl.Value) Then If CBool(MySettings.DownloadData_Impl.Value) Then
Dim errorFound As Boolean = False Dim errorFound As Boolean = False
Try Try
_IdChanged = False
Responser.Method = "POST" Responser.Method = "POST"
LoadSavePostsKV(True) LoadSavePostsKV(True)
ResetBaseTokens() ResetBaseTokens()
@@ -103,9 +106,9 @@ Namespace API.ThreadsNet
End If End If
If IsSavedPosts Then If IsSavedPosts Then
DefaultParser_ElemNode = {"node", "thread_items", 0, "post"} DefaultParser_ElemNode = {"node", "thread_items", 0, "post"}
DownloadSavedPosts(String.Empty, Token) DownloadSavedPosts(String.Empty, 0, Token)
Else Else
DownloadData(String.Empty, Token) DownloadData(String.Empty, 0, Token)
End If End If
If _TempMediaList.Count > 0 Then FirstLoadingDone = True : setMaxPostDate.Invoke(_TempMediaList) If _TempMediaList.Count > 0 Then FirstLoadingDone = True : setMaxPostDate.Invoke(_TempMediaList)
Catch ex As Exception Catch ex As Exception
@@ -151,12 +154,14 @@ Namespace API.ThreadsNet
Responser.Headers.Add(IGS.Header_CSRF_TOKEN, csrf) Responser.Headers.Add(IGS.Header_CSRF_TOKEN, csrf)
End If End If
End Sub End Sub
Private Const GQL_Q As String = "https://www.threads.net/api/graphql?lsd={0}&fb_dtsg={1}&doc_id={2}&fb_api_req_friendly_name={3}&server_timestamps=true&variables={4}" 'Private Const GQL_Q As String = "https://www.threads.net/api/graphql?lsd={0}&fb_dtsg={1}&doc_id={2}&fb_api_req_friendly_name={3}&server_timestamps=true&variables={4}"
Private Const GQL_P_DOC_ID As String = "6371597506283707" Private Const GQL_Q2 As String = "https://www.threads.net/graphql/query"
Private Const GQL_P_NAME As String = "BarcelonaProfileThreadsTabRefetchableQuery" Private Const PayloadData As String = "lsd={0}&fb_dtsg={1}&doc_id={2}&fb_api_req_friendly_name={3}&server_timestamps=true&variables={4}"
Private Const GQL_S_DOC_ID_1 As String = "7758166704280174" Private Const GQL_P_DOC_ID As String = "9039187972876777" '"8779269398849532" '"6371597506283707"
Private Const GQL_S_NAME_1 As String = "BarcelonaSavedPageViewerQuery" Private Const GQL_P_NAME As String = "BarcelonaProfileThreadsTabRefetchableDirectQuery" '"BarcelonaProfileThreadsTabRefetchableQuery"
Private Const GQL_S_DOC_ID_2 As String = "8617275414954442" 'Private Const GQL_S_DOC_ID_1 As String = "9227844190587889" '"7758166704280174"
'Private Const GQL_S_NAME_1 As String = "BarcelonaSavedPageViewerQuery"
Private Const GQL_S_DOC_ID_2 As String = "9116629201788321" '"8617275414954442"
Private Const GQL_S_NAME_2 As String = "BarcelonaSavedPageRefetchableQuery" Private Const GQL_S_NAME_2 As String = "BarcelonaSavedPageRefetchableQuery"
Private Sub DownloadCheckCredentials() Private Sub DownloadCheckCredentials()
If Not Valid Then If Not Valid Then
@@ -166,106 +171,189 @@ Namespace API.ThreadsNet
End If End If
If Not Valid Then DisableDownload() : Throw New Plugin.ExitException("Some credentials are missing") If Not Valid Then DisableDownload() : Throw New Plugin.ExitException("Some credentials are missing")
End Sub End Sub
Private Overloads Sub DownloadData(ByVal Cursor As String, ByVal Token As CancellationToken) Private Function CheckErrors(ByVal e As EContainer) As Boolean
Const var_init$ = """userID"":""{0}""" Return e.ListExists AndAlso Not JsonErrorMessage(e).IsEmptyString
Const var_cursor$ = """after"":""{1}"",""before"":null,""first"":25,""last"":null,""userID"":""{0}"",""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsFeedbackHubEnabledrelayprovider"":false" End Function
Dim URL$ = String.Empty Private Function JsonErrorMessage(ByVal e As EContainer) As String
Return e.ItemF({"errors", 0, "summary"})?.Value
End Function
Private Sub ProcessJsonErrorException(ByVal uex As JsonErrorException, Optional ByVal ThrowEx As Boolean = True)
If uex.UserNotFound Then
UserExists = False
_ForceSaveUserInfo = True
_ForceSaveUserInfoOnException = True
ElseIf ThrowEx Then
Throw New ExitException(uex.ErrMessage) With {.SimpleLogLine = True}
Else
LogError(Nothing, uex.ErrMessage)
End If
End Sub
Private Class JsonErrorException : Inherits Exception
Friend Property UserNotFound As Boolean = False
Private _ErrMessage As String = String.Empty
Public Property ErrMessage As String
Get
Return _ErrMessage
End Get
Set(ByVal m As String)
_ErrMessage = m
UserNotFound = _ErrMessage.StringToLower = "not found"
End Set
End Property
Public Overrides ReadOnly Property Message As String
Get
Return _ErrMessage
End Get
End Property
Friend Sub New()
End Sub
Friend Sub New(ByVal Message As String)
ErrMessage = Message
End Sub
End Class
Private Overloads Sub DownloadData(ByVal Cursor As String, ByVal Round As Integer, ByVal Token As CancellationToken)
'Const var_init$ = """userID"":""{0}"""
'Const var_cursor$ = """after"":""{1}"",""before"":null,""first"":25,""last"":null,""userID"":""{0}"",""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsFeedbackHubEnabledrelayprovider"":false"
Const var_cursor2$ = """after"":{1},""before"":null,""first"":10,""last"":null,""userID"":""{0}"",""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaHasSelfReplyContextrelayprovider"":false,""__relay_internal__pv__BarcelonaShareableListsrelayprovider"":true,""__relay_internal__pv__BarcelonaIsSearchDiscoveryEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaOptionalCookiesEnabledrelayprovider"":true,""__relay_internal__pv__BarcelonaQuotedPostUFIEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaIsCrawlerrelayprovider"":false,""__relay_internal__pv__BarcelonaHasDisplayNamesrelayprovider"":false,""__relay_internal__pv__BarcelonaCanSeeSponsoredContentrelayprovider"":false,""__relay_internal__pv__BarcelonaShouldShowFediverseM075Featuresrelayprovider"":true,""__relay_internal__pv__BarcelonaShouldShowTagRedesignrelayprovider"":false,""__relay_internal__pv__BarcelonaIsInternalUserrelayprovider"":false"
Try Try
DownloadCheckCredentials() DownloadCheckCredentials()
Responser.Method = "POST" With Responser
Responser.Referer = $"https://www.threads.net/@{NameTrue}" .Method = "POST"
Responser.Headers.Add(GQL_HEADER_FB_LSD, Token_lsd) .Referer = $"https://www.threads.net/@{NameTrue}"
Responser.Headers.Add(GQL_HEADER_FB_FRINDLY_NAME, GQL_P_NAME) .ContentType = "application/x-www-form-urlencoded"
With .Headers
.Add(GQL_HEADER_FB_LSD, Token_lsd)
.Add(GQL_HEADER_FB_FRINDLY_NAME, GQL_P_NAME)
End With
End With
Dim nextCursor$ = String.Empty Dim nextCursor$ = String.Empty
Dim dataFound As Boolean = False Dim dataFound As Boolean = False
Dim vars$ Dim vars$ = String.Format(var_cursor2, ID, IIf(Cursor.IsEmptyString, "null", $"""{Cursor}"""))
If Cursor.IsEmptyString Then 'If Cursor.IsEmptyString Then
vars = String.Format(var_init, ID) ' vars = String.Format(var_init, ID)
Else 'Else
vars = String.Format(var_cursor, ID, Cursor) ' vars = String.Format(var_cursor, ID, Cursor)
End If 'End If
vars = SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & vars & "}") vars = String.Format(PayloadData, Token_lsd, Token_dtsg_Var, GQL_P_DOC_ID, GQL_P_NAME,
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & vars & "}"))
URL = String.Format(GQL_Q, Token_lsd, Token_dtsg_Var, GQL_P_DOC_ID, GQL_P_NAME, vars) 'URL = String.Format(GQL_Q, Token_lsd, Token_dtsg_Var, GQL_P_DOC_ID, GQL_P_NAME, vars)
Using j As EContainer = GetDocument(URL, Token) Using j As EContainer = GetDocument(GQL_Q2, vars, Token)
If j.ListExists Then If Not CheckErrors(j) Then
With j({"data", "mediaData"}) If j.ListExists Then
If .ListExists Then With j({"data", "mediaData"})
nextCursor = .Value({"page_info"}, "end_cursor") If .ListExists Then
With .Item({"edges"}) nextCursor = .Value({"page_info"}, "end_cursor")
If .ListExists Then dataFound = DefaultParser(.Self, Sections.Timeline, Token) With .Item({"edges"})
End With If .ListExists Then dataFound = DefaultParser(.Self, Sections.Timeline, Token)
End If End With
End With End If
End With
End If
Else
Throw New JsonErrorException(JsonErrorMessage(j))
End If End If
End Using End Using
If dataFound And Not nextCursor.IsEmptyString Then DownloadData(nextCursor, Token) If dataFound And Not nextCursor.IsEmptyString Then DownloadData(nextCursor, 0, Token)
Catch uex As JsonErrorException
If Round > 0 Then
ProcessJsonErrorException(uex)
ElseIf Not _IdChanged AndAlso UpdateCredentials() Then
DownloadData(Cursor, Round + 1, Token)
Else
ProcessJsonErrorException(uex)
End If
Catch eex As ExitException
Throw eex
Catch ex As Exception Catch ex As Exception
ProcessException(ex, Token, $"data downloading error [{URL}]") ProcessException(ex, Token, "data downloading error")
End Try End Try
End Sub End Sub
Private Sub DownloadSavedPosts(ByVal Cursor As String, ByVal Token As CancellationToken) Private Sub DownloadSavedPosts(ByVal Cursor As String, ByVal Round As Integer, ByVal Token As CancellationToken)
Const var_init$ = """__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsInlineReelsEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaUseCometVideoPlaybackEnginerelayprovider"":false,""__relay_internal__pv__BarcelonaOptionalCookiesEnabledrelayprovider"":true,""__relay_internal__pv__BarcelonaIsTextFragmentsEnabledForPostCaptionsrelayprovider"":true,""__relay_internal__pv__BarcelonaShouldShowFediverseM075Featuresrelayprovider"":true" 'Const var_init$ = """__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsInlineReelsEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaUseCometVideoPlaybackEnginerelayprovider"":false,""__relay_internal__pv__BarcelonaOptionalCookiesEnabledrelayprovider"":true,""__relay_internal__pv__BarcelonaIsTextFragmentsEnabledForPostCaptionsrelayprovider"":true,""__relay_internal__pv__BarcelonaShouldShowFediverseM075Featuresrelayprovider"":true"
Const var_cursor$ = """after"":""{0}"",""first"":25,""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsInlineReelsEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaUseCometVideoPlaybackEnginerelayprovider"":false,""__relay_internal__pv__BarcelonaOptionalCookiesEnabledrelayprovider"":true,""__relay_internal__pv__BarcelonaIsTextFragmentsEnabledForPostCaptionsrelayprovider"":true,""__relay_internal__pv__BarcelonaShouldShowFediverseM075Featuresrelayprovider"":true" 'Const var_cursor$ = """after"":""{0}"",""first"":25,""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsInlineReelsEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaUseCometVideoPlaybackEnginerelayprovider"":false,""__relay_internal__pv__BarcelonaOptionalCookiesEnabledrelayprovider"":true,""__relay_internal__pv__BarcelonaIsTextFragmentsEnabledForPostCaptionsrelayprovider"":true,""__relay_internal__pv__BarcelonaShouldShowFediverseM075Featuresrelayprovider"":true"
Dim URL$ = String.Empty Const var_cursor2$ = """after"":{0},""first"":25,""__relay_internal__pv__BarcelonaQuotedPostUFIEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaHasSelfReplyContextrelayprovider"":false,""__relay_internal__pv__BarcelonaShareableListsrelayprovider"":true,""__relay_internal__pv__BarcelonaIsSearchDiscoveryEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaOptionalCookiesEnabledrelayprovider"":true,""__relay_internal__pv__BarcelonaIsCrawlerrelayprovider"":false,""__relay_internal__pv__BarcelonaHasDisplayNamesrelayprovider"":false,""__relay_internal__pv__BarcelonaCanSeeSponsoredContentrelayprovider"":false,""__relay_internal__pv__BarcelonaShouldShowFediverseM075Featuresrelayprovider"":true,""__relay_internal__pv__BarcelonaShouldShowTagRedesignrelayprovider"":false,""__relay_internal__pv__BarcelonaIsInternalUserrelayprovider"":false"
Try Try
DownloadCheckCredentials() DownloadCheckCredentials()
Responser.Method = "POST" With Responser
Responser.Referer = "https://www.threads.net/" .Method = "POST"
Responser.Headers.Add(GQL_HEADER_FB_LSD, Token_lsd) .Referer = "https://www.threads.net/"
Responser.Headers.Add(GQL_HEADER_FB_FRINDLY_NAME, If(Cursor.IsEmptyString, GQL_S_NAME_1, GQL_S_NAME_2)) .ContentType = "application/x-www-form-urlencoded"
With .Headers
.Add(GQL_HEADER_FB_LSD, Token_lsd)
'.Add(GQL_HEADER_FB_FRINDLY_NAME, If(Cursor.IsEmptyString, GQL_S_NAME_1, GQL_S_NAME_2))
.Add(GQL_HEADER_FB_FRINDLY_NAME, GQL_S_NAME_2)
End With
End With
Dim nextCursor$ = String.Empty Dim nextCursor$ = String.Empty
Dim dataFound As Boolean = False Dim dataFound As Boolean = False
Dim vars$ = SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & If(Cursor.IsEmptyString, var_init, String.Format(var_cursor, Cursor)) & "}") 'Dim vars$ = SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & If(Cursor.IsEmptyString, var_init, String.Format(var_cursor, Cursor)) & "}")
Dim vars$ = String.Format(PayloadData, Token_lsd, Token_dtsg_Var, GQL_S_DOC_ID_2, GQL_S_NAME_2,
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(var_cursor2, IIf(Cursor.IsEmptyString, "null", $"""{Cursor}""")) & "}"))
If Cursor.IsEmptyString Then 'If Cursor.IsEmptyString Then
URL = String.Format(GQL_Q, Token_lsd, Token_dtsg_Var, GQL_S_DOC_ID_1, GQL_S_NAME_1, vars) ' URL = String.Format(GQL_Q, Token_lsd, Token_dtsg_Var, GQL_S_DOC_ID_1, GQL_S_NAME_1, vars)
Else 'Else
URL = String.Format(GQL_Q, Token_lsd, Token_dtsg_Var, GQL_S_DOC_ID_2, GQL_S_NAME_2, vars) ' URL = String.Format(GQL_Q, Token_lsd, Token_dtsg_Var, GQL_S_DOC_ID_2, GQL_S_NAME_2, vars)
End If 'End If
Using j As EContainer = GetDocument(URL, Token) Using j As EContainer = GetDocument(GQL_Q2, vars, Token)
If j.ListExists Then If Not CheckErrors(j) Then
With j({"data", "xdt_viewer", "text_app_saved_media"}) If j.ListExists Then
If .ListExists Then With j({"data", "xdt_text_app_viewer", "saved_media"})
nextCursor = .Value({"page_info"}, "end_cursor") If .ListExists Then
With .Item({"edges"}) nextCursor = .Value({"page_info"}, "end_cursor")
If .ListExists Then dataFound = DefaultParser(.Self, Sections.Timeline, Token) With .Item({"edges"})
End With If .ListExists Then dataFound = DefaultParser(.Self, Sections.Timeline, Token)
End If End With
End With End If
End With
End If
Else
Throw New JsonErrorException(JsonErrorMessage(j))
End If End If
End Using End Using
If dataFound And Not nextCursor.IsEmptyString Then DownloadSavedPosts(nextCursor, Token) If dataFound And Not nextCursor.IsEmptyString Then DownloadSavedPosts(nextCursor, 0, Token)
Catch uex As JsonErrorException
If Round > 0 Then
ProcessJsonErrorException(uex)
ElseIf Not _IdChanged AndAlso UpdateCredentials() Then
DownloadSavedPosts(Cursor, Round + 1, Token)
Else
ProcessJsonErrorException(uex)
End If
Catch eex As ExitException
Throw eex
Catch ex As Exception Catch ex As Exception
ProcessException(ex, Token, $"saved posts downloading error [{URL}]") ProcessException(ex, Token, "saved posts downloading error")
End Try End Try
End Sub End Sub
Private Function GetDocument(ByVal URL As String, ByVal Token As CancellationToken, Optional ByVal Round As Integer = 0) As EContainer Private Function GetDocument(ByVal URL As String, ByVal PayLoad As String, ByVal Token As CancellationToken, Optional ByVal Round As Integer = 0) As EContainer
Try Try
ThrowAny(Token) ThrowAny(Token)
If Round > 0 AndAlso Not UpdateCredentials() Then DisableDownload() : Throw New Exception("Failed to update credentials") If Round > 0 AndAlso Not UpdateCredentials() Then DisableDownload() : Throw New Exception("Failed to update credentials")
ThrowAny(Token) ThrowAny(Token)
WaitTimer() WaitTimer()
Dim r$ = Responser.GetResponse(URL) Dim r$ = Responser.GetResponse(URL, PayLoad)
If Not r.IsEmptyString Then Return JsonDocument.Parse(r) Else Throw New Exception("Failed to get a response") If Not r.IsEmptyString Then Return JsonDocument.Parse(r) Else Throw New Exception("Failed to get a response")
Catch ex As Exception Catch ex As Exception
If Round = 0 Then If Round = 0 Then
Return GetDocument(URL, Token, Round + 1) Return GetDocument(URL, PayLoad, Token, Round + 1)
Else Else
Throw ex Throw ex
End If End If
End Try End Try
End Function End Function
Private _IdChanged As Boolean = False
Private Function UpdateCredentials(Optional ByVal e As ErrorsDescriber = Nothing) As Boolean Private Function UpdateCredentials(Optional ByVal e As ErrorsDescriber = Nothing) As Boolean
Dim URL$ = If(IsSavedPosts, "https://www.threads.net/", $"https://www.threads.net/@{NameTrue}") Dim URL$ = If(IsSavedPosts, "https://www.threads.net/", $"https://www.threads.net/@{NameTrue}")
ResetBaseTokens() ResetBaseTokens()
@@ -294,9 +382,25 @@ Namespace API.ThreadsNet
End With End With
WaitTimer() WaitTimer()
Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException) Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException)
Dim newID$
Dim idStr$ = String.Empty
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
ParseTokens(r, 0) ParseTokens(r, 0)
If ID.IsEmptyString Then ID = RegexReplace(r, RParams.DMS("""props"":\{""user_id"":""(\d+)""", 1, EDP.ReturnValue)) newID = RegexReplace(r, RParams.DMS("""props"":\{[^\{\}]*?""user_id"":""(\d+)""", 1, EDP.ReturnValue))
If ID.IsEmptyString OrElse ID = newID Then
_IdChanged = ID.IsEmptyString
ID = newID
Else
_IdChanged = True
idStr = $"user ID changed from {ID} to {newID}"
LogError(Nothing, idStr)
ID = newID
End If
If _IdChanged Then
If Not idStr.IsEmptyString Then UserDescriptionUpdate(idStr, True, True, True)
_ForceSaveUserInfo = True
_ForceSaveUserInfoOnException = True
End If
End If End If
Return Valid Return Valid
Catch ex As Exception Catch ex As Exception
@@ -322,20 +426,22 @@ Namespace API.ThreadsNet
#End Region #End Region
#Region "ReparseMissing" #Region "ReparseMissing"
Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken) Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken)
Const varsPattern$ = """postID"":""{0}"",""userID"":""{1}"",""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsFeedbackHubEnabledrelayprovider"":false" 'Const varsPattern$ = """postID"":""{0}"",""userID"":""{1}"",""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsFeedbackHubEnabledrelayprovider"":false"
Const varsPattern$ = """postID"":""{0}"",""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaShouldShowFediverseM1Featuresrelayprovider"":true,""__relay_internal__pv__BarcelonaShareableListsrelayprovider"":true,""__relay_internal__pv__BarcelonaIsSearchDiscoveryEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaOptionalCookiesEnabledrelayprovider"":true,""__relay_internal__pv__BarcelonaQuotedPostUFIEnabledrelayprovider"":false,""__relay_internal__pv__BarcelonaIsCrawlerrelayprovider"":false,""__relay_internal__pv__BarcelonaHasDisplayNamesrelayprovider"":false,""__relay_internal__pv__BarcelonaCanSeeSponsoredContentrelayprovider"":false,""__relay_internal__pv__BarcelonaShouldShowFediverseM075Featuresrelayprovider"":true,""__relay_internal__pv__BarcelonaShouldShowTagRedesignrelayprovider"":false,""__relay_internal__pv__BarcelonaIsInternalUserrelayprovider"":false,""__relay_internal__pv__BarcelonaInlineComposerEnabledrelayprovider"":false"
'Const varsPattern$ = "{""postID"":""{0}"",""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsFeedbackHubEnabledrelayprovider"":false}" 'Const varsPattern$ = "{""postID"":""{0}"",""__relay_internal__pv__BarcelonaIsLoggedInrelayprovider"":true,""__relay_internal__pv__BarcelonaIsFeedbackHubEnabledrelayprovider"":false}"
Const urlPattern$ = "https://www.threads.net/api/graphql?lsd={0}&variables={1}&fb_api_req_friendly_name=BarcelonaPostPageQuery&server_timestamps=true&fb_dtsg={2}&doc_id=25460088156920903" 'Const urlPattern$ = "https://www.threads.net/api/graphql?lsd={0}&variables={1}&fb_api_req_friendly_name=BarcelonaPostPageQuery&server_timestamps=true&fb_dtsg={2}&doc_id=25460088156920903"
Dim rList As New List(Of Integer) Dim rList As New List(Of Integer)
Dim URL$ = String.Empty
DefaultParser_ElemNode = Nothing DefaultParser_ElemNode = Nothing
DefaultParser_IgnorePass = True DefaultParser_IgnorePass = True
Try Try
If ContentMissingExists Then If ContentMissingExists Then
Responser.Method = "POST" Responser.Method = "POST"
Responser.ContentType = "application/x-www-form-urlencoded"
Responser.Referer = $"https://www.threads.net/@{NameTrue}" Responser.Referer = $"https://www.threads.net/@{NameTrue}"
If Not IsSingleObjectDownload AndAlso Not UpdateCredentials() Then Throw New Exception("Failed to update credentials") If Not IsSingleObjectDownload AndAlso Not UpdateCredentials() Then Throw New Exception("Failed to update credentials")
Dim m As UserMedia Dim m As UserMedia
Dim vars$ Dim vars$
Dim r As Byte
Dim j As EContainer Dim j As EContainer
ProgressPre.ChangeMax(_ContentList.Count) ProgressPre.ChangeMax(_ContentList.Count)
For i% = 0 To _ContentList.Count - 1 For i% = 0 To _ContentList.Count - 1
@@ -343,21 +449,39 @@ Namespace API.ThreadsNet
m = _ContentList(i) m = _ContentList(i)
If m.State = UserMedia.States.Missing And Not m.Post.ID.IsEmptyString Then If m.State = UserMedia.States.Missing And Not m.Post.ID.IsEmptyString Then
ThrowAny(Token) ThrowAny(Token)
vars = SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(varsPattern, m.Post.ID.Split("_").FirstOrDefault, ID) & "}") 'vars = SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(varsPattern, m.Post.ID.Split("_").FirstOrDefault, ID) & "}")
URL = String.Format(urlPattern, Token_lsd, vars, Token_dtsg_Var) 'URL = String.Format(urlPattern, Token_lsd, vars, Token_dtsg_Var)
j = GetDocument(URL, Token) vars = String.Format(PayloadData, Token_lsd, Token_dtsg_Var, "9094233770675261", "BarcelonaPostPageDirectQuery",
If j.ListExists Then SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & String.Format(varsPattern, m.Post.ID) & "}"))
With j.ItemF({"data", "data", "edges", 0, "node", "thread_items", 0, "post"})
If .ListExists AndAlso DefaultParser({ .Self}, Sections.Timeline, Token) Then rList.Add(i) For r = 0 To 1
End With j = GetDocument(GQL_Q2, vars, Token)
j.Dispose() If Not CheckErrors(j) Then
End If If j.ListExists Then
With j.ItemF({"data", "data", "edges", 0, "node", "thread_items", 0, "post"})
If .ListExists AndAlso DefaultParser({ .Self}, Sections.Timeline, Token) Then rList.Add(i)
End With
j.Dispose()
End If
Else
j.DisposeIfReady(False)
If r > 0 Then
ProcessJsonErrorException(New JsonErrorException(JsonErrorMessage(j)))
ElseIf Not _IdChanged AndAlso UpdateCredentials() Then
Continue For
Else
ProcessJsonErrorException(New JsonErrorException(JsonErrorMessage(j)))
End If
End If
Next
End If End If
Next Next
End If End If
Catch eex As ExitException
Throw eex
Catch ex As Exception Catch ex As Exception
ProcessException(ex, Token, $"ReparseMissing error [{URL}]") ProcessException(ex, Token, "reparseMissing error")
Finally Finally
DefaultParser_ElemNode = DefaultParser_ElemNode_Default DefaultParser_ElemNode = DefaultParser_ElemNode_Default
DefaultParser_IgnorePass = False DefaultParser_IgnorePass = False
@@ -375,9 +499,9 @@ Namespace API.ThreadsNet
If Not postCode.IsEmptyString Then If Not postCode.IsEmptyString Then
Dim postId$ = CodeToID(postCode) Dim postId$ = CodeToID(postCode)
If Not postId.IsEmptyString Then If Not postId.IsEmptyString Then
_NameTrue = MySettings.IsMyUser(url).UserName NameTrue = MySettings.IsMyUser(url).UserName
DefaultParser_PostUrlCreator = Function(post) url DefaultParser_PostUrlCreator = Function(post) url
If Not _NameTrue.IsEmptyString AndAlso UpdateCredentials(EDP.ReturnValue) Then If Not NameTrue(True).IsEmptyString AndAlso UpdateCredentials(EDP.ReturnValue) Then
_ContentList.Add(New UserMedia(url) With {.State = UserMedia.States.Missing, .Post = postId}) _ContentList.Add(New UserMedia(url) With {.State = UserMedia.States.Missing, .Post = postId})
ReparseMissing(Token) ReparseMissing(Token)
End If End If

View File

@@ -62,8 +62,5 @@ Namespace API.TikTok
Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using Using f As New InternalSettingsForm(Options, Me, False) : f.ShowDialog() : End Using
End If End If
End Sub End Sub
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
Return String.Format(UrlPatternUser, DirectCast(User, UserData).TrueName)
End Function
End Class End Class
End Namespace End Namespace

View File

@@ -62,15 +62,6 @@ Namespace API.TikTok
Friend Property TitleUseRegexForTitle_Value As String = String.Empty Friend Property TitleUseRegexForTitle_Value As String = String.Empty
Friend Property TitleUseGlobalRegexOptions As Boolean = True Friend Property TitleUseGlobalRegexOptions As Boolean = True
Private Property LastDownloadDate As Date? = Nothing Private Property LastDownloadDate As Date? = Nothing
Private _TrueName As String = String.Empty
Friend Property TrueName As String
Get
Return _TrueName.IfNullOrEmpty(Name)
End Get
Set(ByVal NewName As String)
_TrueName = NewName
End Set
End Property
#End Region #End Region
#Region "Exchange" #Region "Exchange"
Friend Overrides Function ExchangeOptionsGet() As Object Friend Overrides Function ExchangeOptionsGet() As Object
@@ -98,7 +89,6 @@ Namespace API.TikTok
TitleAddVideoID = .Value(Name_TitleAddVideoID).FromXML(Of Boolean)(True) TitleAddVideoID = .Value(Name_TitleAddVideoID).FromXML(Of Boolean)(True)
LastDownloadDate = AConvert(Of Date)(.Value(Name_LastDownloadDate), ADateTime.Formats.BaseDateTime, Nothing) LastDownloadDate = AConvert(Of Date)(.Value(Name_LastDownloadDate), ADateTime.Formats.BaseDateTime, Nothing)
If Not LastDownloadDate.HasValue Then LastDownloadDate = LastUpdated If Not LastDownloadDate.HasValue Then LastDownloadDate = LastUpdated
_TrueName = .Value(Name_TrueName)
TitleUseRegexForTitle = .Value(Name_TitleUseRegexForTitle).FromXML(Of Boolean)(False) TitleUseRegexForTitle = .Value(Name_TitleUseRegexForTitle).FromXML(Of Boolean)(False)
TitleUseRegexForTitle_Value = .Value(Name_TitleUseRegexForTitle_Value) TitleUseRegexForTitle_Value = .Value(Name_TitleUseRegexForTitle_Value)
TitleUseGlobalRegexOptions = .Value(Name_TitleUseGlobalRegexOptions).FromXML(Of Boolean)(True) TitleUseGlobalRegexOptions = .Value(Name_TitleUseGlobalRegexOptions).FromXML(Of Boolean)(True)
@@ -107,7 +97,6 @@ Namespace API.TikTok
.Add(Name_TitleUseNative, TitleUseNative.BoolToInteger) .Add(Name_TitleUseNative, TitleUseNative.BoolToInteger)
.Add(Name_TitleAddVideoID, TitleAddVideoID.BoolToInteger) .Add(Name_TitleAddVideoID, TitleAddVideoID.BoolToInteger)
.Add(Name_LastDownloadDate, AConvert(Of String)(LastDownloadDate, AModes.XML, ADateTime.Formats.BaseDateTime, String.Empty)) .Add(Name_LastDownloadDate, AConvert(Of String)(LastDownloadDate, AModes.XML, ADateTime.Formats.BaseDateTime, String.Empty))
.Add(Name_TrueName, _TrueName)
.Add(Name_TitleUseRegexForTitle, TitleUseRegexForTitle.BoolToInteger) .Add(Name_TitleUseRegexForTitle, TitleUseRegexForTitle.BoolToInteger)
.Add(Name_TitleUseRegexForTitle_Value, TitleUseRegexForTitle_Value) .Add(Name_TitleUseRegexForTitle_Value, TitleUseRegexForTitle_Value)
.Add(Name_TitleUseGlobalRegexOptions, TitleUseGlobalRegexOptions.BoolToInteger) .Add(Name_TitleUseGlobalRegexOptions, TitleUseGlobalRegexOptions.BoolToInteger)
@@ -174,7 +163,7 @@ Namespace API.TikTok
UserCache = Nothing UserCache = Nothing
End Sub End Sub
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
Dim URL$ = $"https://www.tiktok.com/@{TrueName}" Dim URL$ = $"https://www.tiktok.com/@{NameTrue}"
UserCache = CreateCache() UserCache = CreateCache()
Try Try
Dim postID$, title$, postUrl$, newName$ Dim postID$, title$, postUrl$, newName$
@@ -232,10 +221,7 @@ Namespace API.TikTok
If Not ID.IsEmptyString Then _ForceSaveUserInfo = True If Not ID.IsEmptyString Then _ForceSaveUserInfo = True
End If End If
newName = j.Value("uploader") newName = j.Value("uploader")
If Not newName.IsEmptyString Then If Not newName.IsEmptyString Then NameTrue = newName
If Not _TrueName = newName Then _ForceSaveUserInfo = True
_TrueName = newName
End If
newName = j.Value("creator") newName = j.Value("creator")
If Not newName.IsEmptyString Then UserSiteName = newName If Not newName.IsEmptyString Then UserSiteName = newName
End If End If

View File

@@ -7,7 +7,7 @@
' This program is distributed in the hope that it will be useful, ' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY ' but WITHOUT ANY WARRANTY
Imports System.Globalization Imports System.Globalization
Imports PersonalUtilities.Functions.XML.Base Imports System.Text.RegularExpressions
Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Functions.RegularExpressions
Namespace API.Twitter Namespace API.Twitter
Friend Module Declarations Friend Module Declarations
@@ -17,6 +17,8 @@ Namespace API.Twitter
Friend ReadOnly VideoSizeRegEx As RParams = RParams.DMS("\d+x(\d+)", 1, EDP.ReturnValue) Friend ReadOnly VideoSizeRegEx As RParams = RParams.DMS("\d+x(\d+)", 1, EDP.ReturnValue)
Friend ReadOnly StatusRegEx As RParams = RParams.DM(".*?(twitter|x)\.com/\S+/status/\d+", 0, EDP.ReturnValue) Friend ReadOnly StatusRegEx As RParams = RParams.DM(".*?(twitter|x)\.com/\S+/status/\d+", 0, EDP.ReturnValue)
Friend ReadOnly BroadcastsUrls As Object() = {"entities", "urls", 0, "expanded_url"} Friend ReadOnly BroadcastsUrls As Object() = {"entities", "urls", 0, "expanded_url"}
Friend ReadOnly GdlLimitRegEx As RParams = RParams.DM("Waiting until[\s\W\d\:]+\(rate limit\)", 0, RegexOptions.IgnoreCase, EDP.ReturnValue)
Friend ReadOnly GdlPostCoutNumberNodes As String() = {"data", "user", "result", "legacy", "statuses_count"}
Private Function GetDateProvider() As ADateTime Private Function GetDateProvider() As ADateTime
Dim n As DateTimeFormatInfo = CultureInfo.GetCultureInfo("en-us").DateTimeFormat.Clone Dim n As DateTimeFormatInfo = CultureInfo.GetCultureInfo("en-us").DateTimeFormat.Clone
n.FullDateTimePattern = "ddd MMM dd HH:mm:ss +ffff yyyy" n.FullDateTimePattern = "ddd MMM dd HH:mm:ss +ffff yyyy"

View File

@@ -8,11 +8,10 @@
' but WITHOUT ANY WARRANTY ' but WITHOUT ANY WARRANTY
Imports SCrawler.Plugin.Attributes Imports SCrawler.Plugin.Attributes
Imports DModels = SCrawler.API.Twitter.UserData.DownloadModels Imports DModels = SCrawler.API.Twitter.UserData.DownloadModels
Imports DN = SCrawler.API.Base.DeclaredNames
Namespace API.Twitter Namespace API.Twitter
Friend Class EditorExchangeOptions Friend Class EditorExchangeOptions : Inherits Base.EditorExchangeOptionsBase
Private Const DefaultOffset As Integer = 100 Private Const DefaultOffset As Integer = 100
Friend Property SiteKey As String = TwitterSiteKey Friend Overrides Property SiteKey As String = TwitterSiteKey
<PSetting(NameOf(SiteSettings.GifsDownload), NameOf(MySettings), LeftOffset:=DefaultOffset)> <PSetting(NameOf(SiteSettings.GifsDownload), NameOf(MySettings), LeftOffset:=DefaultOffset)>
Friend Property GifsDownload As Boolean Friend Property GifsDownload As Boolean
<PSetting(NameOf(SiteSettings.GifsSpecialFolder), NameOf(MySettings), LeftOffset:=DefaultOffset)> <PSetting(NameOf(SiteSettings.GifsSpecialFolder), NameOf(MySettings), LeftOffset:=DefaultOffset)>
@@ -51,8 +50,6 @@ Namespace API.Twitter
Caption:="Force apply", Caption:="Force apply",
ToolTip:="Force overrides the default parameters for the first download." & vbCr & "Applies to first download only.", LeftOffset:=DefaultOffset)> ToolTip:="Force overrides the default parameters for the first download." & vbCr & "Applies to first download only.", LeftOffset:=DefaultOffset)>
Friend Overridable Property DownloadModelForceApply As Boolean = False Friend Overridable Property DownloadModelForceApply As Boolean = False
<PSetting(Address:=SettingAddress.User, Caption:=DN.UserNameChangeCaption, ToolTip:=DN.UserNameChangeToolTip, LeftOffset:=DefaultOffset)>
Friend Overridable Property UserName As String = String.Empty
Private ReadOnly Property MySettings As Object Private ReadOnly Property MySettings As Object
Friend Sub New(ByVal s As SiteSettings) Friend Sub New(ByVal s As SiteSettings)
GifsDownload = s.GifsDownload.Value GifsDownload = s.GifsDownload.Value
@@ -71,6 +68,7 @@ Namespace API.Twitter
MySettings = s MySettings = s
End Sub End Sub
Friend Sub New(ByVal u As UserData) Friend Sub New(ByVal u As UserData)
MyBase.New(u)
GifsDownload = u.GifsDownload GifsDownload = u.GifsDownload
GifsSpecialFolder = u.GifsSpecialFolder GifsSpecialFolder = u.GifsSpecialFolder
GifsPrefix = u.GifsPrefix GifsPrefix = u.GifsPrefix
@@ -88,7 +86,6 @@ Namespace API.Twitter
DownloadModelLikes = dm.Contains(DModels.Likes) DownloadModelLikes = dm.Contains(DModels.Likes)
End If End If
End If End If
UserName = u.NameTrue(True)
MySettings = u.HOST.Source MySettings = u.HOST.Source
End Sub End Sub
End Class End Class

View File

@@ -11,14 +11,50 @@ Imports SCrawler.Plugin
Imports SCrawler.Plugin.Attributes Imports SCrawler.Plugin.Attributes
Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Functions.RegularExpressions
Imports PersonalUtilities.Tools.Web.Clients Imports PersonalUtilities.Tools.Web.Clients
Imports PersonalUtilities.Tools.Web.Cookies
Imports DN = SCrawler.API.Base.DeclaredNames Imports DN = SCrawler.API.Base.DeclaredNames
Imports IG = SCrawler.API.Instagram.SiteSettings
Namespace API.Twitter Namespace API.Twitter
<Manifest(TwitterSiteKey), SavedPosts, SeparatedTasks, SpecialForm(False)> <Manifest(TwitterSiteKey), SavedPosts, SeparatedTasks, SpecialForm(False)>
Friend Class SiteSettings : Inherits SiteSettingsBase Friend Class SiteSettings : Inherits SiteSettingsBase
#Region "Declarations" #Region "Declarations"
#Region "Icon"
<PXML("UseNewIcon")> Private ReadOnly Property UseNewIconXML As PropertyValue
<PropertyOption(ControlText:="Use the new Twitter icon (X)", ControlToolTip:="Restart SCrawler to take effect")>
Private ReadOnly Property UseNewIcon As PropertyValue
Get
If Not DefaultInstance Is Nothing Then
Return DirectCast(DefaultInstance, SiteSettings).UseNewIconXML
Else
Return UseNewIconXML
End If
End Get
End Property
Private Sub UpdateIcon()
If CBool(UseNewIcon.Value) Then _Icon = My.Resources.SiteResources.TwitterIconNew_32 : _Image = _Icon.ToBitmap
End Sub
#End Region
#Region "Categories" #Region "Categories"
Private Const CAT_DOWN As String = "Downloading" Private Const CAT_DOWN As String = "Downloading"
#End Region #End Region
#Region "Auth"
<PropertyOption(ControlText:="Update cookies", ControlToolTip:="Update cookies during requests", IsAuth:=True), PXML, PClonable, HiddenControl>
Friend ReadOnly Property CookiesUpdate As PropertyValue
<PropertyOption(ControlText:="Use UserAgent", ControlToolTip:="Use UserAgent in requests", IsAuth:=True), PXML, PClonable>
Friend ReadOnly Property UserAgentUse As PropertyValue
<PropertyOption(ControlText:="UserAgent", IsAuth:=True, AllowNull:=True, InheritanceName:=SettingsCLS.HEADER_DEF_UserAgent),
PXML("UserAgent", OnlyForChecked:=True), PClonable>
Private ReadOnly Property UserAgentXML As PropertyValue
Friend ReadOnly Property UserAgent As String
Get
If CBool(UserAgentUse.Value) AndAlso Not CStr(UserAgentXML.Value).IsEmptyString Then
Return UserAgentXML.Value
Else
Return String.Empty
End If
End Get
End Property
#End Region
#Region "Other properties" #Region "Other properties"
<PropertyOption(ControlText:="Use the appropriate model", <PropertyOption(ControlText:="Use the appropriate model",
ControlToolTip:="Use the appropriate model for new users." & vbCr & ControlToolTip:="Use the appropriate model for new users." & vbCr &
@@ -35,10 +71,30 @@ Namespace API.Twitter
Friend Property UseNewEndPointProfiles As PropertyValue Friend Property UseNewEndPointProfiles As PropertyValue
#End Region #End Region
#Region "Limits" #Region "Limits"
Friend Const TimerDisabled As Integer = -1
Friend Const TimerFirstUseTheSame As Integer = -2
<PropertyOption(ControlText:="Abort on limit", ControlToolTip:="Abort twitter downloading when limit is reached", Category:=CAT_DOWN), PXML, PClonable> <PropertyOption(ControlText:="Abort on limit", ControlToolTip:="Abort twitter downloading when limit is reached", Category:=CAT_DOWN), PXML, PClonable>
Friend Property AbortOnLimit As PropertyValue Friend Property AbortOnLimit As PropertyValue
<PropertyOption(ControlText:="Download already parsed", ControlToolTip:="Download already parsed content on abort", Category:=CAT_DOWN), PXML, PClonable> <PropertyOption(ControlText:="Download already parsed", ControlToolTip:="Download already parsed content on abort", Category:=CAT_DOWN), PXML, PClonable>
Friend Property DownloadAlreadyParsed As PropertyValue Friend Property DownloadAlreadyParsed As PropertyValue
#End Region
#Region "Timers"
<PropertyOption(ControlText:="Sleep timer",
ControlToolTip:="Use sleep timer in requests." & vbCr &
"You can set a timer value (in seconds) to wait before each subsequent request." & vbCr &
"-1 to disable and use the default algorithm." & vbCr &
"Default: 20", Category:=CAT_DOWN), PXML, PClonable>
Friend ReadOnly Property SleepTimer As PropertyValue
<Provider(NameOf(SleepTimer), FieldsChecker:=True)>
Private ReadOnly Property SleepTimerProvider As IFormatProvider
<PropertyOption(ControlText:="Sleep timer at start",
ControlToolTip:="Set a sleep timer (in seconds) before the first request." & vbCr &
"-1 to disable" & vbCr &
"-2 to use the 'Sleep timer' value" & vbCr &
"Default: -2", Category:=CAT_DOWN), PXML, PClonable>
Friend ReadOnly Property SleepTimerBeforeFirst As PropertyValue
<Provider(NameOf(SleepTimerBeforeFirst), FieldsChecker:=True)>
Private ReadOnly Property SleepTimerBeforeFirstProvider As IFormatProvider
#End Region #End Region
<PropertyOption(ControlText:="Media Model: allow non-user tweets", ControlToolTip:="Allow downloading non-user tweets in the media-model.", Category:=DN.CAT_UserDefs), PXML, PClonable> <PropertyOption(ControlText:="Media Model: allow non-user tweets", ControlToolTip:="Allow downloading non-user tweets in the media-model.", Category:=DN.CAT_UserDefs), PXML, PClonable>
Friend ReadOnly Property MediaModelAllowNonUserTweets As PropertyValue Friend ReadOnly Property MediaModelAllowNonUserTweets As PropertyValue
@@ -76,7 +132,17 @@ Namespace API.Twitter
<Provider(NameOf(ConcurrentDownloads), FieldsChecker:=True)> <Provider(NameOf(ConcurrentDownloads), FieldsChecker:=True)>
Private ReadOnly Property MyConcurrentDownloadsProvider As IFormatProvider Private ReadOnly Property MyConcurrentDownloadsProvider As IFormatProvider
#End Region #End Region
Friend Overrides Property DefaultInstance As ISiteSettings
Get
Return MyBase.DefaultInstance
End Get
Set(ByVal Instance As ISiteSettings)
MyBase.DefaultInstance = Instance
If Not Instance Is Nothing Then UpdateIcon()
End Set
End Property
#End Region #End Region
#Region "Initializer"
Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean) Friend Sub New(ByVal AccName As String, ByVal Temp As Boolean)
MyBase.New(TwitterSite, "x.com", AccName, Temp, My.Resources.SiteResources.TwitterIcon_32, My.Resources.SiteResources.TwitterIcon_32.ToBitmap) MyBase.New(TwitterSite, "x.com", AccName, Temp, My.Resources.SiteResources.TwitterIcon_32, My.Resources.SiteResources.TwitterIcon_32.ToBitmap)
@@ -87,11 +153,28 @@ Namespace API.Twitter
.Cookies.Changed = False .Cookies.Changed = False
End With End With
UseNewIconXML = New PropertyValue(False)
CookiesUpdate = New PropertyValue(False)
UserAgentUse = New PropertyValue(True)
UserAgentXML = New PropertyValue(If(Responser.UserAgentExists, Responser.UserAgent, String.Empty), GetType(String),
Sub(ByVal Value As Object)
Responser.UserAgent = CStr(Value)
Responser.SaveSettings(, EDP.ReturnValue)
End Sub)
UseAppropriateModel = New PropertyValue(True) UseAppropriateModel = New PropertyValue(True)
UseNewEndPointSearch = New PropertyValue(True) UseNewEndPointSearch = New PropertyValue(True)
UseNewEndPointProfiles = New PropertyValue(True) UseNewEndPointProfiles = New PropertyValue(True)
AbortOnLimit = New PropertyValue(True) AbortOnLimit = New PropertyValue(True)
DownloadAlreadyParsed = New PropertyValue(True) DownloadAlreadyParsed = New PropertyValue(True)
SleepTimer = New PropertyValue(TimerDisabled)
SleepTimerProvider = New IG.TimersChecker(TimerDisabled)
SleepTimerBeforeFirst = New PropertyValue(TimerFirstUseTheSame)
SleepTimerBeforeFirstProvider = New IG.TimersChecker(TimerFirstUseTheSame)
MediaModelAllowNonUserTweets = New PropertyValue(False) MediaModelAllowNonUserTweets = New PropertyValue(False)
GifsDownload = New PropertyValue(True) GifsDownload = New PropertyValue(True)
GifsSpecialFolder = New PropertyValue(String.Empty, GetType(String)) GifsSpecialFolder = New PropertyValue(String.Empty, GetType(String))
@@ -101,28 +184,60 @@ Namespace API.Twitter
ConcurrentDownloads = New PropertyValue(1) ConcurrentDownloads = New PropertyValue(1)
MyConcurrentDownloadsProvider = New ConcurrentDownloadsProvider MyConcurrentDownloadsProvider = New ConcurrentDownloadsProvider
_AllowUserAgentUpdate = False
UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, $"/(twitter|x).com({CommunitiesUser}|)/"), 3) UserRegex = RParams.DMS(String.Format(UserRegexDefaultPattern, $"/(twitter|x).com({CommunitiesUser}|)/"), 3)
UrlPatternUser = "https://x.com/{0}" UrlPatternUser = "https://x.com/{0}"
ImageVideoContains = "twitter" ImageVideoContains = "twitter"
CheckNetscapeCookiesOnEndInit = True CheckNetscapeCookiesOnEndInit = True
UseNetscapeCookies = True UseNetscapeCookies = True
End Sub End Sub
Friend Overrides Sub EndInit()
UpdateIcon()
MyBase.EndInit()
End Sub
#End Region
#Region "GetInstance"
Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider Friend Overrides Function GetInstance(ByVal What As ISiteSettings.Download) As IPluginContentProvider
Return New UserData Return New UserData
End Function End Function
Friend Const SinglePostPattern As String = "https://x.com/i/web/status/{0}" #End Region
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String #Region "BaseAuthExists, Available"
Return String.Format(SinglePostPattern, Media.Post.ID)
End Function
Friend Overrides Function BaseAuthExists() As Boolean Friend Overrides Function BaseAuthExists() As Boolean
Return Responser.CookiesExists Return Responser.CookiesExists
End Function End Function
Friend Overrides Function Available(ByVal What As ISiteSettings.Download, ByVal Silent As Boolean) As Boolean Friend Overrides Function Available(ByVal What As ISiteSettings.Download, ByVal Silent As Boolean) As Boolean
Return Settings.GalleryDLFile.Exists And BaseAuthExists() Return Settings.GalleryDLFile.Exists And BaseAuthExists()
End Function End Function
#End Region
#Region "Download"
Friend Property LIMIT_ABORT As Boolean = False Friend Property LIMIT_ABORT As Boolean = False
Friend ReadOnly Property LimitSkippedUsers As List(Of UserDataBase) Friend ReadOnly Property LimitSkippedUsers As List(Of UserDataBase)
Friend Property UserNumber As Integer = -1
Friend Overrides Sub DownloadStarted(ByVal What As ISiteSettings.Download)
UserNumber = 0
MyBase.DownloadStarted(What)
End Sub
Friend Overrides Sub AfterDownload(ByVal User As Object, ByVal What As ISiteSettings.Download)
If Not User Is Nothing AndAlso DirectCast(User, UserData).GDL_REQUESTS_COUNT > 0 Then UserNumber += 1
MyBase.AfterDownload(User, What)
End Sub
Friend Overrides Sub DownloadDone(ByVal What As ISiteSettings.Download) Friend Overrides Sub DownloadDone(ByVal What As ISiteSettings.Download)
If UserNumber > 0 Then
If CBool(CookiesUpdate.Value) Then
With CookieKeeper.ParseNetscapeText(CookiesNetscapeFile.GetText(EDP.ReturnValue), EDP.ReturnValue)
If .ListExists Then
Responser.Cookies.Clear()
Responser.Cookies.AddRange(.Self,, EDP.ReturnValue)
Responser.SaveCookies(EDP.ReturnValue)
Else
Update_SaveCookiesNetscape(True)
End If
End With
Else
Update_SaveCookiesNetscape(True)
End If
End If
UserNumber = -1
If LimitSkippedUsers.Count > 0 Then If LimitSkippedUsers.Count > 0 Then
With LimitSkippedUsers With LimitSkippedUsers
If .Count = 1 Then If .Count = 1 Then
@@ -137,6 +252,8 @@ Namespace API.Twitter
LIMIT_ABORT = False LIMIT_ABORT = False
MyBase.DownloadDone(What) MyBase.DownloadDone(What)
End Sub End Sub
#End Region
#Region "UserOptions, Update"
Friend Overrides Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean) Friend Overrides Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean)
If Options Is Nothing OrElse (Not TypeOf Options Is EditorExchangeOptions OrElse If Options Is Nothing OrElse (Not TypeOf Options Is EditorExchangeOptions OrElse
Not DirectCast(Options, EditorExchangeOptions).SiteKey = TwitterSiteKey) Then _ Not DirectCast(Options, EditorExchangeOptions).SiteKey = TwitterSiteKey) Then _
@@ -152,6 +269,8 @@ Namespace API.Twitter
End If End If
MyBase.Update() MyBase.Update()
End Sub End Sub
#End Region
#Region "IsMyUser, IsMyImageVideo, GetUserPostUrl, GetUserUrl"
Friend Const CommunitiesUser As String = "/i/communities" Friend Const CommunitiesUser As String = "/i/communities"
Friend Overrides Function IsMyUser(ByVal UserURL As String) As ExchangeOptions Friend Overrides Function IsMyUser(ByVal UserURL As String) As ExchangeOptions
Dim e As ExchangeOptions = MyBase.IsMyUser(UserURL) Dim e As ExchangeOptions = MyBase.IsMyUser(UserURL)
@@ -169,8 +288,13 @@ Namespace API.Twitter
Return Nothing Return Nothing
End If End If
End Function End Function
Friend Const SinglePostPattern As String = "https://x.com/i/web/status/{0}"
Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
Return String.Format(SinglePostPattern, Media.Post.ID)
End Function
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider) As String
Return DirectCast(User, UserData).GetUserUrl Return DirectCast(User, UserData).GetUserUrl
End Function End Function
#End Region
End Class End Class
End Namespace End Namespace

View File

@@ -35,15 +35,6 @@ Namespace API.Twitter
#Region "Declarations" #Region "Declarations"
Private Const BroadCastPartUrl As String = "i/broadcasts" Private Const BroadCastPartUrl As String = "i/broadcasts"
Private Const Label_Community As String = "Community" Private Const Label_Community As String = "Community"
Private _NameTrue As String = String.Empty
Friend Property NameTrue(Optional ByVal Exact As Boolean = False) As String
Get
Return If(Exact, _NameTrue, _NameTrue.IfNullOrEmpty(Name))
End Get
Set(ByVal NewName As String)
_NameTrue = NewName
End Set
End Property
Friend Overrides ReadOnly Property SpecialLabels As IEnumerable(Of String) Friend Overrides ReadOnly Property SpecialLabels As IEnumerable(Of String)
Get Get
Return {Label_Community} Return {Label_Community}
@@ -114,7 +105,7 @@ Namespace API.Twitter
If .DownloadModelSearch Then DownloadModel += DownloadModels.Search If .DownloadModelSearch Then DownloadModel += DownloadModels.Search
If .DownloadModelLikes Then DownloadModel += DownloadModels.Likes If .DownloadModelLikes Then DownloadModel += DownloadModels.Likes
If Not dModel = DownloadModel Then DownloadModelChanged = True If Not dModel = DownloadModel Then DownloadModelChanged = True
_NameTrue = .UserName NameTrue = .UserName
End With End With
End If End If
End Sub End Sub
@@ -164,12 +155,11 @@ Namespace API.Twitter
StartMD5Checked = .Value(Name_StartMD5Checked).FromXML(Of Boolean)(False) StartMD5Checked = .Value(Name_StartMD5Checked).FromXML(Of Boolean)(False)
MediaModelAllowNonUserTweets = .Value(Name_MediaModelAllowNonUserTweets).FromXML(Of Boolean)(False) MediaModelAllowNonUserTweets = .Value(Name_MediaModelAllowNonUserTweets).FromXML(Of Boolean)(False)
IsCommunity = .Value(Name_IsCommunity).FromXML(Of Boolean)(False) IsCommunity = .Value(Name_IsCommunity).FromXML(Of Boolean)(False)
_NameTrue = .Value(Name_TrueName)
Else Else
If Name.Contains("@") And Not IsCommunity Then If Name.Contains("@") And Not IsCommunity Then
IsCommunity = True IsCommunity = True
_NameTrue = Name.Split("@")(0) NameTrue = Name.Split("@")(0)
ID = _NameTrue ID = NameTrue
ParseUserMediaOnly = False ParseUserMediaOnly = False
Labels.ListAddValue(Label_Community, LNC) Labels.ListAddValue(Label_Community, LNC)
Labels.Sort() Labels.Sort()
@@ -190,7 +180,7 @@ Namespace API.Twitter
.Add(Name_StartMD5Checked, StartMD5Checked.BoolToInteger) .Add(Name_StartMD5Checked, StartMD5Checked.BoolToInteger)
.Add(Name_MediaModelAllowNonUserTweets, MediaModelAllowNonUserTweets.BoolToInteger) .Add(Name_MediaModelAllowNonUserTweets, MediaModelAllowNonUserTweets.BoolToInteger)
.Add(Name_IsCommunity, IsCommunity.BoolToInteger) .Add(Name_IsCommunity, IsCommunity.BoolToInteger)
.Add(Name_TrueName, _NameTrue) .Add(Name_TrueName, NameTrue(True))
End If End If
End With End With
End Sub End Sub
@@ -266,8 +256,10 @@ Namespace API.Twitter
End If End If
Return result Return result
End Function End Function
Friend Property GDL_REQUESTS_COUNT As Integer = 0
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
Try Try
GDL_REQUESTS_COUNT = 0
If MySettings.LIMIT_ABORT Then If MySettings.LIMIT_ABORT Then
Throw New TwitterLimitException(Me) Throw New TwitterLimitException(Me)
Else Else
@@ -426,17 +418,7 @@ Namespace API.Twitter
userInfoParsed = True userInfoParsed = True
Dim resValue$ = j.Value({"data", IIf(IsCommunity, "communityResults", "user"), "result"}, "__typename").StringTrim.StringToLower Dim resValue$ = j.Value({"data", IIf(IsCommunity, "communityResults", "user"), "result"}, "__typename").StringTrim.StringToLower
Dim icon$ Dim icon$
Dim __getImage As Action(Of String) = Sub(ByVal img As String) Dim fileCrFunc As Func(Of String, SFile) = Function(img) UrlFile(img, True)
If Not img.IsEmptyString Then
Dim __imgFile As SFile = UrlFile(img, True)
If Not __imgFile.Name.IsEmptyString Then
If __imgFile.Extension.IsEmptyString Then __imgFile.Extension = "jpg"
__imgFile.Path = MyFile.CutPath.Path
If Not __imgFile.Exists Then GetWebFile(img, __imgFile, EDP.None)
If __imgFile.Exists Then IconBannerDownloaded = True
End If
End If
End Sub
If resValue.IsEmptyString Then If resValue.IsEmptyString Then
UserExists = False UserExists = False
j.Dispose() j.Dispose()
@@ -458,7 +440,7 @@ Namespace API.Twitter
icon = .Value({"custom_banner_media", "media_info"}, "original_img_url"). icon = .Value({"custom_banner_media", "media_info"}, "original_img_url").
IfNullOrEmpty(.Value({"default_banner_media", "media_info"}, "original_img_url")) IfNullOrEmpty(.Value({"default_banner_media", "media_info"}, "original_img_url"))
If Not icon.IsEmptyString And DownloadIconBanner Then __getImage.Invoke(icon) If Not icon.IsEmptyString And DownloadIconBanner Then SimpleDownloadAvatar(icon, fileCrFunc)
End If End If
End If End If
End With End With
@@ -484,8 +466,8 @@ Namespace API.Twitter
icon = .Value("profile_image_url_https") icon = .Value("profile_image_url_https")
If Not icon.IsEmptyString Then icon = icon.Replace("_normal", String.Empty) If Not icon.IsEmptyString Then icon = icon.Replace("_normal", String.Empty)
If DownloadIconBanner Then If DownloadIconBanner Then
__getImage.Invoke(.Value("profile_banner_url")) SimpleDownloadAvatar(.Value("profile_banner_url"), fileCrFunc)
__getImage.Invoke(icon) SimpleDownloadAvatar(icon, fileCrFunc)
End If End If
End If End If
End If End If
@@ -799,19 +781,87 @@ nextpIndx:
End Sub End Sub
Private Sub CheckForLimit(ByVal Value As String) Private Sub CheckForLimit(ByVal Value As String)
If Token.IsCancellationRequested Or (KillOnLimit AndAlso Not ProcessKilled AndAlso If Token.IsCancellationRequested Or (KillOnLimit AndAlso Not ProcessKilled AndAlso
Not Value.IsEmptyString AndAlso Value.ToLower.Contains("for rate limit reset")) Then Not Value.IsEmptyString AndAlso (Value.ToLower.Contains("for rate limit reset") OrElse
Not CStr(RegexReplace(Value, GdlLimitRegEx)).IsEmptyString)) Then
LimitReached = True LimitReached = True
Kill() Kill()
End If End If
End Sub End Sub
End Class End Class
Private ReadOnly Property SleepTimerValue(ByVal First As Boolean) As Integer
Get
Dim fTimer% = If(First, MySettings.SleepTimerBeforeFirst, MySettings.SleepTimer).Value
If First And fTimer = SiteSettings.TimerFirstUseTheSame Then fTimer = MySettings.SleepTimer.Value
Return fTimer
End Get
End Property
Private ReadOnly Property SleepRequest As String
Get
Dim s% = SleepTimerValue(False)
Return If(s = SiteSettings.TimerDisabled, String.Empty, $" --sleep-request {s}")
End Get
End Property
Private Sub GdlWaitFirstTimer(ByVal fTimer As Integer)
If GDL_REQUESTS_COUNT = 0 And Not fTimer = SiteSettings.TimerDisabled And MySettings.UserNumber > 0 Then Thread.Sleep(fTimer * 1000)
GDL_REQUESTS_COUNT += 1
End Sub
Private _GdlPreProgressPerformEnabled As Boolean = False
Private Sub GdlPreProgressPerform(ByVal Path As SFile, ByVal UpDir As SFile)
Dim f As SFile = Nothing
Try
Dim c% = -1, lb% = -1, cc%
Dim e As New ErrorsDescriber(EDP.ReturnValue)
While _GdlPreProgressPerformEnabled
Thread.Sleep(100)
If c > 0 Then
cc = If(SFile.GetFiles(Path,,, e)?.Count, 0)
If cc > c Then
Exit Sub
ElseIf cc > 0 And (lb = -1 Or cc > lb) Then
ProgressPre.Perform(cc - IIf(lb = -1, 0, lb))
lb = cc
End If
ElseIf Path.Exists(SFO.Path, False) Then
Dim files As List(Of SFile) = SFile.GetFiles(Path,,, e)
If files.ListExists Then
f = files.FirstOrDefault(Function(ff) Not ff.Name.IsEmptyString AndAlso ff.Name.StartsWith("01_"))
If UpDir.Exists(SFO.Path, False) Then
Dim fNew As SFile = $"{UpDir.PathWithSeparator}00.txt"
If f.Copy(fNew,, True, SFODelete.DeletePermanently,, e) Then
f = fNew
Using j As EContainer = JsonDocument.Parse(f.GetText(e), e)
If j.ListExists Then
c = j(GdlPostCoutNumberNodes).XmlIfNothingValue.FromXML(Of Integer)(-1)
If c > 0 Then c /= 30 : ProgressPre.ChangeMax(c) : Continue While
End If
End Using
End If
End If
Exit Sub
End If
End If
End While
Catch ex As Exception
ErrorsDescriber.Execute(EDP.SendToLog, ex, $"{ToStringForLog()}:{vbCr}Path: '{Path.Path}'{vbCr}Path 2: '{UpDir.Path}'")
Finally
If f.Exists Then f.Delete(SFO.File, SFODelete.DeletePermanently, EDP.ReturnValue)
End Try
End Sub
Private Sub GdlPreProgressPerformWait(ByVal t As Task)
_GdlPreProgressPerformEnabled = False
Try
While t.Status = TaskStatus.Running Or t.Status = TaskStatus.WaitingToRun : Thread.Sleep(100) : End While
Catch
End Try
End Sub
Private Function GetDataFromGalleryDL(ByVal URL As String, ByVal Cache As CacheKeeper, ByVal UseTempPostList As Boolean, Private Function GetDataFromGalleryDL(ByVal URL As String, ByVal Cache As CacheKeeper, ByVal UseTempPostList As Boolean,
Optional ByVal Token As CancellationToken = Nothing) As SFile Optional ByVal Token As CancellationToken = Nothing) As SFile
Dim command$ = String.Empty Dim command$ = String.Empty
Try Try
Dim conf As SFile = GdlCreateConf(Cache.NewPath) Dim conf As SFile = GdlCreateConf(Cache.NewPath)
command = $"""{Settings.GalleryDLFile}"" --verbose --no-download --no-skip --config ""{conf}"" --write-pages " Dim fTimer% = SleepTimerValue(True)
command &= GdlGetIdFilterString() command = $"""{Settings.GalleryDLFile}"" --verbose --no-download --no-skip{SleepRequest} --config ""{conf}"" --write-pages "
'command &= GdlGetIdFilterString()
Dim dir As SFile = Cache.NewPath Dim dir As SFile = Cache.NewPath
If dir.Exists(SFO.Path,, EDP.ThrowException) Then If dir.Exists(SFO.Path,, EDP.ThrowException) Then
Using batch As New TwitterGDL(dir, Token, MySettings.AbortOnLimit.Value) Using batch As New TwitterGDL(dir, Token, MySettings.AbortOnLimit.Value)
@@ -823,6 +873,7 @@ nextpIndx:
'#If DEBUG Then '#If DEBUG Then
'Debug.WriteLine(command) 'Debug.WriteLine(command)
'#End If '#End If
GdlWaitFirstTimer(fTimer)
batch.Execute(command) batch.Execute(command)
If batch.LimitReached Then If batch.LimitReached Then
If CBool(MySettings.DownloadAlreadyParsed.Value) And If CBool(MySettings.DownloadAlreadyParsed.Value) And
@@ -867,6 +918,8 @@ nextpIndx:
Dim process As Boolean, multiMode As Boolean Dim process As Boolean, multiMode As Boolean
Dim currentModel As DownloadModels Dim currentModel As DownloadModels
Dim urlPrePattern$ = $"https://x.com{IIf(IsCommunity, SiteSettings.CommunitiesUser, String.Empty)}/" Dim urlPrePattern$ = $"https://x.com{IIf(IsCommunity, SiteSettings.CommunitiesUser, String.Empty)}/"
Dim fTimer% = SleepTimerValue(True)
Dim t As Task
If DownloadBroadcasts AndAlso Not dm.Contains(DownloadModels.Profile) Then dm.Add(DownloadModels.Profile) If DownloadBroadcasts AndAlso Not dm.Contains(DownloadModels.Profile) Then dm.Add(DownloadModels.Profile)
@@ -885,7 +938,7 @@ nextpIndx:
dir.Exists(SFO.Path, True, EDP.ThrowException) dir.Exists(SFO.Path, True, EDP.ThrowException)
outList.Add(dir) outList.Add(dir)
tgdl.ChangeDirectory(dir) tgdl.ChangeDirectory(dir)
command = $"""{Settings.GalleryDLFile}"" --verbose --no-download --no-skip --config ""{conf}"" --write-pages " command = $"""{Settings.GalleryDLFile}"" --verbose --no-download --no-skip{SleepRequest} --config ""{conf}"" --write-pages "
If multiMode Then If multiMode Then
command &= "{0}" command &= "{0}"
Else Else
@@ -913,7 +966,18 @@ nextpIndx:
Else Else
tgdl.TempPostsList = _TempPostsList tgdl.TempPostsList = _TempPostsList
End If End If
GdlWaitFirstTimer(fTimer)
_GdlPreProgressPerformEnabled = True
t = New Task(Sub() GdlPreProgressPerform(dir, conf))
t.Start()
tgdl.Execute(command) tgdl.Execute(command)
_GdlPreProgressPerformEnabled = False
GdlPreProgressPerformWait(t)
If tgdl.LimitReached Then If tgdl.LimitReached Then
If CBool(MySettings.DownloadAlreadyParsed.Value) And If CBool(MySettings.DownloadAlreadyParsed.Value) And
SFile.GetFiles(rootDir, "*.txt", IO.SearchOption.AllDirectories, EDP.ReturnValue).Count > 0 Then SFile.GetFiles(rootDir, "*.txt", IO.SearchOption.AllDirectories, EDP.ReturnValue).Count > 0 Then
@@ -936,6 +1000,8 @@ nextpIndx:
Catch ex As Exception Catch ex As Exception
ProcessException(ex, Token, $"{ToStringForLog()}: GetTimelineFromGalleryDL({command})") ProcessException(ex, Token, $"{ToStringForLog()}: GetTimelineFromGalleryDL({command})")
Return Nothing Return Nothing
Finally
_GdlPreProgressPerformEnabled = False
End Try End Try
End Function End Function
Private Function GdlGetIdFilterString(Optional ByVal TL As List(Of String) = Nothing) As String Private Function GdlGetIdFilterString(Optional ByVal TL As List(Of String) = Nothing) As String
@@ -945,8 +1011,11 @@ nextpIndx:
Private Function GdlCreateConf(ByVal Path As SFile) As SFile Private Function GdlCreateConf(ByVal Path As SFile) As SFile
Try Try
Dim conf As SFile = $"{Path.PathWithSeparator}TwitterGdlConfig.conf" Dim conf As SFile = $"{Path.PathWithSeparator}TwitterGdlConfig.conf"
Dim __userAgent$ = MySettings.UserAgent
If Not __userAgent.IsEmptyString Then __userAgent = $"""user-agent"": ""{__userAgent}"","
Dim confText$ = "{""extractor"":{""cookies"": """ & MySettings.CookiesNetscapeFile.ToString.Replace("\", "/") & Dim confText$ = "{""extractor"":{""cookies"": """ & MySettings.CookiesNetscapeFile.ToString.Replace("\", "/") &
""",""cookies-update"": false,""twitter"":{""tweet-endpoint"": ""detail"",""cards"": false,""conversations"": true,""pinned"": false,""quoted"": false,""replies"": true,""retweets"": true,""strategy"": null,""text-tweets"": false,""twitpic"": false,""unique"": true,""users"": ""timeline"",""videos"": true}}}" $""",""cookies-update"": {IIf(CBool(MySettings.CookiesUpdate.Value), "true", "false")}," & __userAgent &
"""twitter"":{""tweet-endpoint"": ""detail"",""cards"": false,""conversations"": true,""pinned"": false,""quoted"": false,""replies"": true,""retweets"": true,""strategy"": null,""text-tweets"": false,""twitpic"": false,""unique"": true,""users"": ""timeline"",""videos"": true}}}"
If conf.Exists(SFO.Path, True, EDP.ThrowException) Then TextSaver.SaveTextToFile(confText, conf) If conf.Exists(SFO.Path, True, EDP.ThrowException) Then TextSaver.SaveTextToFile(confText, conf)
If Not conf.Exists Then Throw New IO.FileNotFoundException("Can't find Twitter GDL config file", conf) If Not conf.Exists Then Throw New IO.FileNotFoundException("Can't find Twitter GDL config file", conf)
Return conf Return conf
@@ -1050,6 +1119,7 @@ nextpIndx:
#End Region #End Region
#Region "DownloadSingleObject" #Region "DownloadSingleObject"
Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken) Protected Overrides Sub DownloadSingleObject_GetPosts(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)
GDL_REQUESTS_COUNT = 0
Dim um As New UserMedia(Data.URL) With {.State = UStates.Missing} Dim um As New UserMedia(Data.URL) With {.State = UStates.Missing}
If Not Data.URL.IsEmptyString AndAlso Data.URL.Contains(BroadCastPartUrl) Then um.Type = UTypes.m3u8 If Not Data.URL.IsEmptyString AndAlso Data.URL.Contains(BroadCastPartUrl) Then um.Type = UTypes.m3u8
_ContentList.Add(um) _ContentList.Add(um)

View File

@@ -45,7 +45,6 @@ Namespace API.XVIDEOS
End Get End Get
End Property End Property
Private Property SiteMode As SiteModes = SiteModes.User Private Property SiteMode As SiteModes = SiteModes.User
Private Property TrueName As String = String.Empty
Private Property Arguments As String = String.Empty Private Property Arguments As String = String.Empty
Private Property PersonType As String = String.Empty Private Property PersonType As String = String.Empty
Friend Overrides ReadOnly Property IsUser As Boolean Friend Overrides ReadOnly Property IsUser As Boolean
@@ -92,14 +91,14 @@ Namespace API.XVIDEOS
If Not Force OrElse (Not SiteMode = SiteModes.User AndAlso Not NewUrl.IsEmptyString AndAlso MyFileSettings.Exists) Then If Not Force OrElse (Not SiteMode = SiteModes.User AndAlso Not NewUrl.IsEmptyString AndAlso MyFileSettings.Exists) Then
Dim eObj As Plugin.ExchangeOptions = Nothing Dim eObj As Plugin.ExchangeOptions = Nothing
If Force Then eObj = MySettings.IsMyUser(NewUrl) If Force Then eObj = MySettings.IsMyUser(NewUrl)
If (Force And Not eObj.UserName.IsEmptyString) Or (Not Force And TrueName.IsEmptyString) Then If (Force And Not eObj.UserName.IsEmptyString) Or (Not Force And NameTrue(True).IsEmptyString) Then
Dim n$() = If(Force, eObj.UserName, Name).Split("@") Dim n$() = If(Force, eObj.UserName, Name).Split("@")
If n.ListExists(2) Then If n.ListExists(2) Then
Dim opt$ = If(Force, eObj.Options, Options) Dim opt$ = If(Force, eObj.Options, Options)
If opt.IsEmptyString AndAlso Not IsNumeric(n(0)) Then If opt.IsEmptyString AndAlso Not IsNumeric(n(0)) Then
If Not Force Then If Not Force Then
PersonType = n(0) PersonType = n(0)
TrueName = If(Force, eObj.UserName, Name).Replace($"{PersonType}@", String.Empty) NameTrue = If(Force, eObj.UserName, Name).Replace($"{PersonType}@", String.Empty)
End If End If
ElseIf Not opt.IsEmptyString Then ElseIf Not opt.IsEmptyString Then
Dim n2$() = opt.Split("@") Dim n2$() = opt.Split("@")
@@ -108,8 +107,8 @@ Namespace API.XVIDEOS
Dim __Arguments$ = opt.Replace($"{__TrueName}@", String.Empty) Dim __Arguments$ = opt.Replace($"{__TrueName}@", String.Empty)
Dim __ForceApply As Boolean = False Dim __ForceApply As Boolean = False
If Force AndAlso (Not TrueName = __TrueName Or Not SiteMode = __SiteMode) Then If Force AndAlso (Not NameTrue(True) = __TrueName Or Not SiteMode = __SiteMode) Then
If ValidateChangeSearchOptions(ToStringForLog, $"{__SiteMode}: {__TrueName}", $"{SiteMode}: {TrueName}") Then If ValidateChangeSearchOptions(ToStringForLog, $"{__SiteMode}: {__TrueName}", $"{SiteMode}: {NameTrue(True)}") Then
__ForceApply = True __ForceApply = True
Else Else
Return False Return False
@@ -120,15 +119,15 @@ Namespace API.XVIDEOS
Options = opt Options = opt
If Not Force Then If Not Force Then
SiteMode = __SiteMode SiteMode = __SiteMode
TrueName = __TrueName NameTrue = __TrueName
UserSiteName = $"{SiteMode}: {TrueName}" UserSiteName = $"{SiteMode}: {NameTrue}"
If FriendlyName.IsEmptyString Then FriendlyName = UserSiteName If FriendlyName.IsEmptyString Then FriendlyName = UserSiteName
Settings.Labels.Add(SearchRequestLabelName) Settings.Labels.Add(SearchRequestLabelName)
Labels.ListAddValue(SearchRequestLabelName, LNC) Labels.ListAddValue(SearchRequestLabelName, LNC)
Labels.Sort() Labels.Sort()
ElseIf Force And __ForceApply Then ElseIf Force And __ForceApply Then
SiteMode = __SiteMode SiteMode = __SiteMode
TrueName = __TrueName NameTrue = __TrueName
End If End If
Return True Return True
@@ -142,14 +141,13 @@ Namespace API.XVIDEOS
With Container With Container
If Loading Then If Loading Then
SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User) SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User)
TrueName = .Value(Name_TrueName)
Arguments = .Value(Name_Arguments) Arguments = .Value(Name_Arguments)
PersonType = .Value(Name_PersonType) PersonType = .Value(Name_PersonType)
If PersonType.IsEmptyString And TrueName.IsEmptyString And Not Name.IsEmptyString Then If PersonType.IsEmptyString And NameTrue(True).IsEmptyString And Not Name.IsEmptyString Then
If Not Name.Contains("@") Then If Not Name.Contains("@") Then
Dim n$() = Name.Split("_") Dim n$() = Name.Split("_")
PersonType = n(0) PersonType = n(0)
TrueName = Name.Replace($"{PersonType}_", String.Empty) NameTrue = Name.Replace($"{PersonType}_", String.Empty)
End If End If
End If End If
UpdateUserOptions() UpdateUserOptions()
@@ -160,7 +158,7 @@ Namespace API.XVIDEOS
.Value(Name_FriendlyName) = FriendlyName .Value(Name_FriendlyName) = FriendlyName
End If End If
.Add(Name_SiteMode, CInt(SiteMode)) .Add(Name_SiteMode, CInt(SiteMode))
.Add(Name_TrueName, TrueName) .Add(Name_TrueName, NameTrue(True))
.Add(Name_Arguments, Arguments) .Add(Name_Arguments, Arguments)
.Add(Name_PersonType, PersonType) .Add(Name_PersonType, PersonType)
@@ -181,19 +179,19 @@ Namespace API.XVIDEOS
Friend Function GetUserUrl(ByVal Page As Integer) As String Friend Function GetUserUrl(ByVal Page As Integer) As String
Dim url$ = String.Empty Dim url$ = String.Empty
If SiteMode = SiteModes.User Then If SiteMode = SiteModes.User Then
url = $"https://xvideos.com/{PersonType}/{TrueName}" url = $"https://xvideos.com/{PersonType}/{NameTrue}"
ElseIf SiteMode = SiteModes.Categories Then ElseIf SiteMode = SiteModes.Categories Then
url = "https://xvideos.com/c/" url = "https://xvideos.com/c/"
If Not Arguments.IsEmptyString Then url &= $"{Arguments}/" If Not Arguments.IsEmptyString Then url &= $"{Arguments}/"
url &= TrueName url &= NameTrue
If Page > 1 Then url &= $"/{Page - 1}" If Page > 1 Then url &= $"/{Page - 1}"
ElseIf SiteMode = SiteModes.Tags Then ElseIf SiteMode = SiteModes.Tags Then
url = "https://www.xvideos.com/tags/" url = "https://www.xvideos.com/tags/"
If Not Arguments.IsEmptyString Then url &= $"{Arguments}/" If Not Arguments.IsEmptyString Then url &= $"{Arguments}/"
url &= $"{TrueName}/" url &= $"{NameTrue}/"
If Page > 1 Then url &= Page - 1 If Page > 1 Then url &= Page - 1
ElseIf SiteMode = SiteModes.Search Then ElseIf SiteMode = SiteModes.Search Then
url = $"https://www.xvideos.com/?k={TrueName}" url = $"https://www.xvideos.com/?k={NameTrue}"
If Not Arguments.IsEmptyString Then url &= $"&{Arguments}" If Not Arguments.IsEmptyString Then url &= $"&{Arguments}"
If Page > 1 Then url &= $"&p={Page - 1}" If Page > 1 Then url &= $"&p={Page - 1}"
End If End If

View File

@@ -86,7 +86,7 @@ Namespace API.Xhamster
If Not .SiteMode = SiteModes.User Then If Not .SiteMode = SiteModes.User Then
Return .GetNonUserUrl(0) Return .GetNonUserUrl(0)
Else Else
Return String.Format(UrlPatternUser, IIf(.IsChannel, ChannelOption, UserOption), .TrueName) Return String.Format(UrlPatternUser, IIf(.IsChannel, ChannelOption, UserOption), .NameTrue)
End If End If
End With End With
End Function End Function

View File

@@ -29,7 +29,6 @@ Namespace API.Xhamster
End Property End Property
Friend Property IsChannel As Boolean = False Friend Property IsChannel As Boolean = False
Friend Property IsCreator As Boolean = False Friend Property IsCreator As Boolean = False
Friend Property TrueName As String = String.Empty
Friend Property Gender As String = String.Empty Friend Property Gender As String = String.Empty
Friend Property SiteMode As SiteModes = SiteModes.User Friend Property SiteMode As SiteModes = SiteModes.User
Friend Property Arguments As String = String.Empty Friend Property Arguments As String = String.Empty
@@ -73,17 +72,17 @@ Namespace API.Xhamster
If Not Force OrElse (Not SiteMode = SiteModes.User AndAlso Not NewUrl.IsEmptyString AndAlso MyFileSettings.Exists) Then If Not Force OrElse (Not SiteMode = SiteModes.User AndAlso Not NewUrl.IsEmptyString AndAlso MyFileSettings.Exists) Then
Dim eObj As Plugin.ExchangeOptions = Nothing Dim eObj As Plugin.ExchangeOptions = Nothing
If Force Then eObj = MySettings.IsMyUser(NewUrl) If Force Then eObj = MySettings.IsMyUser(NewUrl)
If (Force And Not eObj.UserName.IsEmptyString) Or (Not Force And TrueName.IsEmptyString) Then If (Force And Not eObj.UserName.IsEmptyString) Or (Not Force And NameTrue(True).IsEmptyString) Then
Dim n$() = If(Force, eObj.UserName, Name).Split("@") Dim n$() = If(Force, eObj.UserName, Name).Split("@")
If n.ListExists Then If n.ListExists Then
If n.Length = 2 And If(Force, eObj.Options, Options).IsEmptyString Then If n.Length = 2 And If(Force, eObj.Options, Options).IsEmptyString Then
If Force Then Return False If Force Then Return False
TrueName = n(0) NameTrue = n(0)
IsChannel = n(1) = SiteSettings.ChannelOption IsChannel = n(1) = SiteSettings.ChannelOption
IsCreator = n(1) = SiteSettings.P_Creators IsCreator = n(1) = SiteSettings.P_Creators
ElseIf IsChannel Then ElseIf IsChannel Then
If Force Then Return False If Force Then Return False
TrueName = Name NameTrue = Name
ElseIf Not If(Force, eObj.Options, Options).IsEmptyString Then ElseIf Not If(Force, eObj.Options, Options).IsEmptyString Then
Dim __TrueName$, __Arguments$, __Gender$ Dim __TrueName$, __Arguments$, __Gender$
Dim __Mode As SiteModes Dim __Mode As SiteModes
@@ -97,10 +96,10 @@ Namespace API.Xhamster
__Arguments = n2(3) __Arguments = n2(3)
__TrueName = n2.ListTake(3, 100, EDP.ReturnValue).ListToString(String.Empty) __TrueName = n2.ListTake(3, 100, EDP.ReturnValue).ListToString(String.Empty)
If Force AndAlso (Not TrueName = __TrueName Or Not SiteMode = __Mode Or Not Gender = __Gender) Then If Force AndAlso (Not NameTrue(True) = __TrueName Or Not SiteMode = __Mode Or Not Gender = __Gender) Then
If ValidateChangeSearchOptions(ToStringForLog, If ValidateChangeSearchOptions(ToStringForLog,
$"{__Mode}{IIf(__Gender.IsEmptyString, String.Empty, $" ({__Gender})")}: {__TrueName}", $"{__Mode}{IIf(__Gender.IsEmptyString, String.Empty, $" ({__Gender})")}: {__TrueName}",
$"{SiteMode}{IIf(Gender.IsEmptyString, String.Empty, $" ({Gender})")}: {TrueName}") Then $"{SiteMode}{IIf(Gender.IsEmptyString, String.Empty, $" ({Gender})")}: {NameTrue(True)}") Then
__ForceApply = True __ForceApply = True
Else Else
Return False Return False
@@ -110,17 +109,17 @@ Namespace API.Xhamster
Arguments = __Arguments Arguments = __Arguments
Options = If(Force, eObj.Options, Options) Options = If(Force, eObj.Options, Options)
If Not Force Then If Not Force Then
TrueName = __TrueName NameTrue = __TrueName
SiteMode = __Mode SiteMode = __Mode
Gender = __Gender Gender = __Gender
UserSiteName = $"{SiteMode}: {TrueName}" UserSiteName = $"{SiteMode}: {NameTrue}"
If FriendlyName.IsEmptyString Then FriendlyName = UserSiteName If FriendlyName.IsEmptyString Then FriendlyName = UserSiteName
Settings.Labels.Add(SearchRequestLabelName) Settings.Labels.Add(SearchRequestLabelName)
Labels.ListAddValue(SearchRequestLabelName, LNC) Labels.ListAddValue(SearchRequestLabelName, LNC)
Labels.Sort() Labels.Sort()
ElseIf Force And __ForceApply Then ElseIf Force And __ForceApply Then
TrueName = __TrueName NameTrue = __TrueName
SiteMode = __Mode SiteMode = __Mode
Gender = __Gender Gender = __Gender
End If End If
@@ -132,7 +131,7 @@ Namespace API.Xhamster
End If End If
Else Else
If Force Then Return False If Force Then Return False
TrueName = n(0) NameTrue = n(0)
End If End If
End If End If
End If End If
@@ -144,7 +143,6 @@ Namespace API.Xhamster
If Loading Then If Loading Then
IsChannel = .Value(Name_IsChannel).FromXML(Of Boolean)(False) IsChannel = .Value(Name_IsChannel).FromXML(Of Boolean)(False)
IsCreator = .Value(Name_IsCreator).FromXML(Of Boolean)(False) IsCreator = .Value(Name_IsCreator).FromXML(Of Boolean)(False)
TrueName = .Value(Name_TrueName)
Gender = .Value(Name_Gender) Gender = .Value(Name_Gender)
SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User) SiteMode = .Value(Name_SiteMode).FromXML(Of Integer)(SiteModes.User)
Arguments = .Value(Name_Arguments) Arguments = .Value(Name_Arguments)
@@ -157,7 +155,7 @@ Namespace API.Xhamster
End If End If
.Add(Name_IsChannel, IsChannel.BoolToInteger) .Add(Name_IsChannel, IsChannel.BoolToInteger)
.Add(Name_IsCreator, IsCreator.BoolToInteger) .Add(Name_IsCreator, IsCreator.BoolToInteger)
.Add(Name_TrueName, TrueName) .Add(Name_TrueName, NameTrue(True))
.Add(Name_Gender, Gender) .Add(Name_Gender, Gender)
.Add(Name_SiteMode, CInt(SiteMode)) .Add(Name_SiteMode, CInt(SiteMode))
.Add(Name_Arguments, Arguments) .Add(Name_Arguments, Arguments)
@@ -198,7 +196,7 @@ Namespace API.Xhamster
Case SiteModes.User : url &= SiteSettings.P_Creators Case SiteModes.User : url &= SiteSettings.P_Creators
Case Else : Return String.Empty Case Else : Return String.Empty
End Select End Select
url &= $"/{TrueName}" url &= $"/{NameTrue}"
Dim args$ = Arguments Dim args$ = Arguments
If (args.IsEmptyString OrElse Not args.Contains(newest)) And Not SiteMode = SiteModes.Search Then url &= newest If (args.IsEmptyString OrElse Not args.Contains(newest)) And Not SiteMode = SiteModes.Search Then url &= newest
@@ -289,14 +287,14 @@ Namespace API.Xhamster
URL = $"https://xhamster.com/my/favorites/{IIf(IsVideo, "videos", "photos-and-galleries")}{IIf(Page = 1, String.Empty, $"/{Page}")}" URL = $"https://xhamster.com/my/favorites/{IIf(IsVideo, "videos", "photos-and-galleries")}{IIf(Page = 1, String.Empty, $"/{Page}")}"
containerNodes.Add(If(IsVideo, {"favoriteVideoListComponent", "models"}, {"favoritesGalleriesAndPhotosCollection"})) containerNodes.Add(If(IsVideo, {"favoriteVideoListComponent", "models"}, {"favoritesGalleriesAndPhotosCollection"}))
ElseIf IsChannel Then ElseIf IsChannel Then
URL = $"https://xhamster.com/channels/{TrueName}/newest{IIf(Page = 1, String.Empty, $"/{Page}")}" URL = $"https://xhamster.com/channels/{NameTrue}/newest{IIf(Page = 1, String.Empty, $"/{Page}")}"
ElseIf SiteMode = SiteModes.Search Then ElseIf SiteMode = SiteModes.Search Then
URL = GetNonUserUrl(Page) URL = GetNonUserUrl(Page)
containerNodes.Add({"searchResult", "models"}) containerNodes.Add({"searchResult", "models"})
ElseIf IsCreator Or SiteMode = SiteModes.Tags Or SiteMode = SiteModes.Categories Or SiteMode = SiteModes.Pornstars Then ElseIf IsCreator Or SiteMode = SiteModes.Tags Or SiteMode = SiteModes.Categories Or SiteMode = SiteModes.Pornstars Then
URL = GetNonUserUrl(Page) URL = GetNonUserUrl(Page)
Else Else
URL = $"https://xhamster.com/users/{TrueName}/{IIf(IsVideo, "videos", "photos")}{IIf(Page = 1, String.Empty, $"/{Page}")}" URL = $"https://xhamster.com/users/{NameTrue}/{IIf(IsVideo, "videos", "photos")}{IIf(Page = 1, String.Empty, $"/{Page}")}"
End If End If
ThrowAny(Token) ThrowAny(Token)

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -61,6 +61,7 @@ Namespace DownloadObjects
Me.BTT_FEED_DELETE_DAILY_LIST = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_FEED_DELETE_DAILY_LIST = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_FEED_DELETE_DAILY_DATE = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_FEED_DELETE_DAILY_DATE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CURR_SESSION_SET = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_CURR_SESSION_SET = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CURR_SESSION_SET_LAST = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_MERGE_SESSIONS = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_MERGE_SESSIONS = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_CLEAR_DAILY = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_CLEAR_DAILY = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_RESET_DAILY = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_RESET_DAILY = New System.Windows.Forms.ToolStripMenuItem()
@@ -75,7 +76,7 @@ Namespace DownloadObjects
Me.BTT_DOWN_SELECTED = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_DOWN_SELECTED = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_REFRESH = New System.Windows.Forms.ToolStripButton() Me.BTT_REFRESH = New System.Windows.Forms.ToolStripButton()
Me.TP_DATA = New System.Windows.Forms.TableLayoutPanel() Me.TP_DATA = New System.Windows.Forms.TableLayoutPanel()
Me.BTT_CURR_SESSION_SET_LAST = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_CHECK_INVERT = New System.Windows.Forms.ToolStripMenuItem()
SEP_1 = New System.Windows.Forms.ToolStripSeparator() SEP_1 = New System.Windows.Forms.ToolStripSeparator()
SEP_2 = New System.Windows.Forms.ToolStripSeparator() SEP_2 = New System.Windows.Forms.ToolStripSeparator()
MENU_VIEW = New System.Windows.Forms.ToolStripDropDownButton() MENU_VIEW = New System.Windows.Forms.ToolStripDropDownButton()
@@ -187,7 +188,7 @@ Namespace DownloadObjects
' '
Me.MENU_LOAD_SESSION.AutoToolTip = False Me.MENU_LOAD_SESSION.AutoToolTip = False
Me.MENU_LOAD_SESSION.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image Me.MENU_LOAD_SESSION.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image
Me.MENU_LOAD_SESSION.DropDownItems.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_LOAD_SESSION_CURRENT, Me.BTT_LOAD_SESSION_LAST, Me.BTT_LOAD_SESSION_CHOOSE, MENU_LOAD_SEP_0, Me.BTT_COPY_TO, Me.BTT_MOVE_TO, MENU_LOAD_SEP_1, Me.BTT_COPY_SPEC_TO, Me.BTT_MOVE_SPEC_TO, MENU_LOAD_SEP_2, Me.BTT_LOAD_FAV, Me.BTT_LOAD_SPEC, MENU_LOAD_SEP_3, Me.BTT_FEED_ADD_FAV, Me.BTT_FEED_ADD_FAV_REMOVE, Me.BTT_FEED_REMOVE_FAV, MENU_LOAD_SEP_4, Me.BTT_FEED_ADD_SPEC, Me.BTT_FEED_ADD_SPEC_REMOVE, Me.BTT_FEED_REMOVE_SPEC, MENU_LOAD_SEP_5, Me.BTT_FEED_CLEAR_FAV, Me.BTT_FEED_CLEAR_SPEC, Me.BTT_FEED_DELETE_SPEC, Me.BTT_FEED_DELETE_DAILY_LIST, Me.BTT_FEED_DELETE_DAILY_DATE, MENU_LOAD_SEP_6, Me.BTT_CURR_SESSION_SET, Me.BTT_CURR_SESSION_SET_LAST, Me.BTT_MERGE_SESSIONS, Me.BTT_CLEAR_DAILY, Me.BTT_RESET_DAILY, MENU_LOAD_SEP_7, Me.BTT_MERGE_FEEDS, MENU_LOAD_SEP_8, Me.BTT_CHECK_ALL, Me.BTT_CHECK_NONE, MENU_LOAD_SEP_9, Me.BTT_VIEW_SAVE, Me.BTT_VIEW_LOAD}) Me.MENU_LOAD_SESSION.DropDownItems.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_LOAD_SESSION_CURRENT, Me.BTT_LOAD_SESSION_LAST, Me.BTT_LOAD_SESSION_CHOOSE, MENU_LOAD_SEP_0, Me.BTT_COPY_TO, Me.BTT_MOVE_TO, MENU_LOAD_SEP_1, Me.BTT_COPY_SPEC_TO, Me.BTT_MOVE_SPEC_TO, MENU_LOAD_SEP_2, Me.BTT_LOAD_FAV, Me.BTT_LOAD_SPEC, MENU_LOAD_SEP_3, Me.BTT_FEED_ADD_FAV, Me.BTT_FEED_ADD_FAV_REMOVE, Me.BTT_FEED_REMOVE_FAV, MENU_LOAD_SEP_4, Me.BTT_FEED_ADD_SPEC, Me.BTT_FEED_ADD_SPEC_REMOVE, Me.BTT_FEED_REMOVE_SPEC, MENU_LOAD_SEP_5, Me.BTT_FEED_CLEAR_FAV, Me.BTT_FEED_CLEAR_SPEC, Me.BTT_FEED_DELETE_SPEC, Me.BTT_FEED_DELETE_DAILY_LIST, Me.BTT_FEED_DELETE_DAILY_DATE, MENU_LOAD_SEP_6, Me.BTT_CURR_SESSION_SET, Me.BTT_CURR_SESSION_SET_LAST, Me.BTT_MERGE_SESSIONS, Me.BTT_CLEAR_DAILY, Me.BTT_RESET_DAILY, MENU_LOAD_SEP_7, Me.BTT_MERGE_FEEDS, MENU_LOAD_SEP_8, Me.BTT_CHECK_ALL, Me.BTT_CHECK_NONE, Me.BTT_CHECK_INVERT, MENU_LOAD_SEP_9, Me.BTT_VIEW_SAVE, Me.BTT_VIEW_LOAD})
Me.MENU_LOAD_SESSION.Image = Global.SCrawler.My.Resources.Resources.ArrowDownPic_Blue_24 Me.MENU_LOAD_SESSION.Image = Global.SCrawler.My.Resources.Resources.ArrowDownPic_Blue_24
Me.MENU_LOAD_SESSION.ImageTransparentColor = System.Drawing.Color.Magenta Me.MENU_LOAD_SESSION.ImageTransparentColor = System.Drawing.Color.Magenta
Me.MENU_LOAD_SESSION.Name = "MENU_LOAD_SESSION" Me.MENU_LOAD_SESSION.Name = "MENU_LOAD_SESSION"
@@ -347,6 +348,13 @@ Namespace DownloadObjects
Me.BTT_CURR_SESSION_SET.Text = "Set current session..." Me.BTT_CURR_SESSION_SET.Text = "Set current session..."
Me.BTT_CURR_SESSION_SET.ToolTipText = "Select one of the download sessions and set it as the current session" Me.BTT_CURR_SESSION_SET.ToolTipText = "Select one of the download sessions and set it as the current session"
' '
'BTT_CURR_SESSION_SET_LAST
'
Me.BTT_CURR_SESSION_SET_LAST.Image = Global.SCrawler.My.Resources.Resources.ArrowDownPic_Blue_24
Me.BTT_CURR_SESSION_SET_LAST.Name = "BTT_CURR_SESSION_SET_LAST"
Me.BTT_CURR_SESSION_SET_LAST.Size = New System.Drawing.Size(352, 22)
Me.BTT_CURR_SESSION_SET_LAST.Text = "Set last download session as current session"
'
'BTT_MERGE_SESSIONS 'BTT_MERGE_SESSIONS
' '
Me.BTT_MERGE_SESSIONS.AutoToolTip = True Me.BTT_MERGE_SESSIONS.AutoToolTip = True
@@ -476,12 +484,11 @@ Namespace DownloadObjects
Me.TP_DATA.Size = New System.Drawing.Size(484, 436) Me.TP_DATA.Size = New System.Drawing.Size(484, 436)
Me.TP_DATA.TabIndex = 1 Me.TP_DATA.TabIndex = 1
' '
'BTT_CURR_SESSION_SET_LAST 'BTT_CHECK_INVERT
' '
Me.BTT_CURR_SESSION_SET_LAST.Image = Global.SCrawler.My.Resources.Resources.ArrowDownPic_Blue_24 Me.BTT_CHECK_INVERT.Name = "BTT_CHECK_INVERT"
Me.BTT_CURR_SESSION_SET_LAST.Name = "BTT_CURR_SESSION_SET_LAST" Me.BTT_CHECK_INVERT.Size = New System.Drawing.Size(352, 22)
Me.BTT_CURR_SESSION_SET_LAST.Size = New System.Drawing.Size(352, 22) Me.BTT_CHECK_INVERT.Text = "Invert selection"
Me.BTT_CURR_SESSION_SET_LAST.Text = "Set last download session as current session"
' '
'DownloadFeedForm 'DownloadFeedForm
' '
@@ -543,5 +550,6 @@ Namespace DownloadObjects
Private WithEvents BTT_MOVE_SPEC_TO As ToolStripMenuItem Private WithEvents BTT_MOVE_SPEC_TO As ToolStripMenuItem
Private WithEvents BTT_RESET_DAILY As ToolStripMenuItem Private WithEvents BTT_RESET_DAILY As ToolStripMenuItem
Private WithEvents BTT_CURR_SESSION_SET_LAST As ToolStripMenuItem Private WithEvents BTT_CURR_SESSION_SET_LAST As ToolStripMenuItem
Private WithEvents BTT_CHECK_INVERT As ToolStripMenuItem
End Class End Class
End Namespace End Namespace

View File

@@ -1081,13 +1081,14 @@ Namespace DownloadObjects
End Try End Try
End Sub End Sub
#End Region #End Region
Private Sub BTT_CHECK_ALL_NONE_Click(sender As Object, e As EventArgs) Handles BTT_CHECK_ALL.Click, BTT_CHECK_NONE.Click Private Sub BTT_CHECK_ALL_NONE_Click(sender As Object, e As EventArgs) Handles BTT_CHECK_ALL.Click, BTT_CHECK_NONE.Click, BTT_CHECK_INVERT.Click
Try Try
Dim checked As Boolean = sender Is BTT_CHECK_ALL Dim checked As Boolean = sender Is BTT_CHECK_ALL
Dim isInvert As Boolean = sender Is BTT_CHECK_INVERT
ControlInvokeFast(TP_DATA, Sub() ControlInvokeFast(TP_DATA, Sub()
With TP_DATA With TP_DATA
If .Controls.Count > 0 Then If .Controls.Count > 0 Then
For Each cnt As FeedMedia In .Controls : cnt.Checked = checked : Next For Each cnt As FeedMedia In .Controls : cnt.Checked = If(isInvert, Not cnt.Checked, checked) : Next
End If End If
End With End With
End Sub, EDP.None) End Sub, EDP.None)

View File

@@ -407,7 +407,7 @@ Namespace DownloadObjects
#End Region #End Region
#Region "Picture / Video objects" #Region "Picture / Video objects"
Private Sub MyPicture_DoubleClick(sender As Object, e As EventArgs) Handles MyPicture.DoubleClick Private Sub MyPicture_DoubleClick(sender As Object, e As EventArgs) Handles MyPicture.DoubleClick
Try : Process.Start(File) : Catch : End Try Try : Process.Start(IIf(IsSubscription, Post.URL_BASE, File.ToString)) : Catch : End Try
End Sub End Sub
#End Region #End Region
#Region "Context" #Region "Context"

View File

@@ -55,8 +55,10 @@ Namespace DownloadObjects
#Region "FeedsComparer" #Region "FeedsComparer"
Private Class FeedsComparer : Implements IComparer(Of FeedSpecial) Private Class FeedsComparer : Implements IComparer(Of FeedSpecial)
Friend Function Compare(ByVal x As FeedSpecial, ByVal y As FeedSpecial) As Integer Implements IComparer(Of FeedSpecial).Compare Friend Function Compare(ByVal x As FeedSpecial, ByVal y As FeedSpecial) As Integer Implements IComparer(Of FeedSpecial).Compare
If x.IsFavorite Then If x.IsFavorite And Not y.IsFavorite Then
Return -1 Return -1
ElseIf Not x.IsFavorite And y.IsFavorite Then
Return 1
Else Else
Return x.Name.CompareTo(y.Name) Return x.Name.CompareTo(y.Name)
End If End If

View File

@@ -32,8 +32,6 @@ Namespace Editors
Dim ActionButton4 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton4 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton5 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton5 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton6 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton6 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton7 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton8 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TP_FILE_NAME As System.Windows.Forms.TableLayoutPanel Dim TP_FILE_NAME As System.Windows.Forms.TableLayoutPanel
Dim TP_FILE_PATTERNS As System.Windows.Forms.TableLayoutPanel Dim TP_FILE_PATTERNS As System.Windows.Forms.TableLayoutPanel
Dim LBL_DATE_POS As System.Windows.Forms.Label Dim LBL_DATE_POS As System.Windows.Forms.Label
@@ -46,26 +44,28 @@ Namespace Editors
Dim TP_CHANNELS As System.Windows.Forms.TableLayoutPanel Dim TP_CHANNELS As System.Windows.Forms.TableLayoutPanel
Dim TAB_BEHAVIOR As System.Windows.Forms.TabPage Dim TAB_BEHAVIOR As System.Windows.Forms.TabPage
Dim TP_BEHAVIOR As System.Windows.Forms.TableLayoutPanel Dim TP_BEHAVIOR As System.Windows.Forms.TableLayoutPanel
Dim ActionButton9 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton7 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton10 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton8 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TP_OPEN_INFO As System.Windows.Forms.TableLayoutPanel Dim TP_OPEN_INFO As System.Windows.Forms.TableLayoutPanel
Dim TP_OPEN_PROGRESS As System.Windows.Forms.TableLayoutPanel Dim TP_OPEN_PROGRESS As System.Windows.Forms.TableLayoutPanel
Dim TP_BEHAVIOR_F6 As System.Windows.Forms.TableLayoutPanel Dim TP_BEHAVIOR_F6 As System.Windows.Forms.TableLayoutPanel
Dim TAB_DOWN As System.Windows.Forms.TabPage Dim TAB_DOWN As System.Windows.Forms.TabPage
Dim TP_DOWNLOADING As System.Windows.Forms.TableLayoutPanel Dim TP_DOWNLOADING As System.Windows.Forms.TableLayoutPanel
Dim ActionButton11 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton9 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton12 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton10 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TP_MISSING_DATA As System.Windows.Forms.TableLayoutPanel Dim TP_MISSING_DATA As System.Windows.Forms.TableLayoutPanel
Dim TAB_FEED As System.Windows.Forms.TabPage Dim TAB_FEED As System.Windows.Forms.TabPage
Dim TP_FEED As System.Windows.Forms.TableLayoutPanel Dim TP_FEED As System.Windows.Forms.TableLayoutPanel
Dim TP_FEED_IMG_COUNT As System.Windows.Forms.TableLayoutPanel Dim TP_FEED_IMG_COUNT As System.Windows.Forms.TableLayoutPanel
Dim TP_FEED_SES As System.Windows.Forms.TableLayoutPanel Dim TP_FEED_SES As System.Windows.Forms.TableLayoutPanel
Dim ActionButton13 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton11 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton14 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton12 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TP_FEED_SPEC_SEARCH As System.Windows.Forms.TableLayoutPanel Dim TP_FEED_SPEC_SEARCH As System.Windows.Forms.TableLayoutPanel
Dim TAB_NOTIFY As System.Windows.Forms.TabPage Dim TAB_NOTIFY As System.Windows.Forms.TabPage
Dim TP_NOTIFY_MAIN As System.Windows.Forms.TableLayoutPanel Dim TP_NOTIFY_MAIN As System.Windows.Forms.TableLayoutPanel
Dim TP_ENVIR As System.Windows.Forms.TableLayoutPanel Dim TP_ENVIR As System.Windows.Forms.TableLayoutPanel
Dim ActionButton13 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton14 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton15 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton15 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton16 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton16 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton17 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton17 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
@@ -78,25 +78,23 @@ Namespace Editors
Dim ActionButton24 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton24 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton25 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton25 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton26 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton26 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton27 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton28 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TAB_STD As System.Windows.Forms.TabPage Dim TAB_STD As System.Windows.Forms.TabPage
Dim TP_STD As System.Windows.Forms.TableLayoutPanel Dim TP_STD As System.Windows.Forms.TableLayoutPanel
Dim ActionButton29 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton27 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ListColumn1 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn() Dim ListColumn1 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
Dim ListColumn2 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn() Dim ListColumn2 As PersonalUtilities.Forms.Controls.Base.ListColumn = New PersonalUtilities.Forms.Controls.Base.ListColumn()
Dim TAB_DESIGN As System.Windows.Forms.TabPage Dim TAB_DESIGN As System.Windows.Forms.TabPage
Dim TP_DESIGN As System.Windows.Forms.TableLayoutPanel Dim TP_DESIGN As System.Windows.Forms.TableLayoutPanel
Dim ActionButton28 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton29 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton30 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton30 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton31 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton31 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TP_HEADERS_DEF As System.Windows.Forms.TableLayoutPanel
Dim ActionButton32 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton32 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton33 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton33 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TP_HEADERS_DEF As System.Windows.Forms.TableLayoutPanel
Dim ActionButton34 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton34 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton35 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton35 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton36 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton36 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton37 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim ActionButton38 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton()
Dim TAB_HEADERS As System.Windows.Forms.TabPage Dim TAB_HEADERS As System.Windows.Forms.TabPage
Me.TXT_GLOBAL_PATH = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_GLOBAL_PATH = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_IMAGE_LARGE = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_IMAGE_LARGE = New PersonalUtilities.Forms.Controls.TextBoxExtended()
@@ -106,7 +104,6 @@ Namespace Editors
Me.TXT_MAX_JOBS_CHANNELS = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_MAX_JOBS_CHANNELS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.CH_CHECK_VER_START = New System.Windows.Forms.CheckBox() Me.CH_CHECK_VER_START = New System.Windows.Forms.CheckBox()
Me.TXT_IMGUR_CLIENT_ID = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_IMGUR_CLIENT_ID = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_USER_AGENT = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.OPT_FILE_NAME_REPLACE = New System.Windows.Forms.RadioButton() Me.OPT_FILE_NAME_REPLACE = New System.Windows.Forms.RadioButton()
Me.OPT_FILE_NAME_ADD_DATE = New System.Windows.Forms.RadioButton() Me.OPT_FILE_NAME_ADD_DATE = New System.Windows.Forms.RadioButton()
Me.CH_FILE_NAME_CHANGE = New System.Windows.Forms.CheckBox() Me.CH_FILE_NAME_CHANGE = New System.Windows.Forms.CheckBox()
@@ -153,6 +150,7 @@ Namespace Editors
Me.CH_DOWN_ALL_NOTIFY = New System.Windows.Forms.CheckBox() Me.CH_DOWN_ALL_NOTIFY = New System.Windows.Forms.CheckBox()
Me.CH_FEED_SPEC_SEARCH = New System.Windows.Forms.CheckBox() Me.CH_FEED_SPEC_SEARCH = New System.Windows.Forms.CheckBox()
Me.CH_FEED_SPEC_SEARCH_DEEP = New System.Windows.Forms.CheckBox() Me.CH_FEED_SPEC_SEARCH_DEEP = New System.Windows.Forms.CheckBox()
Me.CH_FEED_OPEN_CTRLF = New System.Windows.Forms.CheckBox()
Me.TXT_CHANNELS_ROWS = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_CHANNELS_ROWS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.TXT_CHANNELS_COLUMNS = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_CHANNELS_COLUMNS = New PersonalUtilities.Forms.Controls.TextBoxExtended()
Me.CH_DOWN_IMAGES_NATIVE = New System.Windows.Forms.CheckBox() Me.CH_DOWN_IMAGES_NATIVE = New System.Windows.Forms.CheckBox()
@@ -212,7 +210,6 @@ Namespace Editors
Me.TAB_MAIN = New System.Windows.Forms.TabControl() Me.TAB_MAIN = New System.Windows.Forms.TabControl()
Me.TAB_ENVIR = New System.Windows.Forms.TabPage() Me.TAB_ENVIR = New System.Windows.Forms.TabPage()
Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer() Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
Me.CH_FEED_OPEN_CTRLF = New System.Windows.Forms.CheckBox()
TP_BASIS = New System.Windows.Forms.TableLayoutPanel() TP_BASIS = New System.Windows.Forms.TableLayoutPanel()
TP_IMAGES = New System.Windows.Forms.TableLayoutPanel() TP_IMAGES = New System.Windows.Forms.TableLayoutPanel()
TP_FILE_NAME = New System.Windows.Forms.TableLayoutPanel() TP_FILE_NAME = New System.Windows.Forms.TableLayoutPanel()
@@ -256,7 +253,6 @@ Namespace Editors
CType(Me.TXT_MAX_JOBS_USERS, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_MAX_JOBS_USERS, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_MAX_JOBS_CHANNELS, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_MAX_JOBS_CHANNELS, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_IMGUR_CLIENT_ID, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_IMGUR_CLIENT_ID, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.TXT_USER_AGENT, System.ComponentModel.ISupportInitialize).BeginInit()
TP_FILE_NAME.SuspendLayout() TP_FILE_NAME.SuspendLayout()
TP_FILE_PATTERNS.SuspendLayout() TP_FILE_PATTERNS.SuspendLayout()
TP_CHANNELS_IMGS.SuspendLayout() TP_CHANNELS_IMGS.SuspendLayout()
@@ -333,12 +329,11 @@ Namespace Editors
TP_BASIS.Controls.Add(Me.TXT_MAX_JOBS_USERS, 0, 3) TP_BASIS.Controls.Add(Me.TXT_MAX_JOBS_USERS, 0, 3)
TP_BASIS.Controls.Add(Me.TXT_MAX_JOBS_CHANNELS, 0, 4) TP_BASIS.Controls.Add(Me.TXT_MAX_JOBS_CHANNELS, 0, 4)
TP_BASIS.Controls.Add(Me.CH_CHECK_VER_START, 0, 5) TP_BASIS.Controls.Add(Me.CH_CHECK_VER_START, 0, 5)
TP_BASIS.Controls.Add(Me.TXT_IMGUR_CLIENT_ID, 0, 7) TP_BASIS.Controls.Add(Me.TXT_IMGUR_CLIENT_ID, 0, 6)
TP_BASIS.Controls.Add(Me.TXT_USER_AGENT, 0, 6)
TP_BASIS.Dock = System.Windows.Forms.DockStyle.Fill TP_BASIS.Dock = System.Windows.Forms.DockStyle.Fill
TP_BASIS.Location = New System.Drawing.Point(3, 3) TP_BASIS.Location = New System.Drawing.Point(3, 3)
TP_BASIS.Name = "TP_BASIS" TP_BASIS.Name = "TP_BASIS"
TP_BASIS.RowCount = 9 TP_BASIS.RowCount = 8
TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
@@ -346,10 +341,8 @@ Namespace Editors
TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!))
TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20.0!)) TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
TP_BASIS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
TP_BASIS.Size = New System.Drawing.Size(615, 418) TP_BASIS.Size = New System.Drawing.Size(615, 418)
TP_BASIS.TabIndex = 0 TP_BASIS.TabIndex = 0
' '
@@ -489,30 +482,11 @@ Namespace Editors
Me.TXT_IMGUR_CLIENT_ID.Buttons.Add(ActionButton6) Me.TXT_IMGUR_CLIENT_ID.Buttons.Add(ActionButton6)
Me.TXT_IMGUR_CLIENT_ID.CaptionText = "Imgur Client ID" Me.TXT_IMGUR_CLIENT_ID.CaptionText = "Imgur Client ID"
Me.TXT_IMGUR_CLIENT_ID.Dock = System.Windows.Forms.DockStyle.Fill Me.TXT_IMGUR_CLIENT_ID.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_IMGUR_CLIENT_ID.Location = New System.Drawing.Point(4, 204) Me.TXT_IMGUR_CLIENT_ID.Location = New System.Drawing.Point(4, 175)
Me.TXT_IMGUR_CLIENT_ID.Name = "TXT_IMGUR_CLIENT_ID" Me.TXT_IMGUR_CLIENT_ID.Name = "TXT_IMGUR_CLIENT_ID"
Me.TXT_IMGUR_CLIENT_ID.Size = New System.Drawing.Size(607, 22) Me.TXT_IMGUR_CLIENT_ID.Size = New System.Drawing.Size(607, 22)
Me.TXT_IMGUR_CLIENT_ID.TabIndex = 7 Me.TXT_IMGUR_CLIENT_ID.TabIndex = 7
' '
'TXT_USER_AGENT
'
ActionButton7.BackgroundImage = CType(resources.GetObject("ActionButton7.BackgroundImage"), System.Drawing.Image)
ActionButton7.Name = "Refresh"
ActionButton7.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton8.BackgroundImage = CType(resources.GetObject("ActionButton8.BackgroundImage"), System.Drawing.Image)
ActionButton8.Name = "Clear"
ActionButton8.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_USER_AGENT.Buttons.Add(ActionButton7)
Me.TXT_USER_AGENT.Buttons.Add(ActionButton8)
Me.TXT_USER_AGENT.CaptionText = "UserAgent"
Me.TXT_USER_AGENT.CaptionToolTipEnabled = True
Me.TXT_USER_AGENT.CaptionToolTipText = "Default user agent to use in requests"
Me.TXT_USER_AGENT.Dock = System.Windows.Forms.DockStyle.Fill
Me.TXT_USER_AGENT.Location = New System.Drawing.Point(4, 175)
Me.TXT_USER_AGENT.Name = "TXT_USER_AGENT"
Me.TXT_USER_AGENT.Size = New System.Drawing.Size(607, 22)
Me.TXT_USER_AGENT.TabIndex = 6
'
'TP_FILE_NAME 'TP_FILE_NAME
' '
TP_FILE_NAME.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] TP_FILE_NAME.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
@@ -1131,6 +1105,19 @@ Namespace Editors
"s as well.") "s as well.")
Me.CH_FEED_SPEC_SEARCH_DEEP.UseVisualStyleBackColor = True Me.CH_FEED_SPEC_SEARCH_DEEP.UseVisualStyleBackColor = True
' '
'CH_FEED_OPEN_CTRLF
'
Me.CH_FEED_OPEN_CTRLF.AutoSize = True
Me.CH_FEED_OPEN_CTRLF.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_FEED_OPEN_CTRLF.Location = New System.Drawing.Point(4, 299)
Me.CH_FEED_OPEN_CTRLF.Name = "CH_FEED_OPEN_CTRLF"
Me.CH_FEED_OPEN_CTRLF.Size = New System.Drawing.Size(613, 19)
Me.CH_FEED_OPEN_CTRLF.TabIndex = 11
Me.CH_FEED_OPEN_CTRLF.Text = "Use 'Ctrl+F' to open the Feed"
TT_MAIN.SetToolTip(Me.CH_FEED_OPEN_CTRLF, "If checked, 'Ctrl+F' will be used to open the Feed. Otherwise, 'Alt+F' will be us" &
"ed.")
Me.CH_FEED_OPEN_CTRLF.UseVisualStyleBackColor = True
'
'TP_CHANNELS_IMGS 'TP_CHANNELS_IMGS
' '
TP_CHANNELS_IMGS.ColumnCount = 2 TP_CHANNELS_IMGS.ColumnCount = 2
@@ -1347,11 +1334,11 @@ Namespace Editors
'TXT_FOLDER_CMD 'TXT_FOLDER_CMD
' '
Me.TXT_FOLDER_CMD.AutoShowClearButton = True Me.TXT_FOLDER_CMD.AutoShowClearButton = True
ActionButton9.BackgroundImage = CType(resources.GetObject("ActionButton9.BackgroundImage"), System.Drawing.Image) ActionButton7.BackgroundImage = CType(resources.GetObject("ActionButton7.BackgroundImage"), System.Drawing.Image)
ActionButton9.Enabled = False ActionButton7.Enabled = False
ActionButton9.Name = "Clear" ActionButton7.Name = "Clear"
ActionButton9.Visible = False ActionButton7.Visible = False
Me.TXT_FOLDER_CMD.Buttons.Add(ActionButton9) Me.TXT_FOLDER_CMD.Buttons.Add(ActionButton7)
Me.TXT_FOLDER_CMD.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox Me.TXT_FOLDER_CMD.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox
Me.TXT_FOLDER_CMD.CaptionText = "Folder cmd" Me.TXT_FOLDER_CMD.CaptionText = "Folder cmd"
Me.TXT_FOLDER_CMD.CaptionToolTipEnabled = True Me.TXT_FOLDER_CMD.CaptionToolTipEnabled = True
@@ -1390,11 +1377,11 @@ Namespace Editors
'TXT_CLOSE_SCRIPT 'TXT_CLOSE_SCRIPT
' '
Me.TXT_CLOSE_SCRIPT.AutoShowClearButton = True Me.TXT_CLOSE_SCRIPT.AutoShowClearButton = True
ActionButton10.BackgroundImage = CType(resources.GetObject("ActionButton10.BackgroundImage"), System.Drawing.Image) ActionButton8.BackgroundImage = CType(resources.GetObject("ActionButton8.BackgroundImage"), System.Drawing.Image)
ActionButton10.Enabled = False ActionButton8.Enabled = False
ActionButton10.Name = "Clear" ActionButton8.Name = "Clear"
ActionButton10.Visible = False ActionButton8.Visible = False
Me.TXT_CLOSE_SCRIPT.Buttons.Add(ActionButton10) Me.TXT_CLOSE_SCRIPT.Buttons.Add(ActionButton8)
Me.TXT_CLOSE_SCRIPT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox Me.TXT_CLOSE_SCRIPT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox
Me.TXT_CLOSE_SCRIPT.CaptionText = "Close cmd" Me.TXT_CLOSE_SCRIPT.CaptionText = "Close cmd"
Me.TXT_CLOSE_SCRIPT.CaptionToolTipEnabled = True Me.TXT_CLOSE_SCRIPT.CaptionToolTipEnabled = True
@@ -1578,12 +1565,12 @@ Namespace Editors
' '
'TXT_SCRIPT 'TXT_SCRIPT
' '
ActionButton11.BackgroundImage = CType(resources.GetObject("ActionButton11.BackgroundImage"), System.Drawing.Image) ActionButton9.BackgroundImage = CType(resources.GetObject("ActionButton9.BackgroundImage"), System.Drawing.Image)
ActionButton11.Name = "Open" ActionButton9.Name = "Open"
ActionButton12.BackgroundImage = CType(resources.GetObject("ActionButton12.BackgroundImage"), System.Drawing.Image) ActionButton10.BackgroundImage = CType(resources.GetObject("ActionButton10.BackgroundImage"), System.Drawing.Image)
ActionButton12.Name = "Clear" ActionButton10.Name = "Clear"
Me.TXT_SCRIPT.Buttons.Add(ActionButton11) Me.TXT_SCRIPT.Buttons.Add(ActionButton9)
Me.TXT_SCRIPT.Buttons.Add(ActionButton12) Me.TXT_SCRIPT.Buttons.Add(ActionButton10)
Me.TXT_SCRIPT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox Me.TXT_SCRIPT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox
Me.TXT_SCRIPT.CaptionText = "Script" Me.TXT_SCRIPT.CaptionText = "Script"
Me.TXT_SCRIPT.CaptionToolTipEnabled = True Me.TXT_SCRIPT.CaptionToolTipEnabled = True
@@ -1901,14 +1888,14 @@ Namespace Editors
' '
'NUM_FEED_SES_CURR_LOAD_LAST 'NUM_FEED_SES_CURR_LOAD_LAST
' '
ActionButton13.BackgroundImage = CType(resources.GetObject("ActionButton13.BackgroundImage"), System.Drawing.Image) ActionButton11.BackgroundImage = CType(resources.GetObject("ActionButton11.BackgroundImage"), System.Drawing.Image)
ActionButton13.Name = "Refresh" ActionButton11.Name = "Refresh"
ActionButton13.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh ActionButton11.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton14.BackgroundImage = CType(resources.GetObject("ActionButton14.BackgroundImage"), System.Drawing.Image) ActionButton12.BackgroundImage = CType(resources.GetObject("ActionButton12.BackgroundImage"), System.Drawing.Image)
ActionButton14.Name = "Clear" ActionButton12.Name = "Clear"
ActionButton14.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton12.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.NUM_FEED_SES_CURR_LOAD_LAST.Buttons.Add(ActionButton13) Me.NUM_FEED_SES_CURR_LOAD_LAST.Buttons.Add(ActionButton11)
Me.NUM_FEED_SES_CURR_LOAD_LAST.Buttons.Add(ActionButton14) Me.NUM_FEED_SES_CURR_LOAD_LAST.Buttons.Add(ActionButton12)
Me.NUM_FEED_SES_CURR_LOAD_LAST.CaptionText = "Load last session" Me.NUM_FEED_SES_CURR_LOAD_LAST.CaptionText = "Load last session"
Me.NUM_FEED_SES_CURR_LOAD_LAST.CaptionToolTipEnabled = True Me.NUM_FEED_SES_CURR_LOAD_LAST.CaptionToolTipEnabled = True
Me.NUM_FEED_SES_CURR_LOAD_LAST.CaptionToolTipText = resources.GetString("NUM_FEED_SES_CURR_LOAD_LAST.CaptionToolTipText") Me.NUM_FEED_SES_CURR_LOAD_LAST.CaptionToolTipText = resources.GetString("NUM_FEED_SES_CURR_LOAD_LAST.CaptionToolTipText")
@@ -2040,19 +2027,19 @@ Namespace Editors
' '
'TXT_YTDLP 'TXT_YTDLP
' '
ActionButton13.BackgroundImage = CType(resources.GetObject("ActionButton13.BackgroundImage"), System.Drawing.Image)
ActionButton13.Name = "Open"
ActionButton13.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton14.BackgroundImage = CType(resources.GetObject("ActionButton14.BackgroundImage"), System.Drawing.Image)
ActionButton14.Name = "Refresh"
ActionButton14.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton14.ToolTipText = "Try to find this program automatically (in SCrawler and/or system environment)"
ActionButton15.BackgroundImage = CType(resources.GetObject("ActionButton15.BackgroundImage"), System.Drawing.Image) ActionButton15.BackgroundImage = CType(resources.GetObject("ActionButton15.BackgroundImage"), System.Drawing.Image)
ActionButton15.Name = "Open" ActionButton15.Name = "Clear"
ActionButton15.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open ActionButton15.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
ActionButton16.BackgroundImage = CType(resources.GetObject("ActionButton16.BackgroundImage"), System.Drawing.Image) Me.TXT_YTDLP.Buttons.Add(ActionButton13)
ActionButton16.Name = "Refresh" Me.TXT_YTDLP.Buttons.Add(ActionButton14)
ActionButton16.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton16.ToolTipText = "Try to find this program automatically (in SCrawler and/or system environment)"
ActionButton17.BackgroundImage = CType(resources.GetObject("ActionButton17.BackgroundImage"), System.Drawing.Image)
ActionButton17.Name = "Clear"
ActionButton17.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_YTDLP.Buttons.Add(ActionButton15) Me.TXT_YTDLP.Buttons.Add(ActionButton15)
Me.TXT_YTDLP.Buttons.Add(ActionButton16)
Me.TXT_YTDLP.Buttons.Add(ActionButton17)
Me.TXT_YTDLP.CaptionText = "yt-dlp" Me.TXT_YTDLP.CaptionText = "yt-dlp"
Me.TXT_YTDLP.CaptionToolTipEnabled = True Me.TXT_YTDLP.CaptionToolTipEnabled = True
Me.TXT_YTDLP.CaptionToolTipText = "Path to yt-dlp.exe file" Me.TXT_YTDLP.CaptionToolTipText = "Path to yt-dlp.exe file"
@@ -2066,19 +2053,19 @@ Namespace Editors
' '
'TXT_FFMPEG 'TXT_FFMPEG
' '
ActionButton16.BackgroundImage = CType(resources.GetObject("ActionButton16.BackgroundImage"), System.Drawing.Image)
ActionButton16.Name = "Open"
ActionButton16.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton17.BackgroundImage = CType(resources.GetObject("ActionButton17.BackgroundImage"), System.Drawing.Image)
ActionButton17.Name = "Refresh"
ActionButton17.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton17.ToolTipText = "Try to find this program automatically (in SCrawler and/or system environment)"
ActionButton18.BackgroundImage = CType(resources.GetObject("ActionButton18.BackgroundImage"), System.Drawing.Image) ActionButton18.BackgroundImage = CType(resources.GetObject("ActionButton18.BackgroundImage"), System.Drawing.Image)
ActionButton18.Name = "Open" ActionButton18.Name = "Clear"
ActionButton18.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open ActionButton18.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
ActionButton19.BackgroundImage = CType(resources.GetObject("ActionButton19.BackgroundImage"), System.Drawing.Image) Me.TXT_FFMPEG.Buttons.Add(ActionButton16)
ActionButton19.Name = "Refresh" Me.TXT_FFMPEG.Buttons.Add(ActionButton17)
ActionButton19.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton19.ToolTipText = "Try to find this program automatically (in SCrawler and/or system environment)"
ActionButton20.BackgroundImage = CType(resources.GetObject("ActionButton20.BackgroundImage"), System.Drawing.Image)
ActionButton20.Name = "Clear"
ActionButton20.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_FFMPEG.Buttons.Add(ActionButton18) Me.TXT_FFMPEG.Buttons.Add(ActionButton18)
Me.TXT_FFMPEG.Buttons.Add(ActionButton19)
Me.TXT_FFMPEG.Buttons.Add(ActionButton20)
Me.TXT_FFMPEG.CaptionText = "ffmpeg" Me.TXT_FFMPEG.CaptionText = "ffmpeg"
Me.TXT_FFMPEG.CaptionToolTipEnabled = True Me.TXT_FFMPEG.CaptionToolTipEnabled = True
Me.TXT_FFMPEG.CaptionToolTipText = "Path to ffmpeg.exe file" Me.TXT_FFMPEG.CaptionToolTipText = "Path to ffmpeg.exe file"
@@ -2092,19 +2079,19 @@ Namespace Editors
' '
'TXT_CURL 'TXT_CURL
' '
ActionButton19.BackgroundImage = CType(resources.GetObject("ActionButton19.BackgroundImage"), System.Drawing.Image)
ActionButton19.Name = "Open"
ActionButton19.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton20.BackgroundImage = CType(resources.GetObject("ActionButton20.BackgroundImage"), System.Drawing.Image)
ActionButton20.Name = "Refresh"
ActionButton20.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton20.ToolTipText = "Try to find this program automatically (in SCrawler and/or system environment)"
ActionButton21.BackgroundImage = CType(resources.GetObject("ActionButton21.BackgroundImage"), System.Drawing.Image) ActionButton21.BackgroundImage = CType(resources.GetObject("ActionButton21.BackgroundImage"), System.Drawing.Image)
ActionButton21.Name = "Open" ActionButton21.Name = "Clear"
ActionButton21.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open ActionButton21.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
ActionButton22.BackgroundImage = CType(resources.GetObject("ActionButton22.BackgroundImage"), System.Drawing.Image) Me.TXT_CURL.Buttons.Add(ActionButton19)
ActionButton22.Name = "Refresh" Me.TXT_CURL.Buttons.Add(ActionButton20)
ActionButton22.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton22.ToolTipText = "Try to find this program automatically (in SCrawler and/or system environment)"
ActionButton23.BackgroundImage = CType(resources.GetObject("ActionButton23.BackgroundImage"), System.Drawing.Image)
ActionButton23.Name = "Clear"
ActionButton23.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_CURL.Buttons.Add(ActionButton21) Me.TXT_CURL.Buttons.Add(ActionButton21)
Me.TXT_CURL.Buttons.Add(ActionButton22)
Me.TXT_CURL.Buttons.Add(ActionButton23)
Me.TXT_CURL.CaptionText = "cURL" Me.TXT_CURL.CaptionText = "cURL"
Me.TXT_CURL.CaptionToolTipEnabled = True Me.TXT_CURL.CaptionToolTipEnabled = True
Me.TXT_CURL.CaptionToolTipText = "Path to curl.exe file" Me.TXT_CURL.CaptionToolTipText = "Path to curl.exe file"
@@ -2118,19 +2105,19 @@ Namespace Editors
' '
'TXT_GALLERYDL 'TXT_GALLERYDL
' '
ActionButton22.BackgroundImage = CType(resources.GetObject("ActionButton22.BackgroundImage"), System.Drawing.Image)
ActionButton22.Name = "Open"
ActionButton22.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton23.BackgroundImage = CType(resources.GetObject("ActionButton23.BackgroundImage"), System.Drawing.Image)
ActionButton23.Name = "Refresh"
ActionButton23.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton23.ToolTipText = "Try to find this program automatically (in SCrawler and/or system environment)"
ActionButton24.BackgroundImage = CType(resources.GetObject("ActionButton24.BackgroundImage"), System.Drawing.Image) ActionButton24.BackgroundImage = CType(resources.GetObject("ActionButton24.BackgroundImage"), System.Drawing.Image)
ActionButton24.Name = "Open" ActionButton24.Name = "Clear"
ActionButton24.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open ActionButton24.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
ActionButton25.BackgroundImage = CType(resources.GetObject("ActionButton25.BackgroundImage"), System.Drawing.Image) Me.TXT_GALLERYDL.Buttons.Add(ActionButton22)
ActionButton25.Name = "Refresh" Me.TXT_GALLERYDL.Buttons.Add(ActionButton23)
ActionButton25.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton25.ToolTipText = "Try to find this program automatically (in SCrawler and/or system environment)"
ActionButton26.BackgroundImage = CType(resources.GetObject("ActionButton26.BackgroundImage"), System.Drawing.Image)
ActionButton26.Name = "Clear"
ActionButton26.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_GALLERYDL.Buttons.Add(ActionButton24) Me.TXT_GALLERYDL.Buttons.Add(ActionButton24)
Me.TXT_GALLERYDL.Buttons.Add(ActionButton25)
Me.TXT_GALLERYDL.Buttons.Add(ActionButton26)
Me.TXT_GALLERYDL.CaptionText = "gallery-dl" Me.TXT_GALLERYDL.CaptionText = "gallery-dl"
Me.TXT_GALLERYDL.CaptionToolTipText = "Path to gallery-dl.exe file" Me.TXT_GALLERYDL.CaptionToolTipText = "Path to gallery-dl.exe file"
Me.TXT_GALLERYDL.CaptionWidth = 80.0R Me.TXT_GALLERYDL.CaptionWidth = 80.0R
@@ -2143,14 +2130,14 @@ Namespace Editors
' '
'TXT_CMD_ENCODING 'TXT_CMD_ENCODING
' '
ActionButton27.BackgroundImage = CType(resources.GetObject("ActionButton27.BackgroundImage"), System.Drawing.Image) ActionButton25.BackgroundImage = CType(resources.GetObject("ActionButton25.BackgroundImage"), System.Drawing.Image)
ActionButton27.Name = "Refresh" ActionButton25.Name = "Refresh"
ActionButton27.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh ActionButton25.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Refresh
ActionButton28.BackgroundImage = CType(resources.GetObject("ActionButton28.BackgroundImage"), System.Drawing.Image) ActionButton26.BackgroundImage = CType(resources.GetObject("ActionButton26.BackgroundImage"), System.Drawing.Image)
ActionButton28.Name = "Clear" ActionButton26.Name = "Clear"
ActionButton28.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton26.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_CMD_ENCODING.Buttons.Add(ActionButton27) Me.TXT_CMD_ENCODING.Buttons.Add(ActionButton25)
Me.TXT_CMD_ENCODING.Buttons.Add(ActionButton28) Me.TXT_CMD_ENCODING.Buttons.Add(ActionButton26)
Me.TXT_CMD_ENCODING.CaptionText = "CMD Encoding" Me.TXT_CMD_ENCODING.CaptionText = "CMD Encoding"
Me.TXT_CMD_ENCODING.CaptionToolTipEnabled = True Me.TXT_CMD_ENCODING.CaptionToolTipEnabled = True
Me.TXT_CMD_ENCODING.CaptionToolTipText = "Command line encoding" Me.TXT_CMD_ENCODING.CaptionToolTipText = "Command line encoding"
@@ -2253,10 +2240,10 @@ Namespace Editors
' '
'CMB_STD_OPEN_DBL 'CMB_STD_OPEN_DBL
' '
ActionButton29.BackgroundImage = CType(resources.GetObject("ActionButton29.BackgroundImage"), System.Drawing.Image) ActionButton27.BackgroundImage = CType(resources.GetObject("ActionButton27.BackgroundImage"), System.Drawing.Image)
ActionButton29.Name = "ArrowDown" ActionButton27.Name = "ArrowDown"
ActionButton29.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.ArrowDown ActionButton27.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.ArrowDown
Me.CMB_STD_OPEN_DBL.Buttons.Add(ActionButton29) Me.CMB_STD_OPEN_DBL.Buttons.Add(ActionButton27)
Me.CMB_STD_OPEN_DBL.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.Label Me.CMB_STD_OPEN_DBL.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.Label
Me.CMB_STD_OPEN_DBL.CaptionText = "DoubleClick opens" Me.CMB_STD_OPEN_DBL.CaptionText = "DoubleClick opens"
Me.CMB_STD_OPEN_DBL.CaptionToolTipEnabled = True Me.CMB_STD_OPEN_DBL.CaptionToolTipEnabled = True
@@ -2338,10 +2325,10 @@ Namespace Editors
' '
'TXT_PRG_TITLE 'TXT_PRG_TITLE
' '
ActionButton30.BackgroundImage = CType(resources.GetObject("ActionButton30.BackgroundImage"), System.Drawing.Image) ActionButton28.BackgroundImage = CType(resources.GetObject("ActionButton28.BackgroundImage"), System.Drawing.Image)
ActionButton30.Name = "Clear" ActionButton28.Name = "Clear"
ActionButton30.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton28.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_PRG_TITLE.Buttons.Add(ActionButton30) Me.TXT_PRG_TITLE.Buttons.Add(ActionButton28)
Me.TXT_PRG_TITLE.CaptionText = "Program title" Me.TXT_PRG_TITLE.CaptionText = "Program title"
Me.TXT_PRG_TITLE.CaptionToolTipEnabled = True Me.TXT_PRG_TITLE.CaptionToolTipEnabled = True
Me.TXT_PRG_TITLE.CaptionToolTipText = "Change the title of the main window if you need to" Me.TXT_PRG_TITLE.CaptionToolTipText = "Change the title of the main window if you need to"
@@ -2353,10 +2340,10 @@ Namespace Editors
' '
'TXT_PRG_DESCR 'TXT_PRG_DESCR
' '
ActionButton31.BackgroundImage = CType(resources.GetObject("ActionButton31.BackgroundImage"), System.Drawing.Image) ActionButton29.BackgroundImage = CType(resources.GetObject("ActionButton29.BackgroundImage"), System.Drawing.Image)
ActionButton31.Name = "Clear" ActionButton29.Name = "Clear"
ActionButton31.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton29.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_PRG_DESCR.Buttons.Add(ActionButton31) Me.TXT_PRG_DESCR.Buttons.Add(ActionButton29)
Me.TXT_PRG_DESCR.CaptionText = "Program description" Me.TXT_PRG_DESCR.CaptionText = "Program description"
Me.TXT_PRG_DESCR.CaptionToolTipEnabled = True Me.TXT_PRG_DESCR.CaptionToolTipEnabled = True
Me.TXT_PRG_DESCR.CaptionToolTipText = "Add some additional info to the program info if you need" Me.TXT_PRG_DESCR.CaptionToolTipText = "Add some additional info to the program info if you need"
@@ -2368,14 +2355,14 @@ Namespace Editors
' '
'TXT_USER_LIST_IMAGE 'TXT_USER_LIST_IMAGE
' '
ActionButton32.BackgroundImage = CType(resources.GetObject("ActionButton32.BackgroundImage"), System.Drawing.Image) ActionButton30.BackgroundImage = CType(resources.GetObject("ActionButton30.BackgroundImage"), System.Drawing.Image)
ActionButton32.Name = "Open" ActionButton30.Name = "Open"
ActionButton32.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open ActionButton30.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Open
ActionButton33.BackgroundImage = CType(resources.GetObject("ActionButton33.BackgroundImage"), System.Drawing.Image) ActionButton31.BackgroundImage = CType(resources.GetObject("ActionButton31.BackgroundImage"), System.Drawing.Image)
ActionButton33.Name = "Clear" ActionButton31.Name = "Clear"
ActionButton33.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton31.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_USER_LIST_IMAGE.Buttons.Add(ActionButton32) Me.TXT_USER_LIST_IMAGE.Buttons.Add(ActionButton30)
Me.TXT_USER_LIST_IMAGE.Buttons.Add(ActionButton33) Me.TXT_USER_LIST_IMAGE.Buttons.Add(ActionButton31)
Me.TXT_USER_LIST_IMAGE.CaptionText = "Userlist image" Me.TXT_USER_LIST_IMAGE.CaptionText = "Userlist image"
Me.TXT_USER_LIST_IMAGE.CaptionToolTipEnabled = True Me.TXT_USER_LIST_IMAGE.CaptionToolTipEnabled = True
Me.TXT_USER_LIST_IMAGE.CaptionToolTipText = "Background image for user list" Me.TXT_USER_LIST_IMAGE.CaptionToolTipText = "Background image for user list"
@@ -2449,10 +2436,10 @@ Namespace Editors
' '
'TXT_H_DEF_UserAgent 'TXT_H_DEF_UserAgent
' '
ActionButton34.BackgroundImage = CType(resources.GetObject("ActionButton34.BackgroundImage"), System.Drawing.Image) ActionButton32.BackgroundImage = CType(resources.GetObject("ActionButton32.BackgroundImage"), System.Drawing.Image)
ActionButton34.Name = "Clear" ActionButton32.Name = "Clear"
ActionButton34.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton32.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_H_DEF_UserAgent.Buttons.Add(ActionButton34) Me.TXT_H_DEF_UserAgent.Buttons.Add(ActionButton32)
Me.TXT_H_DEF_UserAgent.CaptionText = "UserAgent" Me.TXT_H_DEF_UserAgent.CaptionText = "UserAgent"
Me.TXT_H_DEF_UserAgent.CaptionWidth = 140.0R Me.TXT_H_DEF_UserAgent.CaptionWidth = 140.0R
Me.TXT_H_DEF_UserAgent.Dock = System.Windows.Forms.DockStyle.Fill Me.TXT_H_DEF_UserAgent.Dock = System.Windows.Forms.DockStyle.Fill
@@ -2463,10 +2450,10 @@ Namespace Editors
' '
'TXT_H_DEF_sec_ch_ua 'TXT_H_DEF_sec_ch_ua
' '
ActionButton35.BackgroundImage = CType(resources.GetObject("ActionButton35.BackgroundImage"), System.Drawing.Image) ActionButton33.BackgroundImage = CType(resources.GetObject("ActionButton33.BackgroundImage"), System.Drawing.Image)
ActionButton35.Name = "Clear" ActionButton33.Name = "Clear"
ActionButton35.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton33.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_H_DEF_sec_ch_ua.Buttons.Add(ActionButton35) Me.TXT_H_DEF_sec_ch_ua.Buttons.Add(ActionButton33)
Me.TXT_H_DEF_sec_ch_ua.CaptionText = "sec-ch-ua" Me.TXT_H_DEF_sec_ch_ua.CaptionText = "sec-ch-ua"
Me.TXT_H_DEF_sec_ch_ua.CaptionWidth = 140.0R Me.TXT_H_DEF_sec_ch_ua.CaptionWidth = 140.0R
Me.TXT_H_DEF_sec_ch_ua.Dock = System.Windows.Forms.DockStyle.Fill Me.TXT_H_DEF_sec_ch_ua.Dock = System.Windows.Forms.DockStyle.Fill
@@ -2477,10 +2464,10 @@ Namespace Editors
' '
'TXT_H_DEF_sec_ch_ua_full_version_list 'TXT_H_DEF_sec_ch_ua_full_version_list
' '
ActionButton36.BackgroundImage = CType(resources.GetObject("ActionButton36.BackgroundImage"), System.Drawing.Image) ActionButton34.BackgroundImage = CType(resources.GetObject("ActionButton34.BackgroundImage"), System.Drawing.Image)
ActionButton36.Name = "Clear" ActionButton34.Name = "Clear"
ActionButton36.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton34.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_H_DEF_sec_ch_ua_full_version_list.Buttons.Add(ActionButton36) Me.TXT_H_DEF_sec_ch_ua_full_version_list.Buttons.Add(ActionButton34)
Me.TXT_H_DEF_sec_ch_ua_full_version_list.CaptionText = "sec-ch-ua-full-version-list" Me.TXT_H_DEF_sec_ch_ua_full_version_list.CaptionText = "sec-ch-ua-full-version-list"
Me.TXT_H_DEF_sec_ch_ua_full_version_list.CaptionWidth = 140.0R Me.TXT_H_DEF_sec_ch_ua_full_version_list.CaptionWidth = 140.0R
Me.TXT_H_DEF_sec_ch_ua_full_version_list.Dock = System.Windows.Forms.DockStyle.Fill Me.TXT_H_DEF_sec_ch_ua_full_version_list.Dock = System.Windows.Forms.DockStyle.Fill
@@ -2491,10 +2478,10 @@ Namespace Editors
' '
'TXT_H_DEF_sec_ch_ua_platform 'TXT_H_DEF_sec_ch_ua_platform
' '
ActionButton37.BackgroundImage = CType(resources.GetObject("ActionButton37.BackgroundImage"), System.Drawing.Image) ActionButton35.BackgroundImage = CType(resources.GetObject("ActionButton35.BackgroundImage"), System.Drawing.Image)
ActionButton37.Name = "Clear" ActionButton35.Name = "Clear"
ActionButton37.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton35.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_H_DEF_sec_ch_ua_platform.Buttons.Add(ActionButton37) Me.TXT_H_DEF_sec_ch_ua_platform.Buttons.Add(ActionButton35)
Me.TXT_H_DEF_sec_ch_ua_platform.CaptionText = "sec-ch-ua-platform" Me.TXT_H_DEF_sec_ch_ua_platform.CaptionText = "sec-ch-ua-platform"
Me.TXT_H_DEF_sec_ch_ua_platform.CaptionWidth = 140.0R Me.TXT_H_DEF_sec_ch_ua_platform.CaptionWidth = 140.0R
Me.TXT_H_DEF_sec_ch_ua_platform.Dock = System.Windows.Forms.DockStyle.Fill Me.TXT_H_DEF_sec_ch_ua_platform.Dock = System.Windows.Forms.DockStyle.Fill
@@ -2505,10 +2492,10 @@ Namespace Editors
' '
'TXT_H_DEF_sec_ch_ua_platform_version 'TXT_H_DEF_sec_ch_ua_platform_version
' '
ActionButton38.BackgroundImage = CType(resources.GetObject("ActionButton38.BackgroundImage"), System.Drawing.Image) ActionButton36.BackgroundImage = CType(resources.GetObject("ActionButton36.BackgroundImage"), System.Drawing.Image)
ActionButton38.Name = "Clear" ActionButton36.Name = "Clear"
ActionButton38.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear ActionButton36.Tag = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons.Clear
Me.TXT_H_DEF_sec_ch_ua_platform_version.Buttons.Add(ActionButton38) Me.TXT_H_DEF_sec_ch_ua_platform_version.Buttons.Add(ActionButton36)
Me.TXT_H_DEF_sec_ch_ua_platform_version.CaptionText = "sec-ch-ua-platform-version" Me.TXT_H_DEF_sec_ch_ua_platform_version.CaptionText = "sec-ch-ua-platform-version"
Me.TXT_H_DEF_sec_ch_ua_platform_version.CaptionWidth = 140.0R Me.TXT_H_DEF_sec_ch_ua_platform_version.CaptionWidth = 140.0R
Me.TXT_H_DEF_sec_ch_ua_platform_version.Dock = System.Windows.Forms.DockStyle.Fill Me.TXT_H_DEF_sec_ch_ua_platform_version.Dock = System.Windows.Forms.DockStyle.Fill
@@ -2571,19 +2558,6 @@ Namespace Editors
Me.CONTAINER_MAIN.TabIndex = 0 Me.CONTAINER_MAIN.TabIndex = 0
Me.CONTAINER_MAIN.TopToolStripPanelVisible = False Me.CONTAINER_MAIN.TopToolStripPanelVisible = False
' '
'CH_FEED_OPEN_CTRLF
'
Me.CH_FEED_OPEN_CTRLF.AutoSize = True
Me.CH_FEED_OPEN_CTRLF.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_FEED_OPEN_CTRLF.Location = New System.Drawing.Point(4, 299)
Me.CH_FEED_OPEN_CTRLF.Name = "CH_FEED_OPEN_CTRLF"
Me.CH_FEED_OPEN_CTRLF.Size = New System.Drawing.Size(613, 19)
Me.CH_FEED_OPEN_CTRLF.TabIndex = 11
Me.CH_FEED_OPEN_CTRLF.Text = "Use 'Ctrl+F' to open the Feed"
TT_MAIN.SetToolTip(Me.CH_FEED_OPEN_CTRLF, "If checked, 'Ctrl+F' will be used to open the Feed. Otherwise, 'Alt+F' will be us" &
"ed.")
Me.CH_FEED_OPEN_CTRLF.UseVisualStyleBackColor = True
'
'GlobalSettingsForm 'GlobalSettingsForm
' '
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
@@ -2611,7 +2585,6 @@ Namespace Editors
CType(Me.TXT_MAX_JOBS_USERS, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_MAX_JOBS_USERS, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_MAX_JOBS_CHANNELS, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_MAX_JOBS_CHANNELS, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_IMGUR_CLIENT_ID, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_IMGUR_CLIENT_ID, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.TXT_USER_AGENT, System.ComponentModel.ISupportInitialize).EndInit()
TP_FILE_NAME.ResumeLayout(False) TP_FILE_NAME.ResumeLayout(False)
TP_FILE_NAME.PerformLayout() TP_FILE_NAME.PerformLayout()
TP_FILE_PATTERNS.ResumeLayout(False) TP_FILE_PATTERNS.ResumeLayout(False)
@@ -2749,7 +2722,6 @@ Namespace Editors
Private WithEvents CH_NOTIFY_AUTO_DOWN As CheckBox Private WithEvents CH_NOTIFY_AUTO_DOWN As CheckBox
Private WithEvents CH_NOTIFY_CHANNELS As CheckBox Private WithEvents CH_NOTIFY_CHANNELS As CheckBox
Private WithEvents CH_DOWN_REPARSE_MISSING As CheckBox Private WithEvents CH_DOWN_REPARSE_MISSING As CheckBox
Private WithEvents TXT_USER_AGENT As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents TXT_USER_LIST_IMAGE As PersonalUtilities.Forms.Controls.TextBoxExtended Private WithEvents TXT_USER_LIST_IMAGE As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents TXT_FEED_CENTER_IMAGE As PersonalUtilities.Forms.Controls.TextBoxExtended Private WithEvents TXT_FEED_CENTER_IMAGE As PersonalUtilities.Forms.Controls.TextBoxExtended
Private WithEvents CH_NAME_SITE_FRIENDLY As CheckBox Private WithEvents CH_NAME_SITE_FRIENDLY As CheckBox

View File

@@ -189,30 +189,6 @@
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton7.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
QVQ4T2P4//8/QczOJyyqHpzfiE0OQwAZC8iqszAzs7CJ69o4BR768V/W2jcGXQ0KB4aFNS3dDQtnrbCb
ePCK48wTN1wXXXzge/jXf/clV55zC4hIIatF0cjIyMikElzc57z0wX+XHd/+2+//99/ywP//xlu//tdb
+eK/4Zp3/1WTOhYzARViNUAluKjTdf37/0ZTTn9TbdhwXblhwwW1/qOP1Ja9+K8w+95/6cm3/6v2Xvkv
qKjniGGAoIqRpW3/4e8S9uGdzFz82gwMDFxAzCxm4ZegtuLDf+VJ1/8rZM25IqLvnM/CximCYYCic1QN
v7x2JIwPwyrJ3XNUylddE9G2TWNmZOBDl4czmJiZMSRBmFdSyYyJgUEQmxwIYxWEYXZBCUls4sgYq6CA
prWNbtG8nXKeaVPR5XiVjSxEzf0yYXy4BBMLO6eQjoOXZvrkbbazrv53Xf/2v4CSbjBMXkhBl1/CMyNZ
qWnvGy5pNQ+YONwAfjXzAOupl/47LLr333L50/96q9/8l23YdES6cO5KuYqVW+R7Tj6SnfP0v4hryjyY
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value>
</data>
<data name="ActionButton8.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<metadata name="TP_FILE_NAME.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TP_FILE_NAME.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
@@ -269,7 +245,7 @@ You can find more detailed information about the missing posts in the form that
<metadata name="TP_BEHAVIOR.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TP_BEHAVIOR.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<data name="ActionButton9.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton7.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
@@ -277,7 +253,7 @@ You can find more detailed information about the missing posts in the form that
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<data name="ActionButton10.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton8.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
@@ -300,7 +276,7 @@ You can find more detailed information about the missing posts in the form that
<metadata name="TP_DOWNLOADING.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TP_DOWNLOADING.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<data name="ActionButton11.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton9.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
@@ -311,7 +287,7 @@ You can find more detailed information about the missing posts in the form that
cMaRN0UdBBkAAAAASUVORK5CYII= cMaRN0UdBBkAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="ActionButton12.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton10.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
@@ -334,7 +310,7 @@ You can find more detailed information about the missing posts in the form that
<metadata name="TP_FEED_SES.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TP_FEED_SES.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<data name="ActionButton13.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton11.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
@@ -350,7 +326,7 @@ You can find more detailed information about the missing posts in the form that
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg== VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="ActionButton14.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton12.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
@@ -376,7 +352,7 @@ You can find more detailed information about the missing posts in the form that
<metadata name="TP_ENVIR.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TP_ENVIR.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<data name="ActionButton15.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton13.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
@@ -387,7 +363,7 @@ You can find more detailed information about the missing posts in the form that
cMaRN0UdBBkAAAAASUVORK5CYII= cMaRN0UdBBkAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="ActionButton16.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton14.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
@@ -403,15 +379,50 @@ You can find more detailed information about the missing posts in the form that
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg== VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="ActionButton17.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton15.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton16.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
cMaRN0UdBBkAAAAASUVORK5CYII=
</value>
</data>
<data name="ActionButton17.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
QVQ4T2P4//8/QczOJyyqHpzfiE0OQwAZC8iqszAzs7CJ69o4BR768V/W2jcGXQ0KB4aFNS3dDQtnrbCb
ePCK48wTN1wXXXzge/jXf/clV55zC4hIIatF0cjIyMikElzc57z0wX+XHd/+2+//99/ywP//xlu//tdb
+eK/4Zp3/1WTOhYzARViNUAluKjTdf37/0ZTTn9TbdhwXblhwwW1/qOP1Ja9+K8w+95/6cm3/6v2Xvkv
qKjniGGAoIqRpW3/4e8S9uGdzFz82gwMDFxAzCxm4ZegtuLDf+VJ1/8rZM25IqLvnM/CximCYYCic1QN
v7x2JIwPwyrJ3XNUylddE9G2TWNmZOBDl4czmJiZMSRBmFdSyYyJgUEQmxwIYxWEYXZBCUls4sgYq6CA
prWNbtG8nXKeaVPR5XiVjSxEzf0yYXy4BBMLO6eQjoOXZvrkbbazrv53Xf/2v4CSbjBMXkhBl1/CMyNZ
qWnvGy5pNQ+YONwAfjXzAOupl/47LLr333L50/96q9/8l23YdES6cO5KuYqVW+R7Tj6SnfP0v4hryjyY
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="ActionButton18.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton18.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton19.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
@@ -422,7 +433,7 @@ You can find more detailed information about the missing posts in the form that
cMaRN0UdBBkAAAAASUVORK5CYII= cMaRN0UdBBkAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="ActionButton19.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton20.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
@@ -436,17 +447,17 @@ You can find more detailed information about the missing posts in the form that
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74 HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg== VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value>
</data>
<data name="ActionButton20.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<data name="ActionButton21.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton21.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton22.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
@@ -457,7 +468,7 @@ You can find more detailed information about the missing posts in the form that
cMaRN0UdBBkAAAAASUVORK5CYII= cMaRN0UdBBkAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="ActionButton22.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton23.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
@@ -473,23 +484,12 @@ You can find more detailed information about the missing posts in the form that
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg== VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="ActionButton23.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton24.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton24.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
WQwhyWIyJIUW5NqyPb7oCVtIlhVTwYf8nv7/t2zJagel9KmqKsIACYL9RjI8UHz5zshougZr/AEvbxEP
aZCDBY3VslixaJvX3wzkkDiOwbZtDRGA5vdNAg+TL27qgmt5XkBG/gTdAG7Gt+3PP9oOaEGFCVEC6rp+
5g9MfM/c5e4OsEZMZkQEtGL5H2DdZ5JRArDwPA+iKII0TfkC9vroC9j5vq8JTWw3WzWgLMtZGIaa0MR8
vlAD8PYlSaIJTTiOowY0p0Bc19XEJo6HE59FAPuMzyAINKGJ1XLFZxHALtMrnkBXOIQIIIQ8YvF/KrgB
cMaRN0UdBBkAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="ActionButton25.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton25.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
@@ -514,30 +514,6 @@ You can find more detailed information about the missing posts in the form that
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton27.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE
QVQ4T2P4//8/QczOJyyqHpzfiE0OQwAZC8iqszAzs7CJ69o4BR768V/W2jcGXQ0KB4aFNS3dDQtnrbCb
ePCK48wTN1wXXXzge/jXf/clV55zC4hIIatF0cjIyMikElzc57z0wX+XHd/+2+//99/ywP//xlu//tdb
+eK/4Zp3/1WTOhYzARViNUAluKjTdf37/0ZTTn9TbdhwXblhwwW1/qOP1Ja9+K8w+95/6cm3/6v2Xvkv
qKjniGGAoIqRpW3/4e8S9uGdzFz82gwMDFxAzCxm4ZegtuLDf+VJ1/8rZM25IqLvnM/CximCYYCic1QN
v7x2JIwPwyrJ3XNUylddE9G2TWNmZOBDl4czmJiZMSRBmFdSyYyJgUEQmxwIYxWEYXZBCUls4sgYq6CA
prWNbtG8nXKeaVPR5XiVjSxEzf0yYXy4BBMLO6eQjoOXZvrkbbazrv53Xf/2v4CSbjBMXkhBl1/CMyNZ
qWnvGy5pNQ+YONwAfjXzAOupl/47LLr333L50/96q9/8l23YdES6cO5KuYqVW+R7Tj6SnfP0v4hryjyY
HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74
qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG
VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg==
</value>
</data>
<data name="ActionButton28.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<metadata name="TAB_STD.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TAB_STD.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
@@ -546,7 +522,7 @@ You can find more detailed information about the missing posts in the form that
<metadata name="TP_STD.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TP_STD.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<data name="ActionButton29.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton27.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE65JREFUeF7t iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE65JREFUeF7t
3X2sJWddB/DdLi2lQG2hdOHuvfM887J7Cxca4ELTQMDWKigIFpBAEAgi9g+CJpJo9Q8NJhgBiYZIYspL 3X2sJWddB/DdLi2lQG2hdOHuvfM887J7Cxca4ELTQMDWKigIFpBAEAgi9g+CJpJo9Q8NJhgBiYZIYspL
@@ -642,23 +618,23 @@ You can find more detailed information about the missing posts in the form that
<metadata name="TP_DESIGN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TP_DESIGN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<data name="ActionButton28.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton29.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton30.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton30.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton31.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton32.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP
@@ -669,7 +645,7 @@ You can find more detailed information about the missing posts in the form that
cMaRN0UdBBkAAAAASUVORK5CYII= cMaRN0UdBBkAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="ActionButton33.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton31.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
@@ -680,6 +656,22 @@ You can find more detailed information about the missing posts in the form that
<metadata name="TP_HEADERS_DEF.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TP_HEADERS_DEF.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<data name="ActionButton32.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton33.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton34.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ActionButton34.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
@@ -702,22 +694,6 @@ You can find more detailed information about the missing posts in the form that
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton37.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value>
</data>
<data name="ActionButton38.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go
tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX
AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<metadata name="TAB_HEADERS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="TAB_HEADERS.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">

View File

@@ -38,7 +38,6 @@ Namespace Editors
TXT_MAX_JOBS_USERS.Value = .MaxUsersJobsCount.Value TXT_MAX_JOBS_USERS.Value = .MaxUsersJobsCount.Value
TXT_MAX_JOBS_CHANNELS.Value = .ChannelsMaxJobsCount.Value TXT_MAX_JOBS_CHANNELS.Value = .ChannelsMaxJobsCount.Value
CH_CHECK_VER_START.Checked = .CheckUpdatesAtStart CH_CHECK_VER_START.Checked = .CheckUpdatesAtStart
TXT_USER_AGENT.Text = .UserAgent
TXT_IMGUR_CLIENT_ID.Text = .ImgurClientID TXT_IMGUR_CLIENT_ID.Text = .ImgurClientID
'Design 'Design
TXT_PRG_TITLE.Text = .ProgramText TXT_PRG_TITLE.Text = .ProgramText
@@ -255,8 +254,6 @@ Namespace Editors
.MaxUsersJobsCount.Value = CInt(TXT_MAX_JOBS_USERS.Value) .MaxUsersJobsCount.Value = CInt(TXT_MAX_JOBS_USERS.Value)
.ChannelsMaxJobsCount.Value = TXT_MAX_JOBS_CHANNELS.Value .ChannelsMaxJobsCount.Value = TXT_MAX_JOBS_CHANNELS.Value
.CheckUpdatesAtStart.Value = CH_CHECK_VER_START.Checked .CheckUpdatesAtStart.Value = CH_CHECK_VER_START.Checked
.UserAgent.Value = TXT_USER_AGENT.Text
UserAgentChanged = .UserAgent.ChangesDetected
.ImgurClientID.Value = TXT_IMGUR_CLIENT_ID.Text .ImgurClientID.Value = TXT_IMGUR_CLIENT_ID.Text
'Design 'Design
.ProgramText.Value = TXT_PRG_TITLE.Text .ProgramText.Value = TXT_PRG_TITLE.Text
@@ -276,6 +273,7 @@ Namespace Editors
.CMDEncoding.ChangesDetected .CMDEncoding.ChangesDetected
'Headers 'Headers
.HEADER_UserAgent.Value = TXT_H_DEF_UserAgent.Text .HEADER_UserAgent.Value = TXT_H_DEF_UserAgent.Text
UserAgentChanged = .HEADER_UserAgent.ChangesDetected
.HEADER_sec_ch_ua.Value = TXT_H_DEF_sec_ch_ua.Text .HEADER_sec_ch_ua.Value = TXT_H_DEF_sec_ch_ua.Text
.HEADER_sec_ch_ua_full_version_list.Value = TXT_H_DEF_sec_ch_ua_full_version_list.Text .HEADER_sec_ch_ua_full_version_list.Value = TXT_H_DEF_sec_ch_ua_full_version_list.Text
.HEADER_sec_ch_ua_platform.Value = TXT_H_DEF_sec_ch_ua_platform.Text .HEADER_sec_ch_ua_platform.Value = TXT_H_DEF_sec_ch_ua_platform.Text
@@ -407,9 +405,6 @@ Namespace Editors
Private Sub TXT_MAX_JOBS_CHANNELS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles TXT_MAX_JOBS_CHANNELS.ActionOnButtonClick Private Sub TXT_MAX_JOBS_CHANNELS_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As EventArgs) Handles TXT_MAX_JOBS_CHANNELS.ActionOnButtonClick
If Sender.DefaultButton = ADB.Refresh Then TXT_MAX_JOBS_CHANNELS.Value = SettingsCLS.DefaultMaxDownloadingTasks If Sender.DefaultButton = ADB.Refresh Then TXT_MAX_JOBS_CHANNELS.Value = SettingsCLS.DefaultMaxDownloadingTasks
End Sub End Sub
Private Sub TXT_USER_AGENT_ActionOnButtonClick(ByVal Sender As ActionButton, ByVal e As ActionButtonEventArgs) Handles TXT_USER_AGENT.ActionOnButtonClick
If Sender.DefaultButton = ADB.Refresh Then TXT_USER_AGENT.Text = Settings.UserAgent.Value
End Sub
Private Sub ChangePositionControlsEnabling() Handles OPT_FILE_NAME_REPLACE.CheckedChanged, OPT_FILE_NAME_ADD_DATE.CheckedChanged Private Sub ChangePositionControlsEnabling() Handles OPT_FILE_NAME_REPLACE.CheckedChanged, OPT_FILE_NAME_ADD_DATE.CheckedChanged
Dim b As Boolean = OPT_FILE_NAME_ADD_DATE.Checked And OPT_FILE_NAME_ADD_DATE.Enabled Dim b As Boolean = OPT_FILE_NAME_ADD_DATE.Checked And OPT_FILE_NAME_ADD_DATE.Enabled
OPT_FILE_DATE_START.Enabled = b OPT_FILE_DATE_START.Enabled = b

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("2025.1.12.0")> <Assembly: AssemblyVersion("2025.2.25.0")>
<Assembly: AssemblyFileVersion("2025.1.12.0")> <Assembly: AssemblyFileVersion("2025.2.25.0")>
<Assembly: NeutralResourcesLanguage("en")> <Assembly: NeutralResourcesLanguage("en")>

View File

@@ -88,6 +88,7 @@ Namespace Plugin.Hosts
ByRef _Vids As XMLValue(Of Boolean)) As IEnumerable(Of PluginHost) ByRef _Vids As XMLValue(Of Boolean)) As IEnumerable(Of PluginHost)
Return {New PluginHost(GetType(API.Reddit.SiteSettings), _XML, GlobalPath, _Temp, _Imgs, _Vids), Return {New PluginHost(GetType(API.Reddit.SiteSettings), _XML, GlobalPath, _Temp, _Imgs, _Vids),
New PluginHost(GetType(API.Twitter.SiteSettings), _XML, GlobalPath, _Temp, _Imgs, _Vids), New PluginHost(GetType(API.Twitter.SiteSettings), _XML, GlobalPath, _Temp, _Imgs, _Vids),
New PluginHost(GetType(API.Bluesky.SiteSettings), _XML, GlobalPath, _Temp, _Imgs, _Vids),
New PluginHost(GetType(API.Mastodon.SiteSettings), _XML, GlobalPath, _Temp, _Imgs, _Vids), New PluginHost(GetType(API.Mastodon.SiteSettings), _XML, GlobalPath, _Temp, _Imgs, _Vids),
New PluginHost(GetType(API.Instagram.SiteSettings), _XML, GlobalPath, _Temp, _Imgs, _Vids), New PluginHost(GetType(API.Instagram.SiteSettings), _XML, GlobalPath, _Temp, _Imgs, _Vids),
New PluginHost(GetType(API.ThreadsNet.SiteSettings), _XML, GlobalPath, _Temp, _Imgs, _Vids), New PluginHost(GetType(API.ThreadsNet.SiteSettings), _XML, GlobalPath, _Temp, _Imgs, _Vids),

View File

@@ -48,6 +48,7 @@ Namespace Plugin.Hosts
.Thrower = Me .Thrower = Me
.LogProvider = LogConnector .LogProvider = LogConnector
.Name = Name .Name = Name
.NameTrue = NameTrue(True)
.ID = ID .ID = ID
.Options = Options .Options = Options
.ParseUserMediaOnly = ParseUserMediaOnly .ParseUserMediaOnly = ParseUserMediaOnly
@@ -78,6 +79,7 @@ Namespace Plugin.Hosts
UserDescriptionUpdate(.UserDescription) UserDescriptionUpdate(.UserDescription)
UserExists = .UserExists UserExists = .UserExists
UserSuspended = .UserSuspended UserSuspended = .UserSuspended
NameTrue = .NameTrue
End With End With
End Sub End Sub
Friend Overrides Sub DownloadSingleObject(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken) Friend Overrides Sub DownloadSingleObject(ByVal Data As IYouTubeMediaContainer, ByVal Token As CancellationToken)

View File

@@ -168,6 +168,7 @@
<Compile Include="API\Base\Declarations.vb" /> <Compile Include="API\Base\Declarations.vb" />
<Compile Include="API\Base\DeclaredNames.vb" /> <Compile Include="API\Base\DeclaredNames.vb" />
<Compile Include="API\Base\DownDetector.vb" /> <Compile Include="API\Base\DownDetector.vb" />
<Compile Include="API\Base\EditorExchangeOptionsBase.vb" />
<Compile Include="API\Base\GDL.vb" /> <Compile Include="API\Base\GDL.vb" />
<Compile Include="API\Base\IUserData.vb" /> <Compile Include="API\Base\IUserData.vb" />
<Compile Include="API\Base\M3U8Base.vb" /> <Compile Include="API\Base\M3U8Base.vb" />
@@ -189,6 +190,10 @@
<Compile Include="API\Base\Structures.vb" /> <Compile Include="API\Base\Structures.vb" />
<Compile Include="API\Base\TokenBatch.vb" /> <Compile Include="API\Base\TokenBatch.vb" />
<Compile Include="API\Base\YTDLP.vb" /> <Compile Include="API\Base\YTDLP.vb" />
<Compile Include="API\Bluesky\Declarations.vb" />
<Compile Include="API\Bluesky\M3U8.vb" />
<Compile Include="API\Bluesky\SiteSettings.vb" />
<Compile Include="API\Bluesky\UserData.vb" />
<Compile Include="API\Facebook\Declarations.vb" /> <Compile Include="API\Facebook\Declarations.vb" />
<Compile Include="API\Facebook\SiteSettings.vb" /> <Compile Include="API\Facebook\SiteSettings.vb" />
<Compile Include="API\Facebook\UserData.vb" /> <Compile Include="API\Facebook\UserData.vb" />
@@ -227,6 +232,7 @@
<Compile Include="API\PathPlugin\SiteSettings.vb" /> <Compile Include="API\PathPlugin\SiteSettings.vb" />
<Compile Include="API\PathPlugin\UserData.vb" /> <Compile Include="API\PathPlugin\UserData.vb" />
<Compile Include="API\Pinterest\Declarations.vb" /> <Compile Include="API\Pinterest\Declarations.vb" />
<Compile Include="API\Pinterest\EditorExchangeOptions.vb" />
<Compile Include="API\Pinterest\SiteSettings.vb" /> <Compile Include="API\Pinterest\SiteSettings.vb" />
<Compile Include="API\Pinterest\UserData.vb" /> <Compile Include="API\Pinterest\UserData.vb" />
<Compile Include="API\PornHub\Declarations.vb" /> <Compile Include="API\PornHub\Declarations.vb" />
@@ -660,6 +666,7 @@
<ItemGroup> <ItemGroup>
<None Include=".editorconfig" /> <None Include=".editorconfig" />
<None Include="API\OnlyFans\OFScraperConfigPattern.json" /> <None Include="API\OnlyFans\OFScraperConfigPattern.json" />
<None Include="Content\Icons\SiteIcons\TwitterIconNew_32.ico" />
<None Include="Content\Pictures\ApplicationPic_16.png" /> <None Include="Content\Pictures\ApplicationPic_16.png" />
<None Include="Content\Pictures\BookmarkBlack_16.png" /> <None Include="Content\Pictures\BookmarkBlack_16.png" />
<None Include="Content\Pictures\DBPic_32.png" /> <None Include="Content\Pictures\DBPic_32.png" />
@@ -797,6 +804,8 @@
<Content Include="API\OnlyFans\DynamicRules.txt" /> <Content Include="API\OnlyFans\DynamicRules.txt" />
<Content Include="API\OnlyFans\DynamicRulesAll.txt" /> <Content Include="API\OnlyFans\DynamicRulesAll.txt" />
<Content Include="API\OnlyFans\OFScraperConfigPatternConstants.txt" /> <Content Include="API\OnlyFans\OFScraperConfigPatternConstants.txt" />
<Content Include="Content\Icons\SiteIcons\BlueskyIcon_32.ico" />
<Content Include="Content\Pictures\SitePictures\BlueskyPic_32.png" />
<Content Include="Content\Pictures\CutPic_48.png" /> <Content Include="Content\Pictures\CutPic_48.png" />
<Content Include="Content\Pictures\FindPic_16.png" /> <Content Include="Content\Pictures\FindPic_16.png" />
</ItemGroup> </ItemGroup>

View File

@@ -173,6 +173,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
Friend ReadOnly Plugins As List(Of PluginHost) Friend ReadOnly Plugins As List(Of PluginHost)
Friend ReadOnly Property Users As List(Of IUserData) Friend ReadOnly Property Users As List(Of IUserData)
Friend ReadOnly Property UsersList As List(Of UserInfo) Friend ReadOnly Property UsersList As List(Of UserInfo)
Private ReadOnly Property UsersListProtected As Boolean = False
Friend Property Channels As Reddit.ChannelsCollection Friend Property Channels As Reddit.ChannelsCollection
Friend ReadOnly Property Labels As LabelsKeeper Friend ReadOnly Property Labels As LabelsKeeper
Friend ReadOnly Property Groups As Groups.DownloadGroupCollection Friend ReadOnly Property Groups As Groups.DownloadGroupCollection
@@ -193,7 +194,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
Private ReadOnly BlackListFile As SFile = $"{SettingsFolderName}\BlackList.txt" Private ReadOnly BlackListFile As SFile = $"{SettingsFolderName}\BlackList.txt"
Private ReadOnly UsersSettingsFile As SFile = $"{SettingsFolderName}\Users.xml" Private ReadOnly UsersSettingsFile As SFile = $"{SettingsFolderName}\Users.xml"
Private ReadOnly Property SettingsVersion As XMLValue(Of Integer) Private ReadOnly Property SettingsVersion As XMLValue(Of Integer)
Private Const SettingsVersionCurrent As Integer = 1 Private Const SettingsVersionCurrent As Integer = 2
Friend ShortcutOpenFeed As New ButtonKey(Keys.F, True) Friend ShortcutOpenFeed As New ButtonKey(Keys.F, True)
Friend ShortcutOpenSearch As New ButtonKey(Keys.F,, True) Friend ShortcutOpenSearch As New ButtonKey(Keys.F,, True)
Private Sub ChangeFeedOpenMode() Private Sub ChangeFeedOpenMode()
@@ -228,10 +229,10 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
EnvironmentProgramsList = New List(Of String) EnvironmentProgramsList = New List(Of String)
SettingsVersion = New XMLValue(Of Integer)("SettingsVersion", 0, MyXML) SettingsVersion = New XMLValue(Of Integer)("SettingsVersion", 0, MyXML)
UsersListProtected = MyXML.Value("UsersListProtected").FromXML(Of Boolean)(False)
Dim n() As String = {"Scheduler"} Dim n() As String = {"Scheduler"}
AutomationFile = New XMLValue(Of String)("File",, MyXML, n) AutomationFile = New XMLValue(Of String)("File",, MyXML, n)
If SettingsVersion.Value = 0 AndAlso MyXML.Contains(AutomationFile.Name) Then AutomationFile.Value = MyXML.Value(AutomationFile.Name)
AutomationScript = New XMLValueUse(Of String)("Script", String.Empty,, MyXML, n) AutomationScript = New XMLValueUse(Of String)("Script", String.Empty,, MyXML, n)
AutomationScript_ExcludeManual = New XMLValue(Of Boolean)("ScriptExcludeManual", True, MyXML, n) AutomationScript_ExcludeManual = New XMLValue(Of Boolean)("ScriptExcludeManual", True, MyXML, n)
@@ -264,7 +265,6 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
MaxSmallImageHeight = New XMLValue(Of Integer)("MaxSmallImageHeight", 15, MyXML, n) MaxSmallImageHeight = New XMLValue(Of Integer)("MaxSmallImageHeight", 15, MyXML, n)
CollectionsPath = New XMLValue(Of String)("CollectionsPath", CollectionsFolderName, MyXML, n) CollectionsPath = New XMLValue(Of String)("CollectionsPath", CollectionsFolderName, MyXML, n)
MaxUsersJobsCount = New XMLValue(Of Integer)("MaxJobsCount", DefaultMaxDownloadingTasks, MyXML, n) MaxUsersJobsCount = New XMLValue(Of Integer)("MaxJobsCount", DefaultMaxDownloadingTasks, MyXML, n)
UserAgent = New XMLValue(Of String)("UserAgent",, MyXML, n)
ImgurClientID = New XMLValue(Of String)("ImgurClientID", String.Empty, MyXML, {Name_Node_Sites}) ImgurClientID = New XMLValue(Of String)("ImgurClientID", String.Empty, MyXML, {Name_Node_Sites})
'Basis: new version 'Basis: new version
@@ -333,7 +333,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
DefaultDownloadImages = New XMLValue(Of Boolean)("DownloadImages", True, MyXML, n) DefaultDownloadImages = New XMLValue(Of Boolean)("DownloadImages", True, MyXML, n)
DefaultDownloadVideos = New XMLValue(Of Boolean)("DownloadVideos", True, MyXML, n) DefaultDownloadVideos = New XMLValue(Of Boolean)("DownloadVideos", True, MyXML, n)
DownloadNativeImageFormat = New XMLValue(Of Boolean)("DownloadNativeImageFormat", True, MyXML, n) DownloadNativeImageFormat = New XMLValue(Of Boolean)("DownloadNativeImageFormat", True, MyXML, n)
UserSiteNameAsFriendly = New XMLValue(Of Boolean)("UserSiteNameAsFriendly", False, MyXML, n) UserSiteNameAsFriendly = New XMLValue(Of Boolean)("UserSiteNameAsFriendly", True, MyXML, n)
'STDownloader 'STDownloader
n = {"Downloader"} n = {"Downloader"}
@@ -367,6 +367,8 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
UseDefaultAccountIfMissing = New XMLValue(Of Boolean)("UseDefaultAccountIfMissing", True, MyXML, n) UseDefaultAccountIfMissing = New XMLValue(Of Boolean)("UseDefaultAccountIfMissing", True, MyXML, n)
AutomationBrushUndownloadedPlansMinutes = New XMLValue(Of Integer)("AutomationBrushUndownloadedPlansMinutes", 10080, MyXML, n) AutomationBrushUndownloadedPlansMinutes = New XMLValue(Of Integer)("AutomationBrushUndownloadedPlansMinutes", 10080, MyXML, n)
DownDetectorEnabled = New XMLValue(Of Boolean)("DownDetectorEnabled", True, MyXML, n) DownDetectorEnabled = New XMLValue(Of Boolean)("DownDetectorEnabled", True, MyXML, n)
'TODELETE: DownDetectorEnabled change
If SettingsVersion.Value < SettingsVersionCurrent Then DownDetectorEnabled.Value = False 'SettingsVersionCurrent = 2
'Downloading: file naming 'Downloading: file naming
n = {"Downloading", "FileName"} n = {"Downloading", "FileName"}
@@ -516,6 +518,8 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
Dim NeedUpdate As Boolean = False Dim NeedUpdate As Boolean = False
Dim i%, indx% Dim i%, indx%
Dim errStr As Func(Of Date, String) = Function(d) IIf(UsersListProtected, String.Empty,
$"It will be removed from SCrawler on {d.ToStringDate(DateTimeDefaultProvider)}.")
Dim UsersListInitialCount% = UsersList.Count Dim UsersListInitialCount% = UsersList.Count
Dim iUser As UserInfo Dim iUser As UserInfo
Dim userFileExists As Boolean, pluginFound As Boolean Dim userFileExists As Boolean, pluginFound As Boolean
@@ -531,7 +535,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
If .Plugin.IsEmptyString Then If .Plugin.IsEmptyString Then
pluginFound = False pluginFound = False
If .Site.IsEmptyString Then If .Site.IsEmptyString Then
MyMainLOG = $"The corresponding plugin was not found for the user [{ .Name}]. The user was removed from SCrawler." MyMainLOG = $"The corresponding plugin was not found for the user [{ .Name}].{IIf(UsersListProtected, String.Empty, " The user has been removed from SCrawler.")}"
Else Else
indx = __plugins.FindIndex(Function(p) p.Value.ToLower = .Site.ToLower) indx = __plugins.FindIndex(Function(p) p.Value.ToLower = .Site.ToLower)
If indx >= 0 Then If indx >= 0 Then
@@ -561,19 +565,17 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
If .LastSeen.HasValue Then .LastSeen = Nothing : NeedUpdate = True If .LastSeen.HasValue Then .LastSeen = Nothing : NeedUpdate = True
Else Else
.LastSeen = Now .LastSeen = Now
MyMainLOG = $"The user [{ .Site}: { .Name}] was not found. " & MyMainLOG = $"The user [{ .Site}: { .Name}] was not found. " & errStr(.LastSeen.Value)
$"It will be removed from SCrawler on { .LastSeen.Value.ToStringDate(DateTimeDefaultProvider)}."
NeedUpdate = True NeedUpdate = True
End If End If
ElseIf userFileExists Then ElseIf userFileExists Then
If .Protected Then If .Protected Then
If Not .LastSeen.HasValue Then .LastSeen = Now : NeedUpdate = True If Not .LastSeen.HasValue Then .LastSeen = Now : NeedUpdate = True
MyMainLOG = $"The corresponding plugin was not found for the user [{ .Site}: { .Name}]. " & MyMainLOG = $"The corresponding plugin was not found for the user [{ .Site}: { .Name}]. " & errStr(.LastSeen.Value)
$"It will be removed from SCrawler on { .LastSeen.Value.ToStringDate(DateTimeDefaultProvider)}."
Else Else
If .LastSeen.HasValue Then .LastSeen = Nothing : NeedUpdate = True If .LastSeen.HasValue Then .LastSeen = Nothing : NeedUpdate = True
End If End If
ElseIf If(.LastSeen, Now).AddDays(30) < Now Then ElseIf If(.LastSeen, Now).AddDays(30) < Now And Not UsersListProtected Then
UsersList.RemoveAt(i) UsersList.RemoveAt(i)
MyMainLOG = $"The user [{ .Site}: { .Name}] was not found and was removed from SCrawler." MyMainLOG = $"The user [{ .Site}: { .Name}] was not found and was removed from SCrawler."
NeedUpdate = True NeedUpdate = True
@@ -633,8 +635,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
uu.LastSeen = Now uu.LastSeen = Now
NeedUpdate = True NeedUpdate = True
UsersList(uIndex) = uu UsersList(uIndex) = uu
MyMainLOG = $"The user [{uu.Site}: {uu.Name}] was not found. " & MyMainLOG = $"The user [{uu.Site}: {uu.Name}] was not found. " & errStr(uu.LastSeen.Value)
$"It will be removed from SCrawler on {uu.LastSeen.Value.ToStringDate(DateTimeDefaultProvider)}."
End If End If
End If End If
Return uIndex >= 0 Return uIndex >= 0
@@ -649,7 +650,7 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
__del = False __del = False
If Not .Item(i).FileExists Then If Not .Item(i).FileExists Then
With DirectCast(.Item(i), UserDataBase).User With DirectCast(.Item(i), UserDataBase).User
If Not findWrongUser(.Self) Then If Not findWrongUser(.Self) And Not UsersListProtected Then
__del = True __del = True
MyMainLOG = $"The user [{ .Site}: { .Name}] was not found and was removed from SCrawler." MyMainLOG = $"The user [{ .Site}: { .Name}] was not found and was removed from SCrawler."
End If End If
@@ -875,7 +876,11 @@ Friend Class SettingsCLS : Implements IDownloaderSettings, IDisposable
End Get End Get
End Property End Property
Friend ReadOnly Property MaxUsersJobsCount As XMLValue(Of Integer) Friend ReadOnly Property MaxUsersJobsCount As XMLValue(Of Integer)
Friend ReadOnly Property UserAgent As XMLValue(Of String) Friend ReadOnly Property UserAgent As String
Get
Return HEADER_UserAgent
End Get
End Property
Friend ReadOnly Property ImgurClientID As XMLValue(Of String) Friend ReadOnly Property ImgurClientID As XMLValue(Of String)
#End Region #End Region
#Region "Basis: new version" #Region "Basis: new version"

View File

@@ -64,6 +64,26 @@ Namespace My.Resources
End Set End Set
End Property End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
'''</summary>
Friend Shared ReadOnly Property BlueskyIcon_32() As System.Drawing.Icon
Get
Dim obj As Object = ResourceManager.GetObject("BlueskyIcon_32", resourceCulture)
Return CType(obj,System.Drawing.Icon)
End Get
End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend Shared ReadOnly Property BlueskyPic_32() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("BlueskyPic_32", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
'''<summary> '''<summary>
''' Looks up a localized resource of type System.Drawing.Icon similar to (Icon). ''' Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
'''</summary> '''</summary>
@@ -324,6 +344,16 @@ Namespace My.Resources
End Get End Get
End Property End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
'''</summary>
Friend Shared ReadOnly Property TwitterIconNew_32() As System.Drawing.Icon
Get
Dim obj As Object = ResourceManager.GetObject("TwitterIconNew_32", resourceCulture)
Return CType(obj,System.Drawing.Icon)
End Get
End Property
'''<summary> '''<summary>
''' Looks up a localized resource of type System.Drawing.Icon similar to (Icon). ''' Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
'''</summary> '''</summary>

View File

@@ -118,6 +118,12 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="BlueskyIcon_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Content\Icons\SiteIcons\BlueskyIcon_32.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="BlueskyPic_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Content\Pictures\SitePictures\BlueskyPic_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="FacebookIcon_32" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="FacebookIcon_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Content\Icons\SiteIcons\FacebookIcon_32.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>Content\Icons\SiteIcons\FacebookIcon_32.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
@@ -193,6 +199,9 @@
<data name="TikTokPic_192" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="TikTokPic_192" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Content\Pictures\SitePictures\TikTokPic_192.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>Content\Pictures\SitePictures\TikTokPic_192.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="TwitterIconNew_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Content\Icons\SiteIcons\TwitterIconNew_32.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="TwitterIcon_32" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="TwitterIcon_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Content\Icons\SiteIcons\TwitterIcon_32.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>Content\Icons\SiteIcons\TwitterIcon_32.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>