mirror of
https://github.com/AAndyProgram/SCrawler.git
synced 2026-03-14 15:52:18 +00:00
2026.2.14.0
TokenBatch: add 'MyWorkingDirectory' property API.Instagram: update 'ID' extraction; reduce the number of downloaded stories (GQL) to 5 API.Twitter: get a new username based on the user ID API.XHamster: videos aren't downloading Feed: fix a bug when removing from favorites
This commit is contained in:
21
Changelog.md
21
Changelog.md
@@ -2,13 +2,30 @@
|
|||||||
- [ffmpeg](https://github.com/AAndyProgram/SCrawler/wiki/Settings#ffmpeg)
|
- [ffmpeg](https://github.com/AAndyProgram/SCrawler/wiki/Settings#ffmpeg)
|
||||||
- x64 version - [release](https://github.com/GyanD/codexffmpeg/releases/tag/5.1.2); [zip](https://github.com/GyanD/codexffmpeg/releases/download/5.1.2/ffmpeg-5.1.2-full_build.zip); **version `5.1.2-full_build-www.gyan.dev`**
|
- x64 version - [release](https://github.com/GyanD/codexffmpeg/releases/tag/5.1.2); [zip](https://github.com/GyanD/codexffmpeg/releases/download/5.1.2/ffmpeg-5.1.2-full_build.zip); **version `5.1.2-full_build-www.gyan.dev`**
|
||||||
- x86 version - [release](https://github.com/yt-dlp/FFmpeg-Builds/releases/tag/autobuild-2022-11-30-12-57); [zip](https://github.com/yt-dlp/FFmpeg-Builds/releases/download/autobuild-2022-11-30-12-57/ffmpeg-N-109274-gd7a5f068c2-win32-gpl.zip); **version `N-109457-geeb280f351-20221226`**
|
- x86 version - [release](https://github.com/yt-dlp/FFmpeg-Builds/releases/tag/autobuild-2022-11-30-12-57); [zip](https://github.com/yt-dlp/FFmpeg-Builds/releases/download/autobuild-2022-11-30-12-57/ffmpeg-N-109274-gd7a5f068c2-win32-gpl.zip); **version `N-109457-geeb280f351-20221226`**
|
||||||
- [Gallery-dl](https://github.com/AAndyProgram/SCrawler/wiki/Settings#gallery-dl) - **1.31.4**
|
- [Gallery-dl](https://github.com/AAndyProgram/SCrawler/wiki/Settings#gallery-dl) - **1.31.6**
|
||||||
- [YT-DLP](https://github.com/AAndyProgram/SCrawler/wiki/Settings#yt-dlp) - **2025.12.08**
|
- [YT-DLP](https://github.com/AAndyProgram/SCrawler/wiki/Settings#yt-dlp) - **2026.02.04.233607**
|
||||||
- [Deno](https://github.com/AAndyProgram/SCrawler/wiki/Settings#deno) - latest *(`2.0.0` or higher)*
|
- [Deno](https://github.com/AAndyProgram/SCrawler/wiki/Settings#deno) - latest *(`2.0.0` or higher)*
|
||||||
- [OF-Scraper](https://github.com/AAndyProgram/SCrawler/wiki/Settings#of-scraper) - **3.12.9** ([release](https://github.com/datawhores/OF-Scraper/releases/tag/3.12.9))
|
- [OF-Scraper](https://github.com/AAndyProgram/SCrawler/wiki/Settings#of-scraper) - **3.12.9** ([release](https://github.com/datawhores/OF-Scraper/releases/tag/3.12.9))
|
||||||
|
|
||||||
# 2026
|
# 2026
|
||||||
|
|
||||||
|
## 2026.2.14.0
|
||||||
|
|
||||||
|
*2026-02-14*
|
||||||
|
|
||||||
|
- Added
|
||||||
|
- Sites:
|
||||||
|
- Twitter: get a new username based on the user ID
|
||||||
|
- Minor improvements
|
||||||
|
- Updated
|
||||||
|
- gallery-dl up to version **1.31.6**
|
||||||
|
- yt-dlp up to version **2026.02.04.233607**
|
||||||
|
- Fixed
|
||||||
|
- Sites:
|
||||||
|
- **Instagram: some profiles aren't downloading**
|
||||||
|
- xHamster: videos aren't downloading
|
||||||
|
- Minor bugs
|
||||||
|
|
||||||
## 2026.1.24.0
|
## 2026.1.24.0
|
||||||
|
|
||||||
*2026-01-24*
|
*2026-01-24*
|
||||||
|
|||||||
@@ -13,12 +13,17 @@ Namespace API.Base
|
|||||||
Friend Property TempPostsList As List(Of String)
|
Friend Property TempPostsList As List(Of String)
|
||||||
Protected ReadOnly Token As CancellationToken
|
Protected ReadOnly Token As CancellationToken
|
||||||
Friend Property DebugMode As Boolean = False
|
Friend Property DebugMode As Boolean = False
|
||||||
|
Friend Overridable Property MyWorkingDirectory As SFile = Nothing
|
||||||
Friend Sub New(ByVal _Token As CancellationToken, Optional ByVal _MainProcessName As String = Nothing, Optional ByVal WorkingDir As SFile = Nothing)
|
Friend Sub New(ByVal _Token As CancellationToken, Optional ByVal _MainProcessName As String = Nothing, Optional ByVal WorkingDir As SFile = Nothing)
|
||||||
MyBase.New(True)
|
MyBase.New(True)
|
||||||
Token = _Token
|
Token = _Token
|
||||||
MainProcessName = _MainProcessName
|
MainProcessName = _MainProcessName
|
||||||
If Not WorkingDir.IsEmptyString Then ChangeDirectory(WorkingDir)
|
If Not WorkingDir.IsEmptyString Then ChangeDirectory(WorkingDir)
|
||||||
End Sub
|
End Sub
|
||||||
|
Public Overrides Sub ChangeDirectory(ByVal Directory As SFile)
|
||||||
|
MyBase.ChangeDirectory(Directory)
|
||||||
|
If Not Directory.IsEmptyString Then MyWorkingDirectory = Directory
|
||||||
|
End Sub
|
||||||
Protected Overrides Function Internal_Execute(ByVal Commands As IEnumerable(Of String), ByVal e As ErrorsDescriber) As Boolean
|
Protected Overrides Function Internal_Execute(ByVal Commands As IEnumerable(Of String), ByVal e As ErrorsDescriber) As Boolean
|
||||||
If Not Encoding.HasValue Then Encoding = UnicodeEncoding
|
If Not Encoding.HasValue Then Encoding = UnicodeEncoding
|
||||||
Return MyBase.Internal_Execute(Commands, e)
|
Return MyBase.Internal_Execute(Commands, e)
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ Namespace API.Instagram
|
|||||||
Friend Const PageTokenRegexPatternDefault As String = "\[\],{""token"":""(.*?)""},\d+\]"
|
Friend Const PageTokenRegexPatternDefault As String = "\[\],{""token"":""(.*?)""},\d+\]"
|
||||||
Friend ReadOnly Regex_UserToken_dtsg As RParams = RParams.DMS("DTSGInitialData["":,.\[\]]*?{\s*.token.:\s*""([^""]+)", 1, EDP.ReturnValue)
|
Friend ReadOnly Regex_UserToken_dtsg As RParams = RParams.DMS("DTSGInitialData["":,.\[\]]*?{\s*.token.:\s*""([^""]+)", 1, EDP.ReturnValue)
|
||||||
Friend ReadOnly Regex_UserToken_lsd As RParams = RParams.DMS("LSD["":,.\[\]]*?{\s*.token.:\s*""([^""]+)", 1, EDP.ReturnValue)
|
Friend ReadOnly Regex_UserToken_lsd As RParams = RParams.DMS("LSD["":,.\[\]]*?{\s*.token.:\s*""([^""]+)", 1, EDP.ReturnValue)
|
||||||
|
Friend ReadOnly Regex_ProfileID As RParams = RParams.DMS("profilePage_(\d+)", 1, EDP.ReturnValue)
|
||||||
Friend Sub UpdateResponser(ByVal Source As IResponse, ByRef Destination As Responser, ByVal UpdateWwwClaim As Boolean)
|
Friend Sub UpdateResponser(ByVal Source As IResponse, ByRef Destination As Responser, ByVal UpdateWwwClaim As Boolean)
|
||||||
Const r_wwwClaimName$ = "x-ig-set-www-claim"
|
Const r_wwwClaimName$ = "x-ig-set-www-claim"
|
||||||
Const r_tokenName$ = SiteSettings.Header_CSRF_TOKEN_COOKIE
|
Const r_tokenName$ = SiteSettings.Header_CSRF_TOKEN_COOKIE
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ Namespace API.Instagram
|
|||||||
<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
|
||||||
Friend Overrides Property UserName As String
|
Friend Overrides Property UserName As String
|
||||||
|
<PSetting(Address:=SettingAddress.User, Caption:="Verified profile", ToolTip:="This profile has a verified mark")>
|
||||||
|
Friend Property IsVerifiedProfile As Boolean = False
|
||||||
<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")>
|
||||||
@@ -57,6 +59,8 @@ Namespace API.Instagram
|
|||||||
|
|
||||||
PutImageVideoFolder = .PutImageVideoFolder
|
PutImageVideoFolder = .PutImageVideoFolder
|
||||||
|
|
||||||
|
IsVerifiedProfile = .IsVerifiedProfile
|
||||||
|
|
||||||
ForceUpdateUserName = .ForceUpdateUserName
|
ForceUpdateUserName = .ForceUpdateUserName
|
||||||
ForceUpdateUserInfo = .ForceUpdateUserInfo
|
ForceUpdateUserInfo = .ForceUpdateUserInfo
|
||||||
End With
|
End With
|
||||||
|
|||||||
@@ -148,6 +148,8 @@ Namespace API.Instagram
|
|||||||
#End Region
|
#End Region
|
||||||
<PropertyOption(ControlText:="Use GraphQL to download", IsAuth:=True), PXML, PClonable>
|
<PropertyOption(ControlText:="Use GraphQL to download", IsAuth:=True), PXML, PClonable>
|
||||||
Friend ReadOnly Property USE_GQL As PropertyValue
|
Friend ReadOnly Property USE_GQL As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Use GraphQL to download user data", IsAuth:=True), PXML, PClonable, HiddenControl>
|
||||||
|
Friend ReadOnly Property USE_GQL_UserData As PropertyValue
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Download data"
|
#Region "Download data"
|
||||||
<PropertyOption(ControlText:="Download timeline", Category:=CAT_DOWN), PXML, PClonable>
|
<PropertyOption(ControlText:="Download timeline", Category:=CAT_DOWN), PXML, PClonable>
|
||||||
@@ -165,6 +167,14 @@ Namespace API.Instagram
|
|||||||
<PropertyOption(ControlText:="Download tagged posts", Category:=CAT_DOWN), PXML, PClonable>
|
<PropertyOption(ControlText:="Download tagged posts", Category:=CAT_DOWN), PXML, PClonable>
|
||||||
Friend ReadOnly Property DownloadTagged As PropertyValue
|
Friend ReadOnly Property DownloadTagged As PropertyValue
|
||||||
<PXML> Private ReadOnly Property DownloadTagged_Def As PropertyValue
|
<PXML> Private ReadOnly Property DownloadTagged_Def As PropertyValue
|
||||||
|
<PropertyOption(ControlText:="Number of posts (verified)", ControlToolTip:="The number of posts received per request if the profile has a verified mark", Category:=CAT_DOWN), PXML, PClonable, HiddenControl>
|
||||||
|
Friend ReadOnly Property PostNumberVerified As PropertyValue
|
||||||
|
<Provider(NameOf(PostNumberVerified), FieldsChecker:=True)>
|
||||||
|
Private ReadOnly Property PostNumberVerifiedProvider As IFormatProvider
|
||||||
|
<PropertyOption(ControlText:="Number of posts (unverified)", ControlToolTip:="The number of posts received per request if the profile doesn't have a verified mark", Category:=CAT_DOWN), PXML, PClonable, HiddenControl>
|
||||||
|
Friend ReadOnly Property PostNumberVerifiedNot As PropertyValue
|
||||||
|
<Provider(NameOf(PostNumberVerifiedNot), FieldsChecker:=True)>
|
||||||
|
Private ReadOnly Property PostNumberVerifiedNotProvider As IFormatProvider
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Timers"
|
#Region "Timers"
|
||||||
Friend Const TimersUrgentTip As String = vbCr & "It is highly recommended not to change the default value."
|
Friend Const TimersUrgentTip As String = vbCr & "It is highly recommended not to change the default value."
|
||||||
@@ -485,6 +495,7 @@ Namespace API.Instagram
|
|||||||
HH_IG_WWW_CLAIM_USE_DEFAULT_ALGO = New PropertyValue(True)
|
HH_IG_WWW_CLAIM_USE_DEFAULT_ALGO = New PropertyValue(True)
|
||||||
TokenUpdateIntervalProvider = New TokenRefreshIntervalProvider
|
TokenUpdateIntervalProvider = New TokenRefreshIntervalProvider
|
||||||
USE_GQL = New PropertyValue(False)
|
USE_GQL = New PropertyValue(False)
|
||||||
|
USE_GQL_UserData = New PropertyValue(True)
|
||||||
|
|
||||||
DownloadTimeline = New PropertyValue(True)
|
DownloadTimeline = New PropertyValue(True)
|
||||||
DownloadTimeline_Def = New PropertyValue(DownloadTimeline.Value, GetType(Boolean))
|
DownloadTimeline_Def = New PropertyValue(DownloadTimeline.Value, GetType(Boolean))
|
||||||
@@ -496,6 +507,10 @@ Namespace API.Instagram
|
|||||||
DownloadStoriesUser_Def = New PropertyValue(DownloadStoriesUser.Value, GetType(Boolean))
|
DownloadStoriesUser_Def = New PropertyValue(DownloadStoriesUser.Value, GetType(Boolean))
|
||||||
DownloadTagged = New PropertyValue(False)
|
DownloadTagged = New PropertyValue(False)
|
||||||
DownloadTagged_Def = New PropertyValue(DownloadTagged.Value, GetType(Boolean))
|
DownloadTagged_Def = New PropertyValue(DownloadTagged.Value, GetType(Boolean))
|
||||||
|
PostNumberVerified = New PropertyValue(50)
|
||||||
|
PostNumberVerifiedProvider = New TimersChecker(12)
|
||||||
|
PostNumberVerifiedNot = New PropertyValue(12)
|
||||||
|
PostNumberVerifiedNotProvider = New TimersChecker(12)
|
||||||
|
|
||||||
RequestsWaitTimer_Any = New PropertyValue(1000)
|
RequestsWaitTimer_Any = New PropertyValue(1000)
|
||||||
RequestsWaitTimer_AnyProvider = New TimersChecker(0)
|
RequestsWaitTimer_AnyProvider = New TimersChecker(0)
|
||||||
|
|||||||
@@ -6,12 +6,13 @@
|
|||||||
'
|
'
|
||||||
' 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.Security.Cryptography
|
||||||
Imports System.Threading
|
Imports System.Threading
|
||||||
Imports SCrawler.API.Base
|
|
||||||
Imports PersonalUtilities.Functions.XML
|
|
||||||
Imports PersonalUtilities.Functions.RegularExpressions
|
Imports PersonalUtilities.Functions.RegularExpressions
|
||||||
|
Imports PersonalUtilities.Functions.XML
|
||||||
Imports PersonalUtilities.Tools.Web.Clients
|
Imports PersonalUtilities.Tools.Web.Clients
|
||||||
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||||
|
Imports SCrawler.API.Base
|
||||||
Namespace API.Instagram
|
Namespace API.Instagram
|
||||||
Partial Friend Class UserData
|
Partial Friend Class UserData
|
||||||
#Region "Tokens"
|
#Region "Tokens"
|
||||||
@@ -43,9 +44,9 @@ Namespace API.Instagram
|
|||||||
Private Const GQL_UserStories_DocId As String = "25231722019806941"
|
Private Const GQL_UserStories_DocId As String = "25231722019806941"
|
||||||
Private Const GQL_UserStories_FbFriendlyName As String = "PolarisStoriesV3ReelPageStandaloneQuery"
|
Private Const GQL_UserStories_FbFriendlyName As String = "PolarisStoriesV3ReelPageStandaloneQuery"
|
||||||
|
|
||||||
Private Const GQL_Timeline_DocId As String = "7268577773270422"
|
Private Const GQL_Timeline_DocId As String = "7268577773270422" '"34579740524958711" '"7268577773270422"
|
||||||
Private Const GQL_Timeline_FbFriendlyName As String = "PolarisProfilePostsQuery"
|
Private Const GQL_Timeline_FbFriendlyName As String = "PolarisProfilePostsQuery"
|
||||||
Private Const GQL_Timeline_DocId_Second As String = "7286316061475375"
|
Private Const GQL_Timeline_DocId_Second As String = "7286316061475375" '"33944389991841132" '"7286316061475375"
|
||||||
Private Const GQL_Timeline_FbFriendlyName_Second As String = "PolarisProfilePostsTabContentQuery_connection"
|
Private Const GQL_Timeline_FbFriendlyName_Second As String = "PolarisProfilePostsTabContentQuery_connection"
|
||||||
|
|
||||||
Private Const GQL_Reels_DocId As String = "7191572580905225"
|
Private Const GQL_Reels_DocId As String = "7191572580905225"
|
||||||
@@ -64,33 +65,42 @@ Namespace API.Instagram
|
|||||||
Responser.Headers.Add(GQL_HEADER_FB_FRINDLY_NAME, HeaderValue)
|
Responser.Headers.Add(GQL_HEADER_FB_FRINDLY_NAME, HeaderValue)
|
||||||
Responser.Headers.Add(GQL_HEADER_FB_LSD, Token_lsd)
|
Responser.Headers.Add(GQL_HEADER_FB_LSD, Token_lsd)
|
||||||
End Sub
|
End Sub
|
||||||
<Obsolete("Use 'GET' function: 'GetUserData'", False)>
|
'<Obsolete("Use 'GET' function: 'GetUserData'", False)>
|
||||||
Private Sub GetUserDataGQL(ByVal Token As CancellationToken)
|
Private Function GetUserDataGQL(ByVal Token As CancellationToken) As String
|
||||||
Dim vars$ = String.Format(GQL_URL_PATTERN_VARS, GQL_UserData_DocId, Token_lsd, Token_dtsg_Var, GQL_UserData_FbFriendlyName,
|
Dim vars$ = String.Format(GQL_URL_PATTERN_VARS, GQL_UserData_DocId, Token_lsd, Token_dtsg_Var, GQL_UserData_FbFriendlyName,
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & $"""id"":""{ID}"",""relay_header"":false,""render_surface"":""PROFILE""" & "}"))
|
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & $"""id"":""{ID}"",""relay_header"":false,""render_surface"":""PROFILE""" & "}"))
|
||||||
UpdateRequestNumber()
|
UpdateRequestNumber()
|
||||||
ChangeResponserMode(True)
|
ChangeResponserMode(True)
|
||||||
UpdateHeadersGQL(GQL_UserData_FbFriendlyName)
|
UpdateHeadersGQL(GQL_UserData_FbFriendlyName)
|
||||||
Dim r$ = Responser.GetResponse(GQL_URL, vars)
|
Dim r$ = Responser.GetResponse(GQL_URL, vars)
|
||||||
If Not r.IsEmptyString Then
|
Return r
|
||||||
Using j As EContainer = JsonDocument.Parse(r)
|
'If Not r.IsEmptyString Then
|
||||||
If j.ListExists Then
|
' Using j As EContainer = JsonDocument.Parse(r)
|
||||||
With j({"data", "user"})
|
' If j.ListExists Then
|
||||||
If .ListExists Then
|
' With j({"data", "user"})
|
||||||
UserSiteName = .Value("full_name").IfNullOrEmpty(UserSiteName)
|
' If .ListExists Then
|
||||||
Dim f As New SFile With {.Path = DownloadContentDefault_GetRootDir(), .Name = "ProfilePicture", .Extension = "jpg"}
|
' UserSiteName = .Value("full_name").IfNullOrEmpty(UserSiteName)
|
||||||
Dim pic$ = .Value({"hd_profile_pic_url_info"}, "url").IfNullOrEmpty(.Value("profile_pic_url"))
|
' IsVerifiedProfile = .Value("is_verified").FromXML(Of Boolean)(False)
|
||||||
If Not pic.IsEmptyString Then GetWebFile(pic, f, EDP.ReturnValue)
|
' IsVerifiedProfile_Checked = True
|
||||||
UserDescriptionUpdate(.Value("biography"))
|
' Dim descr$ = .Value("biography")
|
||||||
End If
|
' If If(.Item("bio_links")?.Count, 0) > 0 Then descr.StringAppend(.Item("bio_links").Select(Function(bl) bl.Value("url")).ListToString(vbNewLine), vbNewLine)
|
||||||
End With
|
' Dim eUrl$ = .Value("external_url")
|
||||||
End If
|
' If Not eUrl.IsEmptyString AndAlso (descr.IsEmptyString OrElse Not descr.Contains(eUrl)) Then descr.StringAppendLine(eUrl)
|
||||||
End Using
|
' UserDescriptionUpdate(descr)
|
||||||
End If
|
|
||||||
End Sub
|
' Dim f As New SFile With {.Path = DownloadContentDefault_GetRootDir(), .Name = "ProfilePicture", .Extension = "jpg"}
|
||||||
|
' Dim pic$ = .Value({"hd_profile_pic_url_info"}, "url").IfNullOrEmpty(.Value("profile_pic_url"))
|
||||||
|
' If Not pic.IsEmptyString Then GetWebFile(pic, f, EDP.ReturnValue)
|
||||||
|
' End If
|
||||||
|
' End With
|
||||||
|
' End If
|
||||||
|
' End Using
|
||||||
|
'End If
|
||||||
|
End Function
|
||||||
Private Function GetTimelineGQL(ByVal Cursor As String, ByVal Token As CancellationToken) As String
|
Private Function GetTimelineGQL(ByVal Cursor As String, ByVal Token As CancellationToken) As String
|
||||||
Const none_cursor$ = "none"
|
Const none_cursor$ = "none"
|
||||||
Dim nextCursor$ = String.Empty, hasNextPage$ = String.Empty
|
Dim nextCursor$ = String.Empty
|
||||||
|
Dim hasNextPage As Boolean = False
|
||||||
Dim vars$
|
Dim vars$
|
||||||
|
|
||||||
ThrowAny(Token)
|
ThrowAny(Token)
|
||||||
@@ -98,14 +108,18 @@ Namespace API.Instagram
|
|||||||
ChangeResponserMode(True)
|
ChangeResponserMode(True)
|
||||||
|
|
||||||
If Cursor.IsEmptyString Then
|
If Cursor.IsEmptyString Then
|
||||||
vars = "{""data"":{""count"":50,""include_relationship_info"":true,""latest_besties_reel_media"":true,""latest_reel_media"":true},""username"":""" &
|
vars = "{""data"":{""count"":" & PostNumberPerRequest & ",""include_relationship_info"":true,""latest_besties_reel_media"":true,""latest_reel_media"":true},""username"":""" &
|
||||||
NameTrue & """,""__relay_internal__pv__PolarisShareMenurelayprovider"":false}"
|
NameTrue & """,""__relay_internal__pv__PolarisShareMenurelayprovider"":false}"
|
||||||
|
'vars = "{""data"":{""count"":" & PostNumberPerRequest & ",""include_reel_media_seen_timestamp"":true,""include_relationship_info"":true,""latest_besties_reel_media"":true,""latest_reel_media"":true},""username"":""" &
|
||||||
|
' NameTrue & """,""__relay_internal__pv__PolarisShareMenurelayprovider"":false}"
|
||||||
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Timeline_DocId, Token_lsd, Token_dtsg_Var, GQL_Timeline_FbFriendlyName,
|
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Timeline_DocId, Token_lsd, Token_dtsg_Var, GQL_Timeline_FbFriendlyName,
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly(vars))
|
SymbolsConverter.ASCII.EncodeSymbolsOnly(vars))
|
||||||
UpdateHeadersGQL(GQL_Timeline_FbFriendlyName)
|
UpdateHeadersGQL(GQL_Timeline_FbFriendlyName)
|
||||||
Else
|
Else
|
||||||
vars = "{""after"":""" & Cursor & """,""before"":null,""data"":{""count"":50,""include_relationship_info"":true,""latest_besties_reel_media"":true,""latest_reel_media"":true},""first"":50,""last"":null,""username"":""" &
|
vars = "{""after"":""" & Cursor & """,""before"":null,""data"":{""count"":" & PostNumberPerRequest & ",""include_relationship_info"":true,""latest_besties_reel_media"":true,""latest_reel_media"":true},""first"":" & PostNumberPerRequest & ",""last"":null,""username"":""" &
|
||||||
NameTrue & """,""__relay_internal__pv__PolarisShareMenurelayprovider"":false}"
|
NameTrue & """,""__relay_internal__pv__PolarisShareMenurelayprovider"":false}"
|
||||||
|
'vars = "{""after"":""" & Cursor & """,""before"":null,""data"":{""count"":" & PostNumberPerRequest & ",""include_reel_media_seen_timestamp"":true,""include_relationship_info"":true,""latest_besties_reel_media"":true,""latest_reel_media"":true},""first"":" & PostNumberPerRequest & ",""last"":null,""username"":""" &
|
||||||
|
' NameTrue & """}"
|
||||||
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Timeline_DocId_Second, Token_lsd, Token_dtsg_Var, GQL_Timeline_FbFriendlyName_Second,
|
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Timeline_DocId_Second, Token_lsd, Token_dtsg_Var, GQL_Timeline_FbFriendlyName_Second,
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly(vars))
|
SymbolsConverter.ASCII.EncodeSymbolsOnly(vars))
|
||||||
UpdateHeadersGQL(GQL_Timeline_FbFriendlyName_Second)
|
UpdateHeadersGQL(GQL_Timeline_FbFriendlyName_Second)
|
||||||
@@ -140,7 +154,8 @@ Namespace API.Instagram
|
|||||||
End Function
|
End Function
|
||||||
Private Function GetHighlightsGQL_List() As List(Of String)
|
Private Function GetHighlightsGQL_List() As List(Of String)
|
||||||
|
|
||||||
Dim nextCursor$ = String.Empty, hasNextPage$ = String.Empty
|
Dim nextCursor$ = String.Empty
|
||||||
|
Dim hasNextPage As Boolean = False
|
||||||
Dim i% = -1
|
Dim i% = -1
|
||||||
Dim hList As New List(Of String)
|
Dim hList As New List(Of String)
|
||||||
Dim tmpList As New List(Of String)
|
Dim tmpList As New List(Of String)
|
||||||
@@ -178,7 +193,9 @@ Namespace API.Instagram
|
|||||||
Dim tmpList As New List(Of String)
|
Dim tmpList As New List(Of String)
|
||||||
Dim i% = -1
|
Dim i% = -1
|
||||||
If StoriesList.ListExists Then
|
If StoriesList.ListExists Then
|
||||||
tmpList.AddRange(StoriesList.Take(10))
|
'TODO: 5 Instagram stories
|
||||||
|
'tmpList.AddRange(StoriesList.Take(10))
|
||||||
|
tmpList.AddRange(StoriesList.Take(5))
|
||||||
StoriesList.RemoveRange(0, tmpList.Count)
|
StoriesList.RemoveRange(0, tmpList.Count)
|
||||||
|
|
||||||
Dim vars$ = String.Format(GQL_URL_PATTERN_VARS, GQL_Highlights_DocId_Second, Token_lsd, Token_dtsg_Var, GQL_Highlights_FbFriendlyName_Second,
|
Dim vars$ = String.Format(GQL_URL_PATTERN_VARS, GQL_Highlights_DocId_Second, Token_lsd, Token_dtsg_Var, GQL_Highlights_FbFriendlyName_Second,
|
||||||
@@ -238,11 +255,9 @@ Namespace API.Instagram
|
|||||||
Private Function GetReelsGQL(ByVal Cursor As String) As String
|
Private Function GetReelsGQL(ByVal Cursor As String) As String
|
||||||
GetReelsGQL_SetEnvir = True
|
GetReelsGQL_SetEnvir = True
|
||||||
|
|
||||||
Dim errData$ = String.Empty
|
UpdateTokens(Cursor.IsEmptyString)
|
||||||
If Cursor.IsEmptyString And Not ValidateBaseTokens() Then GetPageTokens()
|
|
||||||
If Cursor.IsEmptyString And Not ValidateBaseTokens(errData) Then ValidateBaseTokens_Error(errData)
|
|
||||||
|
|
||||||
Dim vars$ = """data"":{""include_feed_video"":true,""page_size"":50,""target_user_id"":""" & ID & """}"
|
Dim vars$ = """data"":{""include_feed_video"":true,""page_size"":" & PostNumberPerRequest & ",""target_user_id"":""" & ID & """}"
|
||||||
If Not Cursor.IsEmptyString Then vars = $"""after"":""{Cursor}"",""before"":null,{vars},""first"":4,""last"":null"
|
If Not Cursor.IsEmptyString Then vars = $"""after"":""{Cursor}"",""before"":null,{vars},""first"":4,""last"":null"
|
||||||
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Reels_DocId, Token_lsd, Token_dtsg_Var, GQL_Reels_FbFriendlyName,
|
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Reels_DocId, Token_lsd, Token_dtsg_Var, GQL_Reels_FbFriendlyName,
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & vars & "}"))
|
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & vars & "}"))
|
||||||
@@ -258,10 +273,10 @@ Namespace API.Instagram
|
|||||||
Dim vars$
|
Dim vars$
|
||||||
If Cursor.IsEmptyString Then
|
If Cursor.IsEmptyString Then
|
||||||
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Tagged_DocId, Token_lsd, Token_dtsg_Var, GQL_Tagged_FbFriendlyName,
|
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Tagged_DocId, Token_lsd, Token_dtsg_Var, GQL_Tagged_FbFriendlyName,
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & $"""count"":50,""user_id"":""{ID}""" & "}"))
|
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & $"""count"":{PostNumberPerRequest},""user_id"":""{ID}""" & "}"))
|
||||||
Else
|
Else
|
||||||
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Tagged_DocId, Token_lsd, Token_dtsg_Var, GQL_Tagged_FbFriendlyName,
|
vars = String.Format(GQL_URL_PATTERN_VARS, GQL_Tagged_DocId, Token_lsd, Token_dtsg_Var, GQL_Tagged_FbFriendlyName,
|
||||||
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & $"""after"":""{Cursor}"",""before"":null,""count"":50,""first"":50,""last"":null,""user_id"":""{ID}""" & "}"))
|
SymbolsConverter.ASCII.EncodeSymbolsOnly("{" & $"""after"":""{Cursor}"",""before"":null,""count"":{PostNumberPerRequest},""first"":{PostNumberPerRequest},""last"":null,""user_id"":""{ID}""" & "}"))
|
||||||
End If
|
End If
|
||||||
UpdateRequestNumber()
|
UpdateRequestNumber()
|
||||||
ChangeResponserMode(True)
|
ChangeResponserMode(True)
|
||||||
@@ -270,6 +285,13 @@ Namespace API.Instagram
|
|||||||
End Function
|
End Function
|
||||||
#End Region
|
#End Region
|
||||||
#Region "ValidateBaseTokens"
|
#Region "ValidateBaseTokens"
|
||||||
|
Private Sub UpdateTokens(ByVal process As Boolean)
|
||||||
|
If process Then
|
||||||
|
Dim TokensErrData$ = String.Empty
|
||||||
|
If Not ValidateBaseTokens() Then GetPageTokens()
|
||||||
|
If Not ValidateBaseTokens(TokensErrData) Then ValidateBaseTokens_Error(TokensErrData)
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
Protected Overridable Overloads Function ValidateBaseTokens() As Boolean
|
Protected Overridable Overloads Function ValidateBaseTokens() As Boolean
|
||||||
Return ValidateBaseTokens(Nothing)
|
Return ValidateBaseTokens(Nothing)
|
||||||
End Function
|
End Function
|
||||||
@@ -307,6 +329,10 @@ Namespace API.Instagram
|
|||||||
Try
|
Try
|
||||||
If Not r.IsEmptyString Then
|
If Not r.IsEmptyString Then
|
||||||
ResetBaseTokens()
|
ResetBaseTokens()
|
||||||
|
If ID.IsEmptyString Then
|
||||||
|
Dim __id$ = RegexReplace(r, Regex_ProfileID)
|
||||||
|
If CLng(AConvert(Of Long)(__id, 0, EDP.ReturnValue)) <> 0 Then ID = __id
|
||||||
|
End If
|
||||||
Select Case Attempt
|
Select Case Attempt
|
||||||
Case 0
|
Case 0
|
||||||
Dim rr As RParams = RParams.DM(PageTokenRegexPatternDefault, 0, RegexReturn.List, EDP.ReturnValue)
|
Dim rr As RParams = RParams.DM(PageTokenRegexPatternDefault, 0, RegexReturn.List, EDP.ReturnValue)
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ Namespace API.Instagram
|
|||||||
Private Const Name_TaggedChecked As String = "TaggedChecked"
|
Private Const Name_TaggedChecked As String = "TaggedChecked"
|
||||||
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"
|
||||||
|
Private Const Name_IsVerifiedProfile As String = "IsVerifiedProfile"
|
||||||
|
Private Const Name_IsVerifiedProfile_Checked As String = "IsVerifiedProfile_Checked"
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Declarations"
|
#Region "Declarations"
|
||||||
Friend Structure PostKV : Implements IEContainerProvider
|
Friend Structure PostKV : Implements IEContainerProvider
|
||||||
@@ -115,6 +117,13 @@ Namespace API.Instagram
|
|||||||
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
|
||||||
|
Friend Property IsVerifiedProfile As Boolean = False
|
||||||
|
Friend Property IsVerifiedProfile_Checked As Boolean = False
|
||||||
|
Private ReadOnly Property PostNumberPerRequest As Integer
|
||||||
|
Get
|
||||||
|
With MySiteSettings : Return If(IsVerifiedProfile, .PostNumberVerified, .PostNumberVerifiedNot).Value : End With
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Loader"
|
#Region "Loader"
|
||||||
Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean)
|
Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean)
|
||||||
@@ -136,6 +145,8 @@ Namespace API.Instagram
|
|||||||
TaggedChecked = .Value(Name_TaggedChecked).FromXML(Of Boolean)(False)
|
TaggedChecked = .Value(Name_TaggedChecked).FromXML(Of Boolean)(False)
|
||||||
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)
|
||||||
|
IsVerifiedProfile = .Value(Name_IsVerifiedProfile).FromXML(Of Boolean)(False)
|
||||||
|
IsVerifiedProfile_Checked = .Value(Name_IsVerifiedProfile_Checked).FromXML(Of Boolean)(False)
|
||||||
Else
|
Else
|
||||||
.Add(Name_LastCursor, LastCursor)
|
.Add(Name_LastCursor, LastCursor)
|
||||||
.Add(Name_FirstLoadingDone, FirstLoadingDone.BoolToInteger)
|
.Add(Name_FirstLoadingDone, FirstLoadingDone.BoolToInteger)
|
||||||
@@ -153,6 +164,8 @@ Namespace API.Instagram
|
|||||||
.Add(Name_TaggedChecked, TaggedChecked.BoolToInteger)
|
.Add(Name_TaggedChecked, TaggedChecked.BoolToInteger)
|
||||||
.Add(Name_ForceUpdateUserName, ForceUpdateUserName.BoolToInteger)
|
.Add(Name_ForceUpdateUserName, ForceUpdateUserName.BoolToInteger)
|
||||||
.Add(Name_ForceUpdateUserInfo, ForceUpdateUserInfo.BoolToInteger)
|
.Add(Name_ForceUpdateUserInfo, ForceUpdateUserInfo.BoolToInteger)
|
||||||
|
.Add(Name_IsVerifiedProfile, IsVerifiedProfile.BoolToInteger)
|
||||||
|
.Add(Name_IsVerifiedProfile_Checked, IsVerifiedProfile_Checked.BoolToInteger)
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
End Sub
|
End Sub
|
||||||
@@ -179,6 +192,9 @@ Namespace API.Instagram
|
|||||||
|
|
||||||
PutImageVideoFolder = .PutImageVideoFolder
|
PutImageVideoFolder = .PutImageVideoFolder
|
||||||
|
|
||||||
|
IsVerifiedProfile = .IsVerifiedProfile
|
||||||
|
If IsVerifiedProfile Then IsVerifiedProfile_Checked = True
|
||||||
|
|
||||||
ForceUpdateUserName = .ForceUpdateUserName
|
ForceUpdateUserName = .ForceUpdateUserName
|
||||||
ForceUpdateUserInfo = .ForceUpdateUserInfo
|
ForceUpdateUserInfo = .ForceUpdateUserInfo
|
||||||
End With
|
End With
|
||||||
@@ -663,6 +679,7 @@ Namespace API.Instagram
|
|||||||
Dim StoriesList As List(Of String) = Nothing
|
Dim StoriesList As List(Of String) = Nothing
|
||||||
Dim StoriesRequested As Boolean = False
|
Dim StoriesRequested As Boolean = False
|
||||||
Dim dValue% = 1
|
Dim dValue% = 1
|
||||||
|
Dim __idIsEmpty As Boolean = ID.IsEmptyString
|
||||||
LastCursor = Cursor
|
LastCursor = Cursor
|
||||||
Try
|
Try
|
||||||
Do While dValue = 1
|
Do While dValue = 1
|
||||||
@@ -676,7 +693,6 @@ Namespace API.Instagram
|
|||||||
Dim HasNextPage As Boolean = False
|
Dim HasNextPage As Boolean = False
|
||||||
Dim EndCursor$ = String.Empty
|
Dim EndCursor$ = String.Empty
|
||||||
Dim PostID$ = String.Empty, PostDate$ = String.Empty, SpecFolder$ = String.Empty
|
Dim PostID$ = String.Empty, PostDate$ = String.Empty, SpecFolder$ = String.Empty
|
||||||
Dim TokensErrData$ = String.Empty
|
|
||||||
Dim PostIDKV As PostKV
|
Dim PostIDKV As PostKV
|
||||||
Dim ENode() As Object = Nothing
|
Dim ENode() As Object = Nothing
|
||||||
Dim processGetResponse As Boolean = True
|
Dim processGetResponse As Boolean = True
|
||||||
@@ -684,14 +700,11 @@ Namespace API.Instagram
|
|||||||
|
|
||||||
'Check environment
|
'Check environment
|
||||||
If Not IsSavedPosts Then
|
If Not IsSavedPosts Then
|
||||||
If ID.IsEmptyString Then GetUserData()
|
If _UseGQL And Cursor.IsEmptyString And Not Section = Sections.SavedPosts Then UpdateTokens(True)
|
||||||
|
If ID.IsEmptyString Or __idIsEmpty Or Not IsVerifiedProfile_Checked Then GetUserData(Token)
|
||||||
If ID.IsEmptyString Then UserExists = False : _ForceSaveUserInfoOnException = True : Throw New Plugin.ExitException("can't get user ID")
|
If ID.IsEmptyString Then UserExists = False : _ForceSaveUserInfoOnException = True : Throw New Plugin.ExitException("can't get user ID")
|
||||||
If _UseGQL And Cursor.IsEmptyString And Not Section = Sections.SavedPosts Then
|
|
||||||
If Not ValidateBaseTokens() Then GetPageTokens()
|
|
||||||
If Not ValidateBaseTokens(TokensErrData) Then ValidateBaseTokens_Error(TokensErrData)
|
|
||||||
End If
|
|
||||||
If ForceUpdateUserName Then GetUserNameById()
|
If ForceUpdateUserName Then GetUserNameById()
|
||||||
If ForceUpdateUserInfo Then GetUserData()
|
If ForceUpdateUserInfo Then GetUserData(Token)
|
||||||
End If
|
End If
|
||||||
|
|
||||||
'Create query
|
'Create query
|
||||||
@@ -703,7 +716,7 @@ Namespace API.Instagram
|
|||||||
MySiteSettings.TooManyRequests(False)
|
MySiteSettings.TooManyRequests(False)
|
||||||
GoTo NextPageBlock
|
GoTo NextPageBlock
|
||||||
Else
|
Else
|
||||||
URL = $"https://www.instagram.com/api/v1/feed/user/{NameTrue}/username/?count=50" &
|
URL = $"https://www.instagram.com/api/v1/feed/user/{NameTrue}/username/?count={PostNumberPerRequest}" &
|
||||||
If(Cursor.IsEmptyString, String.Empty, $"&max_id={Cursor}")
|
If(Cursor.IsEmptyString, String.Empty, $"&max_id={Cursor}")
|
||||||
ENode = Nothing
|
ENode = Nothing
|
||||||
End If
|
End If
|
||||||
@@ -726,7 +739,7 @@ Namespace API.Instagram
|
|||||||
ENode = {"data", "xdt_api__v1__usertags__user_id__feed_connection"}
|
ENode = {"data", "xdt_api__v1__usertags__user_id__feed_connection"}
|
||||||
processGetResponse = False
|
processGetResponse = False
|
||||||
Else
|
Else
|
||||||
Dim vars$ = "{""id"":" & ID & ",""first"":50,""after"":""" & Cursor & """}"
|
Dim vars$ = "{""id"":" & ID & $",""first"":{PostNumberPerRequest},""after"":""" & Cursor & """}"
|
||||||
vars = SymbolsConverter.ASCII.EncodeSymbolsOnly(vars)
|
vars = SymbolsConverter.ASCII.EncodeSymbolsOnly(vars)
|
||||||
URL = $"https://www.instagram.com/graphql/query/?doc_id=17946422347485809&variables={vars}"
|
URL = $"https://www.instagram.com/graphql/query/?doc_id=17946422347485809&variables={vars}"
|
||||||
ENode = {"data", "user", "edge_user_to_photos_of_you"}
|
ENode = {"data", "user", "edge_user_to_photos_of_you"}
|
||||||
@@ -1241,25 +1254,37 @@ NextPageBlock:
|
|||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "GetUserId, GetUserName"
|
#Region "GetUserId, GetUserName"
|
||||||
Private Sub GetUserData()
|
Private Sub GetUserData(ByVal Token As CancellationToken)
|
||||||
Dim __idFound As Boolean = False
|
Dim __idFound As Boolean = False
|
||||||
If ForceUpdateUserInfo Then ForceUpdateUserInfo = False : _ForceSaveUserInfo = True
|
If ForceUpdateUserInfo Then ForceUpdateUserInfo = False : _ForceSaveUserInfo = True
|
||||||
Try
|
Try
|
||||||
|
Dim r$
|
||||||
|
Dim ____dataGql As Boolean = _UseGQL Or CBool(MySiteSettings.USE_GQL_UserData.Value)
|
||||||
|
If ____dataGql Then
|
||||||
|
UpdateTokens(True)
|
||||||
|
r = GetUserDataGQL(Token)
|
||||||
|
If Not _UseGQL Then ChangeResponserMode(_UseGQL)
|
||||||
|
Else
|
||||||
ChangeResponserMode(False)
|
ChangeResponserMode(False)
|
||||||
UpdateRequestNumber()
|
UpdateRequestNumber()
|
||||||
Dim r$ = Responser.GetResponse($"https://i.instagram.com/api/v1/users/web_profile_info/?username={NameTrue}")
|
r = Responser.GetResponse($"https://i.instagram.com/api/v1/users/web_profile_info/?username={NameTrue}")
|
||||||
|
End If
|
||||||
|
|
||||||
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", "user"}) Then
|
If Not j Is Nothing AndAlso j.Contains({"data", "user"}) Then
|
||||||
With j({"data", "user"})
|
With j({"data", "user"})
|
||||||
ID = .Value("id")
|
If Not ____dataGql Or ID.IsEmptyString Then ID = .Value("id")
|
||||||
__idFound = True
|
__idFound = True
|
||||||
UserSiteNameUpdate(.Value("full_name"))
|
UserSiteNameUpdate(.Value("full_name"))
|
||||||
|
IsVerifiedProfile = .Value("is_verified").FromXML(Of Boolean)(False)
|
||||||
|
IsVerifiedProfile_Checked = True
|
||||||
Dim descr$ = .Value("biography")
|
Dim descr$ = .Value("biography")
|
||||||
If If(.Item("bio_links")?.Count, 0) > 0 Then descr.StringAppend(.Item("bio_links").Select(Function(bl) bl.Value("url")).ListToString(vbNewLine), vbNewLine)
|
If If(.Item("bio_links")?.Count, 0) > 0 Then descr.StringAppend(.Item("bio_links").Select(Function(bl) bl.Value("url")).ListToString(vbNewLine), vbNewLine)
|
||||||
Dim eUrl$ = .Value("external_url")
|
Dim eUrl$ = .Value("external_url")
|
||||||
If Not eUrl.IsEmptyString AndAlso (descr.IsEmptyString OrElse Not descr.Contains(eUrl)) Then descr.StringAppendLine(eUrl)
|
If Not eUrl.IsEmptyString AndAlso (descr.IsEmptyString OrElse Not descr.Contains(eUrl)) Then descr.StringAppendLine(eUrl)
|
||||||
UserDescriptionUpdate(descr)
|
UserDescriptionUpdate(descr)
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@@ -297,10 +297,17 @@ Namespace API.Twitter
|
|||||||
Private Const DEBUG_PROFILE As Boolean = False
|
Private Const DEBUG_PROFILE As Boolean = False
|
||||||
Private Const DEBUG_LEAVE_CACHE As Boolean = False
|
Private Const DEBUG_LEAVE_CACHE As Boolean = False
|
||||||
Private JsonNullErr As Boolean = False
|
Private JsonNullErr As Boolean = False
|
||||||
|
Private ____UserExists As Boolean = True
|
||||||
|
Private NotUserExistsAttempts As Integer = 0
|
||||||
|
Friend Overrides Sub DownloadData(ByVal Token As CancellationToken)
|
||||||
|
____UserExists = UserExists
|
||||||
|
MyBase.DownloadData(Token)
|
||||||
|
End Sub
|
||||||
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
|
||||||
Try
|
Try
|
||||||
GDL_REQUESTS_COUNT = 0
|
GDL_REQUESTS_COUNT = 0
|
||||||
JsonNullErr = False
|
JsonNullErr = False
|
||||||
|
NotUserExistsAttempts = 0
|
||||||
If MySettings.LIMIT_ABORT Then
|
If MySettings.LIMIT_ABORT Then
|
||||||
Throw New TwitterLimitException(Me)
|
Throw New TwitterLimitException(Me)
|
||||||
Else
|
Else
|
||||||
@@ -317,6 +324,14 @@ Namespace API.Twitter
|
|||||||
End If
|
End If
|
||||||
LikesPosts.Clear()
|
LikesPosts.Clear()
|
||||||
If _ContentList.Count > 0 Then _DataNames.ListAddList(_ContentList.Select(Function(c) c.File.File), LAP.ClearBeforeAdd, LAP.NotContainsOnly)
|
If _ContentList.Count > 0 Then _DataNames.ListAddList(_ContentList.Select(Function(c) c.File.File), LAP.ClearBeforeAdd, LAP.NotContainsOnly)
|
||||||
|
If Not ____UserExists Then
|
||||||
|
For i% = 0 To 1
|
||||||
|
NotUserExistsAttempts += 1
|
||||||
|
DownloadData_Timeline(Token)
|
||||||
|
If UserExists Then ____UserExists = True : Exit For
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
If Not UserExists Then Exit Sub
|
||||||
DownloadData_Timeline(Token)
|
DownloadData_Timeline(Token)
|
||||||
If _TempMediaList.Count = 0 And LikesPosts.Count = 0 And JsonNullErr Then Throw New Plugin.ExitException("No deserialized data found")
|
If _TempMediaList.Count = 0 And LikesPosts.Count = 0 And JsonNullErr Then Throw New Plugin.ExitException("No deserialized data found")
|
||||||
LoadSavePostsKV(False)
|
LoadSavePostsKV(False)
|
||||||
@@ -366,6 +381,7 @@ Namespace API.Twitter
|
|||||||
Dim j As EContainer, rootNode As EContainer, optionalNode As EContainer, workingNode As EContainer, tmpNode As EContainer, nn As EContainer = Nothing
|
Dim j As EContainer, rootNode As EContainer, optionalNode As EContainer, workingNode As EContainer, tmpNode As EContainer, nn As EContainer = Nothing
|
||||||
Dim multiMode As Boolean = IsMultiMode
|
Dim multiMode As Boolean = IsMultiMode
|
||||||
Dim currentModel As DownloadModels = DownloadModels.Undefined
|
Dim currentModel As DownloadModels = DownloadModels.Undefined
|
||||||
|
Dim onlyUpdateUser As Boolean = Not ____UserExists
|
||||||
|
|
||||||
Dim __parseContainer As Func(Of EContainer, Boolean) =
|
Dim __parseContainer As Func(Of EContainer, Boolean) =
|
||||||
Function(ByVal ee As EContainer) As Boolean
|
Function(ByVal ee As EContainer) As Boolean
|
||||||
@@ -478,6 +494,7 @@ Namespace API.Twitter
|
|||||||
End If
|
End If
|
||||||
'parse files
|
'parse files
|
||||||
For i = 0 To timelineFiles.Count - 1
|
For i = 0 To timelineFiles.Count - 1
|
||||||
|
If userInfoParsed And onlyUpdateUser Then Exit Sub
|
||||||
j = JsonDocument.Parse(timelineFiles(i).GetText, jsonArgs)
|
j = JsonDocument.Parse(timelineFiles(i).GetText, jsonArgs)
|
||||||
If jsonArgs.State = WebDocumentEventArgs.States.Error Then
|
If jsonArgs.State = WebDocumentEventArgs.States.Error Then
|
||||||
jsonArgs.Reset(Token)
|
jsonArgs.Reset(Token)
|
||||||
@@ -530,6 +547,14 @@ Namespace API.Twitter
|
|||||||
Dim tScreenName$ = .Value({"core"}, "screen_name")
|
Dim tScreenName$ = .Value({"core"}, "screen_name")
|
||||||
With .Item({"legacy"})
|
With .Item({"legacy"})
|
||||||
If .ListExists Then
|
If .ListExists Then
|
||||||
|
If onlyUpdateUser Then
|
||||||
|
If Not NameTrue = tScreenName Or 1 = 1 Then
|
||||||
|
Dim uStr$ = $"username changed from '{NameTrue}' to '{tScreenName}'"
|
||||||
|
LogError(Nothing, uStr)
|
||||||
|
UserDescriptionUpdate(uStr, True, True, True)
|
||||||
|
End If
|
||||||
|
NameTrue = tScreenName
|
||||||
|
End If
|
||||||
If .Value("screen_name").IfNullOrEmpty(tScreenName).StringToLower = NameTrue.ToLower Then
|
If .Value("screen_name").IfNullOrEmpty(tScreenName).StringToLower = NameTrue.ToLower Then
|
||||||
UserSiteNameUpdate(.Value("name"))
|
UserSiteNameUpdate(.Value("name"))
|
||||||
UserDescriptionUpdate(.Value("description"))
|
UserDescriptionUpdate(.Value("description"))
|
||||||
@@ -846,6 +871,23 @@ nextpIndx:
|
|||||||
Private Class TwitterGDL : Inherits GDL.GDLBatch
|
Private Class TwitterGDL : Inherits GDL.GDLBatch
|
||||||
Private ReadOnly KillOnLimit As Boolean
|
Private ReadOnly KillOnLimit As Boolean
|
||||||
Friend LimitReached As Boolean = False
|
Friend LimitReached As Boolean = False
|
||||||
|
Private _GetOnlyUserInfo As Boolean = False
|
||||||
|
Friend Overrides Property MyWorkingDirectory As SFile
|
||||||
|
Get
|
||||||
|
Return If(MyBase.MyWorkingDirectory.IsEmptyString, If(FileExchanger?.RootDirectory, MyBase.MyWorkingDirectory), MyBase.MyWorkingDirectory)
|
||||||
|
End Get
|
||||||
|
Set(ByVal dir As SFile)
|
||||||
|
MyBase.MyWorkingDirectory = dir
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
|
Friend Property GetOnlyUserInfo As Boolean
|
||||||
|
Get
|
||||||
|
Return _GetOnlyUserInfo And Not MyWorkingDirectory.IsEmptyString
|
||||||
|
End Get
|
||||||
|
Set(ByVal __GetOnlyUserInfo As Boolean)
|
||||||
|
_GetOnlyUserInfo = __GetOnlyUserInfo
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
Friend Sub New(ByVal Dir As SFile, ByVal _Token As CancellationToken, ByVal _KillOnLimit As Boolean)
|
Friend Sub New(ByVal Dir As SFile, ByVal _Token As CancellationToken, ByVal _KillOnLimit As Boolean)
|
||||||
MyBase.New(_Token,, Dir)
|
MyBase.New(_Token,, Dir)
|
||||||
KillOnLimit = _KillOnLimit
|
KillOnLimit = _KillOnLimit
|
||||||
@@ -855,11 +897,15 @@ nextpIndx:
|
|||||||
End Function
|
End Function
|
||||||
Private Function IdExists(ByVal Value As String) As Boolean
|
Private Function IdExists(ByVal Value As String) As Boolean
|
||||||
Try
|
Try
|
||||||
|
If GetOnlyUserInfo Then
|
||||||
|
Return CheckForData()
|
||||||
|
Else
|
||||||
Value = Value.StringTrim
|
Value = Value.StringTrim
|
||||||
If Not Value.IsEmptyString AndAlso (Value.StartsWith("*") Or Value.StartsWith(".\gallery-dl\")) Then
|
If Not Value.IsEmptyString AndAlso (Value.StartsWith("*") Or Value.StartsWith(".\gallery-dl\")) Then
|
||||||
Dim id$ = Value.Split("\").Last.Split(".").First.Split("_").First
|
Dim id$ = Value.Split("\").Last.Split(".").First.Split("_").First
|
||||||
If Not id.IsEmptyString Then Return TempPostsList.Contains(id)
|
If Not id.IsEmptyString Then Return TempPostsList.Contains(id)
|
||||||
End If
|
End If
|
||||||
|
End If
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
End Try
|
End Try
|
||||||
Return False
|
Return False
|
||||||
@@ -867,8 +913,14 @@ nextpIndx:
|
|||||||
Protected Overrides Async Sub ErrorDataReceiver(ByVal Sender As Object, ByVal e As DataReceivedEventArgs)
|
Protected Overrides Async Sub ErrorDataReceiver(ByVal Sender As Object, ByVal e As DataReceivedEventArgs)
|
||||||
Await Task.Run(Sub() CheckForLimit(e.Data))
|
Await Task.Run(Sub() CheckForLimit(e.Data))
|
||||||
End Sub
|
End Sub
|
||||||
|
Private Function CheckForData()
|
||||||
|
If GetOnlyUserInfo Then
|
||||||
|
If SFile.GetFiles(MyWorkingDirectory, "*.txt",, EDP.ReturnValue).Count > 2 Then Return True
|
||||||
|
End If
|
||||||
|
Return False
|
||||||
|
End Function
|
||||||
Private Sub CheckForLimit(ByVal Value As String)
|
Private Sub CheckForLimit(ByVal Value As String)
|
||||||
If Token.IsCancellationRequested Or (KillOnLimit AndAlso Not ProcessKilled AndAlso
|
If CheckForData() Or Token.IsCancellationRequested Or (KillOnLimit AndAlso Not ProcessKilled AndAlso
|
||||||
Not Value.IsEmptyString AndAlso (Value.ToLower.Contains("for rate limit reset") OrElse
|
Not Value.IsEmptyString AndAlso (Value.ToLower.Contains("for rate limit reset") OrElse
|
||||||
Not CStr(RegexReplace(Value, GdlLimitRegEx)).IsEmptyString)) Then
|
Not CStr(RegexReplace(Value, GdlLimitRegEx)).IsEmptyString)) Then
|
||||||
LimitReached = True
|
LimitReached = True
|
||||||
@@ -1017,11 +1069,12 @@ nextpIndx:
|
|||||||
.AutoClear = True,
|
.AutoClear = True,
|
||||||
.AutoReset = True,
|
.AutoReset = True,
|
||||||
.CommandPermanent = $"chcp {BatchExecutor.UnicodeEncoding}",
|
.CommandPermanent = $"chcp {BatchExecutor.UnicodeEncoding}",
|
||||||
.FileExchanger = confCache
|
.FileExchanger = confCache,
|
||||||
|
.GetOnlyUserInfo = NotUserExistsAttempts > 0
|
||||||
}
|
}
|
||||||
tgdl.FileExchanger.DeleteCacheOnDispose = False
|
tgdl.FileExchanger.DeleteCacheOnDispose = False
|
||||||
tgdl.FileExchanger.DeleteRootOnDispose = False
|
tgdl.FileExchanger.DeleteRootOnDispose = False
|
||||||
For i As Byte = 0 To IIf(IsCommunity, 0, 3)
|
For i As Byte = 0 To IIf(IsCommunity Or NotUserExistsAttempts > 0, 0, 3)
|
||||||
dir = rootDir.NewPath
|
dir = rootDir.NewPath
|
||||||
dir.Exists(SFO.Path, True, EDP.ThrowException)
|
dir.Exists(SFO.Path, True, EDP.ThrowException)
|
||||||
outList.Add(dir)
|
outList.Add(dir)
|
||||||
@@ -1032,6 +1085,20 @@ nextpIndx:
|
|||||||
Else
|
Else
|
||||||
command &= GdlGetIdFilterString()
|
command &= GdlGetIdFilterString()
|
||||||
End If
|
End If
|
||||||
|
If NotUserExistsAttempts > 0 Then
|
||||||
|
Select Case NotUserExistsAttempts
|
||||||
|
Case 1 : command &= $"{urlPrePattern}{NameTrue}/media" : currentModel = DownloadModels.Media : process = True
|
||||||
|
Case 2
|
||||||
|
If ID.IsEmptyString Then
|
||||||
|
process = False
|
||||||
|
Else
|
||||||
|
command &= $"https://twitter.com/intent/user?user_id={ID}"
|
||||||
|
currentModel = DownloadModels.Media
|
||||||
|
process = True
|
||||||
|
End If
|
||||||
|
Case Else : process = False
|
||||||
|
End Select
|
||||||
|
Else
|
||||||
Select Case i
|
Select Case i
|
||||||
Case 0 : command &= $"{urlPrePattern}{NameTrue}/media" : currentModel = DownloadModels.Media : process = dm.Contains(currentModel) Or IsCommunity
|
Case 0 : command &= $"{urlPrePattern}{NameTrue}/media" : currentModel = DownloadModels.Media : process = dm.Contains(currentModel) Or IsCommunity
|
||||||
Case 1 : command &= $"{urlPrePattern}{NameTrue}" : currentModel = DownloadModels.Profile : process = dm.Contains(currentModel)
|
Case 1 : command &= $"{urlPrePattern}{NameTrue}" : currentModel = DownloadModels.Profile : process = dm.Contains(currentModel)
|
||||||
@@ -1039,6 +1106,7 @@ nextpIndx:
|
|||||||
Case 3 : command &= $"{urlPrePattern}{NameTrue}/likes" : currentModel = DownloadModels.Likes : process = dm.Contains(currentModel)
|
Case 3 : command &= $"{urlPrePattern}{NameTrue}/likes" : currentModel = DownloadModels.Likes : process = dm.Contains(currentModel)
|
||||||
Case Else : process = False
|
Case Else : process = False
|
||||||
End Select
|
End Select
|
||||||
|
End If
|
||||||
'#If DEBUG Then
|
'#If DEBUG Then
|
||||||
'Debug.WriteLine(command)
|
'Debug.WriteLine(command)
|
||||||
'#End If
|
'#End If
|
||||||
|
|||||||
@@ -744,12 +744,13 @@ Namespace API.Xhamster
|
|||||||
If IsSingleObjectDownload Then
|
If IsSingleObjectDownload Then
|
||||||
cc = Settings.Cache
|
cc = Settings.Cache
|
||||||
Else
|
Else
|
||||||
If MyCache Is Nothing Then MyCache = CreateCache() : MyCache.Validate()
|
If MyCache Is Nothing Then MyCache = CreateCache()
|
||||||
cc = MyCache
|
cc = MyCache
|
||||||
End If
|
End If
|
||||||
|
cc.Validate()
|
||||||
Dim path As SFile = cc.NewPath
|
Dim path As SFile = cc.NewPath
|
||||||
Dim c$ = If(MySettings.CookiesNetscapeFile.Exists, $" --no-cookies-from-browser --cookies ""{MySettings.CookiesNetscapeFile}""", String.Empty)
|
Dim c$ = If(MySettings.CookiesNetscapeFile.Exists, $" --no-cookies-from-browser --cookies ""{MySettings.CookiesNetscapeFile}""", String.Empty)
|
||||||
Dim cmd$ = $"{Settings.YtdlpFile} --write-info-json --skip-download{c} {URL} -o ""{path.PathWithSeparator}file"""
|
Dim cmd$ = $"""{Settings.YtdlpFile}"" --write-info-json --skip-download{c} {URL} -o ""{path.PathWithSeparator}file"""
|
||||||
path.Exists()
|
path.Exists()
|
||||||
Using ytdlp As New YTDLP.YTDLPBatch(TokenPersonal,, path) : ytdlp.Encoding = Settings.CMDEncoding : ytdlp.Execute(cmd) : End Using
|
Using ytdlp As New YTDLP.YTDLPBatch(TokenPersonal,, path) : ytdlp.Encoding = Settings.CMDEncoding : ytdlp.Execute(cmd) : End Using
|
||||||
Return SFile.GetFiles(path, "*.json",, EDP.ReturnValue).FirstOrDefault
|
Return SFile.GetFiles(path, "*.json",, EDP.ReturnValue).FirstOrDefault
|
||||||
@@ -794,7 +795,7 @@ Namespace API.Xhamster
|
|||||||
Private Function YTDLPDownload(ByVal Media As UserMedia, ByVal DestinationFile As SFile, ByVal Token As CancellationToken) As SFile
|
Private Function YTDLPDownload(ByVal Media As UserMedia, ByVal DestinationFile As SFile, ByVal Token As CancellationToken) As SFile
|
||||||
DestinationFile.Extension = "mp4"
|
DestinationFile.Extension = "mp4"
|
||||||
Dim c$ = If(MySettings.CookiesNetscapeFile.Exists, $" --no-cookies-from-browser --cookies ""{MySettings.CookiesNetscapeFile}""", String.Empty)
|
Dim c$ = If(MySettings.CookiesNetscapeFile.Exists, $" --no-cookies-from-browser --cookies ""{MySettings.CookiesNetscapeFile}""", String.Empty)
|
||||||
Dim cmd$ = $"{Settings.YtdlpFile} --format {DirectCast(Media.Object, XMMediaInfo).FormatID}{c} {Media.URL_BASE} -o ""{DestinationFile}"""
|
Dim cmd$ = $"""{Settings.YtdlpFile}"" --format {DirectCast(Media.Object, XMMediaInfo).FormatID}{c} {Media.URL_BASE} -o ""{DestinationFile}"""
|
||||||
Using ytdlp As New YTDLP.YTDLPBatch(TokenPersonal,, DestinationFile) : ytdlp.Encoding = Settings.CMDEncoding : ytdlp.Execute(cmd) : End Using
|
Using ytdlp As New YTDLP.YTDLPBatch(TokenPersonal,, DestinationFile) : ytdlp.Encoding = Settings.CMDEncoding : ytdlp.Execute(cmd) : End Using
|
||||||
Return DestinationFile
|
Return DestinationFile
|
||||||
End Function
|
End Function
|
||||||
|
|||||||
@@ -99,15 +99,15 @@ Namespace DownloadObjects
|
|||||||
End Sub
|
End Sub
|
||||||
Private Sub FeedRemoveCheckedMedia(ByVal MediaList As IEnumerable(Of UserMediaD), Optional ByVal OverriddenNames As List(Of String) = Nothing,
|
Private Sub FeedRemoveCheckedMedia(ByVal MediaList As IEnumerable(Of UserMediaD), Optional ByVal OverriddenNames As List(Of String) = Nothing,
|
||||||
Optional ByVal RemoveChecked As Boolean = True, Optional ByVal ExcludingNames As IEnumerable(Of String) = Nothing,
|
Optional ByVal RemoveChecked As Boolean = True, Optional ByVal ExcludingNames As IEnumerable(Of String) = Nothing,
|
||||||
Optional ByVal RemoveFromDataListOnly As Boolean = False)
|
Optional ByVal IsAddAndRemove As Boolean = False)
|
||||||
Try
|
Try
|
||||||
If FeedMode = FeedModes.Special Then
|
If FeedMode = FeedModes.Saved Then Exit Sub
|
||||||
If LoadedFeedNames.Count > 0 Then
|
|
||||||
Dim dataRemoved As Boolean = False
|
Dim dataRemoved As Boolean = False
|
||||||
If OverriddenNames.ListExists And Not LoadedFeedNames.ListContains(OverriddenNames) Then Exit Sub
|
If FeedMode = FeedModes.Special And OverriddenNames.ListExists And Not LoadedFeedNames.ListContains(OverriddenNames) Then Exit Sub
|
||||||
If Not RemoveFromDataListOnly Then
|
|
||||||
Dim eNames As IEnumerable(Of String) = If(ExcludingNames, New String() {})
|
Dim eNames As IEnumerable(Of String) = If(ExcludingNames, New String() {})
|
||||||
With If(OverriddenNames, LoadedFeedNames)
|
With If(OverriddenNames, LoadedFeedNames)
|
||||||
|
If FeedMode = FeedModes.Special And .ListExists Then
|
||||||
.ForEach(Sub(ByVal feedName As String)
|
.ForEach(Sub(ByVal feedName As String)
|
||||||
If Not eNames.Contains(feedName) Then
|
If Not eNames.Contains(feedName) Then
|
||||||
Dim indx% = Settings.Feeds.IndexOf(feedName)
|
Dim indx% = Settings.Feeds.IndexOf(feedName)
|
||||||
@@ -116,25 +116,33 @@ Namespace DownloadObjects
|
|||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End Sub)
|
End Sub)
|
||||||
End With
|
ElseIf FeedMode = FeedModes.Current And Not OverriddenNames.ListExists And IsAddAndRemove Then
|
||||||
|
dataRemoved = Downloader.Files.ListDisposeRemove(MediaList) > 0
|
||||||
|
'Downloader.FilesSave()
|
||||||
|
Else
|
||||||
|
Exit Sub
|
||||||
End If
|
End If
|
||||||
If RemoveFromDataListOnly Then
|
End With
|
||||||
RefillSpecialFeedsData()
|
|
||||||
ElseIf dataRemoved Then
|
If dataRemoved Then DataList.ListDisposeRemove(MediaList)
|
||||||
DataList.ListDisposeRemove(MediaList)
|
|
||||||
If RemoveChecked Then
|
Select Case FeedMode
|
||||||
|
Case FeedModes.Special
|
||||||
|
If RemoveChecked And IsAddAndRemove Then
|
||||||
If RemoveCheckedMedia(False) Then RefillAfterDelete()
|
If RemoveCheckedMedia(False) Then RefillAfterDelete()
|
||||||
Else
|
Else
|
||||||
RefillSpecialFeedsData()
|
RefillSpecialFeedsData()
|
||||||
End If
|
End If
|
||||||
End If
|
Case FeedModes.Current
|
||||||
End If
|
If dataRemoved Then
|
||||||
ElseIf FeedMode = FeedModes.Current Then
|
If RemoveChecked Then
|
||||||
If OverriddenNames Is Nothing AndAlso Downloader.Files.ListDisposeRemove(MediaList) > 0 AndAlso RemoveCheckedMedia(False) Then
|
RemoveCheckedMedia(False)
|
||||||
DataList.ListDisposeRemove(MediaList)
|
|
||||||
RefillAfterDelete()
|
RefillAfterDelete()
|
||||||
|
Else
|
||||||
|
RefillList()
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
End Select
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[DownloadFeedForm.FeedRemoveCheckedMedia]")
|
ErrorsDescriber.Execute(EDP.SendToLog, ex, "[DownloadFeedForm.FeedRemoveCheckedMedia]")
|
||||||
End Try
|
End Try
|
||||||
@@ -333,7 +341,7 @@ Namespace DownloadObjects
|
|||||||
Dim c As IEnumerable(Of UserMediaD) = GetCheckedMedia()
|
Dim c As IEnumerable(Of UserMediaD) = GetCheckedMedia()
|
||||||
If c.ListExists Then
|
If c.ListExists Then
|
||||||
f.Add(c)
|
f.Add(c)
|
||||||
FeedRemoveCheckedMedia(c,,, {f.Name})
|
FeedRemoveCheckedMedia(c,,, {f.Name}, True)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
@@ -352,7 +360,7 @@ Namespace DownloadObjects
|
|||||||
Dim m As IEnumerable(Of UserMediaD) = GetCheckedMedia()
|
Dim m As IEnumerable(Of UserMediaD) = GetCheckedMedia()
|
||||||
If m.ListExists Then
|
If m.ListExists Then
|
||||||
f.Remove(m)
|
f.Remove(m)
|
||||||
FeedRemoveCheckedMedia(m, {f.Name}.ToList)
|
FeedRemoveCheckedMedia(m, {f.Name}.ToList,,, False)
|
||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
@@ -1000,14 +1008,14 @@ Namespace DownloadObjects
|
|||||||
Dim m As IEnumerable(Of UserMediaD) = GetCheckedMedia()
|
Dim m As IEnumerable(Of UserMediaD) = GetCheckedMedia()
|
||||||
If m.ListExists Then
|
If m.ListExists Then
|
||||||
Settings.Feeds.Favorite.Add(m)
|
Settings.Feeds.Favorite.Add(m)
|
||||||
If sender Is BTT_FEED_ADD_FAV_REMOVE Then FeedRemoveCheckedMedia(m,,, {FeedSpecial.FavoriteName})
|
If sender Is BTT_FEED_ADD_FAV_REMOVE Then FeedRemoveCheckedMedia(m,,, {FeedSpecial.FavoriteName}, True)
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub BTT_FEED_REMOVE_FAV_Click(sender As Object, e As EventArgs) Handles BTT_FEED_REMOVE_FAV.Click
|
Private Sub BTT_FEED_REMOVE_FAV_Click(sender As Object, e As EventArgs) Handles BTT_FEED_REMOVE_FAV.Click
|
||||||
Dim m As IEnumerable(Of UserMediaD) = GetCheckedMedia()
|
Dim m As IEnumerable(Of UserMediaD) = GetCheckedMedia()
|
||||||
If m.ListExists Then
|
If m.ListExists Then
|
||||||
Settings.Feeds.Favorite.Remove(m)
|
Settings.Feeds.Favorite.Remove(m)
|
||||||
If FeedMode = FeedModes.Special Then FeedRemoveCheckedMedia(m, {FeedSpecial.FavoriteName}.ToList)
|
If FeedMode = FeedModes.Special Then FeedRemoveCheckedMedia(m, {FeedSpecial.FavoriteName}.ToList,,, False)
|
||||||
End If
|
End If
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub BTT_FEED_ADD_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_ADD_SPEC.Click, BTT_FEED_ADD_SPEC_REMOVE.Click
|
Private Sub BTT_FEED_ADD_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_ADD_SPEC.Click, BTT_FEED_ADD_SPEC_REMOVE.Click
|
||||||
@@ -1020,7 +1028,7 @@ Namespace DownloadObjects
|
|||||||
f.Add(c)
|
f.Add(c)
|
||||||
End Sub)
|
End Sub)
|
||||||
End With
|
End With
|
||||||
If sender Is BTT_FEED_ADD_SPEC_REMOVE Then FeedRemoveCheckedMedia(c,,, names)
|
If sender Is BTT_FEED_ADD_SPEC_REMOVE Then FeedRemoveCheckedMedia(c,,, names, True)
|
||||||
names.Clear()
|
names.Clear()
|
||||||
Else
|
Else
|
||||||
MsgBoxE({"You haven't selected media to add to your feed(s)", "Add to feed(s)"}, vbExclamation)
|
MsgBoxE({"You haven't selected media to add to your feed(s)", "Add to feed(s)"}, vbExclamation)
|
||||||
@@ -1036,7 +1044,7 @@ Namespace DownloadObjects
|
|||||||
f.Remove(c)
|
f.Remove(c)
|
||||||
End Sub)
|
End Sub)
|
||||||
End With
|
End With
|
||||||
If FeedMode = FeedModes.Special Then FeedRemoveCheckedMedia(c, names)
|
If FeedMode = FeedModes.Special Then FeedRemoveCheckedMedia(c, names,,, False)
|
||||||
Else
|
Else
|
||||||
MsgBoxE({"You haven't selected media to remove from your feed(s)", "Remove from feed(s)"}, vbExclamation)
|
MsgBoxE({"You haven't selected media to remove from your feed(s)", "Remove from feed(s)"}, vbExclamation)
|
||||||
End If
|
End If
|
||||||
@@ -1408,8 +1416,10 @@ Namespace DownloadObjects
|
|||||||
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Download subscription media")
|
ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Download subscription media")
|
||||||
End Try
|
End Try
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub FeedMedia_FeedAddWithRemove(ByVal Sender As FeedMedia, ByVal Feeds As IEnumerable(Of String), ByVal Media As UserMediaD, ByVal RemoveOperation As Boolean)
|
Private Sub FeedMedia_FeedRemoveCheckedMedia(ByVal Sender As FeedMedia, ByVal Media As UserMediaD, ByVal Names As IEnumerable(Of String),
|
||||||
FeedRemoveCheckedMedia({Media},, False, Feeds, RemoveOperation)
|
ByVal IsOverriddenNames As Boolean, ByVal IsAddAndRemove As Boolean)
|
||||||
|
FeedRemoveCheckedMedia({Media}, CObj(If(IsOverriddenNames, Names.ListIfNothing, Nothing)), False,
|
||||||
|
CObj(If(IsOverriddenNames, Nothing, Names)), IsAddAndRemove)
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Delete / Remove"
|
#Region "Delete / Remove"
|
||||||
@@ -1616,7 +1626,7 @@ Namespace DownloadObjects
|
|||||||
AddHandler .MediaDownload, AddressOf FeedMedia_Download
|
AddHandler .MediaDownload, AddressOf FeedMedia_Download
|
||||||
AddHandler .MediaMove, AddressOf FeedMedia_MediaMove
|
AddHandler .MediaMove, AddressOf FeedMedia_MediaMove
|
||||||
AddHandler .MediaCopy, AddressOf FeedMedia_MediaCopy
|
AddHandler .MediaCopy, AddressOf FeedMedia_MediaCopy
|
||||||
AddHandler .FeedAddWithRemove, AddressOf FeedMedia_FeedAddWithRemove
|
AddHandler .FeedRemoveCheckedMedia, AddressOf FeedMedia_FeedRemoveCheckedMedia
|
||||||
End With
|
End With
|
||||||
If de.Data.Type = UTypes.Text OrElse de.Data.PostTextFile.IsEmptyString Then Exit For
|
If de.Data.Type = UTypes.Text OrElse de.Data.PostTextFile.IsEmptyString Then Exit For
|
||||||
Next
|
Next
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ Namespace DownloadObjects
|
|||||||
Friend Event MediaDeleted(ByVal Sender As Object)
|
Friend Event MediaDeleted(ByVal Sender As Object)
|
||||||
Friend Event MediaDeletedText(ByVal Sender As Object)
|
Friend Event MediaDeletedText(ByVal Sender As Object)
|
||||||
Friend Event MediaDownload As EventHandler
|
Friend Event MediaDownload As EventHandler
|
||||||
Friend Event FeedAddWithRemove(ByVal Sender As FeedMedia, ByVal Feeds As IEnumerable(Of String), ByVal Media As UserMediaD, ByVal RemoveOperation As Boolean)
|
Friend Event FeedRemoveCheckedMedia(ByVal Sender As FeedMedia, ByVal Media As UserMediaD, ByVal Names As IEnumerable(Of String),
|
||||||
|
ByVal IsOverriddenNames As Boolean, ByVal IsAddAndRemove As Boolean)
|
||||||
Friend Event MediaMove As MediaMoveCopyEventHandler
|
Friend Event MediaMove As MediaMoveCopyEventHandler
|
||||||
Friend Event MediaCopy As MediaMoveCopyEventHandler
|
Friend Event MediaCopy As MediaMoveCopyEventHandler
|
||||||
#End Region
|
#End Region
|
||||||
@@ -435,11 +436,11 @@ Namespace DownloadObjects
|
|||||||
End Function
|
End Function
|
||||||
Private Sub Feed_SPEC_ADD_REMOVE(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs)
|
Private Sub Feed_SPEC_ADD_REMOVE(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs)
|
||||||
Dim f As FeedSpecial = Feed_SPEC_ADD_Impl(Source)
|
Dim f As FeedSpecial = Feed_SPEC_ADD_Impl(Source)
|
||||||
If Not f Is Nothing Then RaiseEvent FeedAddWithRemove(Me, {f.Name}, Media, False)
|
If Not f Is Nothing Then RaiseEvent FeedRemoveCheckedMedia(Me, Media, {f.Name}, False, True)
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub Feed_SPEC_REMOVE(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs)
|
Private Sub Feed_SPEC_REMOVE(ByVal Source As ToolStripMenuItem, ByVal e As EventArgs)
|
||||||
Dim f As FeedSpecial = Source.Tag
|
Dim f As FeedSpecial = Source.Tag
|
||||||
If Not f Is Nothing AndAlso Not f.Disposed Then f.Remove(Media) : RaiseEvent FeedAddWithRemove(Me, {f.Name}, Media, True)
|
If Not f Is Nothing AndAlso Not f.Disposed Then f.Remove(Media) : RaiseEvent FeedRemoveCheckedMedia(Me, Media, {f.Name}, True, False)
|
||||||
End Sub
|
End Sub
|
||||||
#End Region
|
#End Region
|
||||||
#Region "Dispose"
|
#Region "Dispose"
|
||||||
@@ -598,14 +599,14 @@ Namespace DownloadObjects
|
|||||||
With Settings.Feeds.Favorite
|
With Settings.Feeds.Favorite
|
||||||
If Not .Contains(Media) Then .Add(Media)
|
If Not .Contains(Media) Then .Add(Media)
|
||||||
BTT_FEED_ADD_FAV.ControlChangeColor(True, False)
|
BTT_FEED_ADD_FAV.ControlChangeColor(True, False)
|
||||||
If sender Is BTT_FEED_ADD_FAV_REMOVE Then RaiseEvent FeedAddWithRemove(Me, {FeedSpecial.FavoriteName}, Media, False)
|
If sender Is BTT_FEED_ADD_FAV_REMOVE Then RaiseEvent FeedRemoveCheckedMedia(Me, Media, {FeedSpecial.FavoriteName}, False, True)
|
||||||
End With
|
End With
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub BTT_FEED_ADD_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_ADD_SPEC.Click, BTT_FEED_ADD_SPEC_REMOVE.Click
|
Private Sub BTT_FEED_ADD_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_ADD_SPEC.Click, BTT_FEED_ADD_SPEC_REMOVE.Click
|
||||||
With FeedSpecialCollection.ChooseFeeds(True)
|
With FeedSpecialCollection.ChooseFeeds(True)
|
||||||
If .ListExists Then
|
If .ListExists Then
|
||||||
.ForEach(Sub(f) f.Add(Media))
|
.ForEach(Sub(f) f.Add(Media))
|
||||||
If sender Is BTT_FEED_ADD_SPEC_REMOVE Then RaiseEvent FeedAddWithRemove(Me, .Select(Function(f) f.Name), Media, False)
|
If sender Is BTT_FEED_ADD_SPEC_REMOVE Then RaiseEvent FeedRemoveCheckedMedia(Me, Media, .Select(Function(f) f.Name), False, True)
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
End Sub
|
End Sub
|
||||||
@@ -613,14 +614,14 @@ Namespace DownloadObjects
|
|||||||
With Settings.Feeds.Favorite
|
With Settings.Feeds.Favorite
|
||||||
If .Contains(Media) Then .Remove(Media)
|
If .Contains(Media) Then .Remove(Media)
|
||||||
BTT_FEED_ADD_FAV.ControlChangeColor(True)
|
BTT_FEED_ADD_FAV.ControlChangeColor(True)
|
||||||
RaiseEvent FeedAddWithRemove(Me, {FeedSpecial.FavoriteName}, Media, True)
|
RaiseEvent FeedRemoveCheckedMedia(Me, Media, {FeedSpecial.FavoriteName}, True, False)
|
||||||
End With
|
End With
|
||||||
End Sub
|
End Sub
|
||||||
Private Sub BTT_FEED_REMOVE_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_REMOVE_SPEC.Click
|
Private Sub BTT_FEED_REMOVE_SPEC_Click(sender As Object, e As EventArgs) Handles BTT_FEED_REMOVE_SPEC.Click
|
||||||
With FeedSpecialCollection.ChooseFeeds(False)
|
With FeedSpecialCollection.ChooseFeeds(False)
|
||||||
If .ListExists Then
|
If .ListExists Then
|
||||||
.ForEach(Sub(f) f.Remove(Media))
|
.ForEach(Sub(f) f.Remove(Media))
|
||||||
RaiseEvent FeedAddWithRemove(Me, .Select(Function(f) f.Name), Media, True)
|
RaiseEvent FeedRemoveCheckedMedia(Me, Media, .Select(Function(f) f.Name), True, False)
|
||||||
End If
|
End If
|
||||||
End With
|
End With
|
||||||
End Sub
|
End Sub
|
||||||
|
|||||||
@@ -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("2026.1.24.0")>
|
<Assembly: AssemblyVersion("2026.2.14.0")>
|
||||||
<Assembly: AssemblyFileVersion("2026.1.24.0")>
|
<Assembly: AssemblyFileVersion("2026.2.14.0")>
|
||||||
<Assembly: NeutralResourcesLanguage("en")>
|
<Assembly: NeutralResourcesLanguage("en")>
|
||||||
|
|||||||
Reference in New Issue
Block a user