Compare commits

...

4 Commits

Author SHA1 Message Date
Andy
5d64b8c7ce 2022.12.27.0
XVideos: added 'Quickies'; fixed downloading.
Instagram: added more enable/disable options.
2022-12-27 15:04:56 +03:00
Andy
aabf6d62ab 2022.12.26.0
UserMedia: fixed plugin bugs
Instagram: updated algo and settings; update responser settings based on site response
PornHub: fixed bug in SiteSettings; fixed typos
RedGis: fixed downloading user profiles
XVideos: fixed user profile opening
UserDataBind: fixed multiple collection removing issue
DownloadedInfoForm: fixed user focusing
UserCreatorForm: add user name to form header if user exists
ListImagesLoader: changed loading algo
MainFrame: added channels button to tray context menu
Added ffmpeg fox x86
Fixed typos
2022-12-26 17:37:25 +03:00
Andy
03487185c5 Update names
Updated library objects
2022-12-24 15:45:12 +03:00
Andy
f0686bbc8e Fixes
Fixed typo
Added label icon to context menu
Fixed PornHub bug
Added 'Object' to IUserMedia
2022-12-24 15:18:04 +03:00
57 changed files with 785 additions and 978 deletions

View File

@@ -1,3 +1,36 @@
# 2022.12.27.0
*2022-12-27*
- Added
- XVideos: added downloading 'Quickies'
- Instagram: added more enable/disable options
- Fixed
- XVideos not downloading (sorry, I broke it in a previous release)
# 2022.12.26.0
*2022-12-26*
**ATTENTION!**
**Instagram requirements changed. Headers and cookies are now required to download Timeline, Stories and Saved posts; hash to download tagged posts. Please update your credentials.**
**Instagram tagged posts no longer provide the total amount of tagged posts. I've corrected the tagged posts notification, but now I can't tell how many requests will be spent on downloading tagged posts. And from now on, one request will be spent on downloading each tagged post, because Instagram doesn't provide complete information about the tagged post with the site's response. In this case, if the number of tagged posts is 1000, 1000 requests will be spent. Be careful when downloading them. I highly recommend that you forcefully disable the downloading of tagged posts for a while.**
- Added
- Updated user loading algorithm
- Channels button to tray context menu
- (Request #96) Add FFmpeg to x86 version
- Fixed
- PornHub wrong behavior when downloading images
- Unable open XVideos user profile
- Cannot delete multiple collections at once
- Can't focus user from the download info form
- Instagram downloader not working
- (Issue #69) **RedGifs data is not downloading**. Again.
- Minor bugs
# 2022.11.16.0 # 2022.11.16.0
*2022-11-16* *2022-11-16*

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

View File

@@ -1,7 +1,10 @@
# :rainbow_flag: Social networks crawler :rainbow_flag: # :rainbow_flag: Social networks crawler :rainbow_flag: :christmas_tree:
# :christmas_tree: Happy new year :christmas_tree:
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/AAndyProgram/SCrawler)](https://github.com/AAndyProgram/SCrawler/releases/latest) [![GitHub release (latest by date)](https://img.shields.io/github/v/release/AAndyProgram/SCrawler)](https://github.com/AAndyProgram/SCrawler/releases/latest)
[![GitHub license](https://img.shields.io/github/license/AAndyProgram/SCrawler)](https://github.com/AAndyProgram/SCrawler/blob/main/LICENSE) [![GitHub license](https://img.shields.io/github/license/AAndyProgram/SCrawler)](https://github.com/AAndyProgram/SCrawler/blob/main/LICENSE)
[![GitHub all releases](https://img.shields.io/github/downloads/aandyprogram/scrawler/total?label=Total%20downloads)](https://github.com/AAndyProgram/SCrawler/releases)
[![FAQ](https://img.shields.io/badge/FAQ-green)](FAQ.md) [![FAQ](https://img.shields.io/badge/FAQ-green)](FAQ.md)
[![GUIDE](https://img.shields.io/badge/GUIDE-green)](https://github.com/AAndyProgram/SCrawler/wiki) [![GUIDE](https://img.shields.io/badge/GUIDE-green)](https://github.com/AAndyProgram/SCrawler/wiki)
[![How to support](https://img.shields.io/badge/HowToSupport-green)](HowToSupport.md) [![How to support](https://img.shields.io/badge/HowToSupport-green)](HowToSupport.md)

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

View File

@@ -34,6 +34,7 @@ Namespace Plugin
Public Property PostDate As Date? Implements IUserMedia.PostDate Public Property PostDate As Date? Implements IUserMedia.PostDate
Public Property SpecialFolder As String Implements IUserMedia.SpecialFolder Public Property SpecialFolder As String Implements IUserMedia.SpecialFolder
Public Property Attempts As Integer Implements IUserMedia.Attempts Public Property Attempts As Integer Implements IUserMedia.Attempts
Public Property [Object] As Object Implements IUserMedia.Object
End Structure End Structure
Public Interface IUserMedia Public Interface IUserMedia
Property ContentType As Integer Property ContentType As Integer
@@ -46,5 +47,6 @@ Namespace Plugin
Property PostDate As Date? Property PostDate As Date?
Property SpecialFolder As String Property SpecialFolder As String
Property Attempts As Integer Property Attempts As Integer
Property [Object] As Object
End Interface End Interface
End Namespace End Namespace

View File

@@ -28,7 +28,7 @@ Namespace API.Base
Return $"{Appender.StringTrimEnd("/")}/{File}" Return $"{Appender.StringTrimEnd("/")}/{File}"
End If End If
End Function End Function
Friend Shared Function Download(ByVal URLs As List(Of String), ByVal DestinationFile As SFile, Optional ByVal Responser As Response = Nothing) As SFile Friend Shared Function Download(ByVal URLs As List(Of String), ByVal DestinationFile As SFile, Optional ByVal Responser As Responser = Nothing) As SFile
Dim CachePath As SFile = Nothing Dim CachePath As SFile = Nothing
Try Try
If URLs.ListExists Then If URLs.ListExists Then

View File

@@ -17,8 +17,8 @@ Namespace API.Base
Friend Overridable ReadOnly Property Icon As Icon Implements ISiteSettings.Icon Friend Overridable ReadOnly Property Icon As Icon Implements ISiteSettings.Icon
Friend Overridable ReadOnly Property Image As Image Implements ISiteSettings.Image Friend Overridable ReadOnly Property Image As Image Implements ISiteSettings.Image
Private Property Logger As ILogProvider = LogConnector Implements ISiteSettings.Logger Private Property Logger As ILogProvider = LogConnector Implements ISiteSettings.Logger
Friend Overridable ReadOnly Property Responser As Response Friend Overridable ReadOnly Property Responser As Responser
Private Property IResponserContainer_Responser As Response Implements IResponserContainer.Responser Private Property IResponserContainer_Responser As Responser Implements IResponserContainer.Responser
Get Get
Return Responser Return Responser
End Get End Get
@@ -30,7 +30,7 @@ Namespace API.Base
End Sub End Sub
Friend Sub New(ByVal SiteName As String, ByVal CookiesDomain As String) Friend Sub New(ByVal SiteName As String, ByVal CookiesDomain As String)
Site = SiteName Site = SiteName
Responser = New Response($"{SettingsFolderName}\Responser_{Site}.xml") Responser = New Responser($"{SettingsFolderName}\Responser_{Site}.xml")
With Responser With Responser
If .File.Exists Then If .File.Exists Then
If EncryptCookies.CookiesEncrypted Then .CookiesEncryptKey = SettingsCLS.CookieEncryptKey If EncryptCookies.CookiesEncrypted Then .CookiesEncryptKey = SettingsCLS.CookieEncryptKey

View File

@@ -104,7 +104,7 @@ Namespace API.Base
Return Post.ID Return Post.ID
End Get End Get
Set(ByVal PostID As String) Set(ByVal PostID As String)
Post.ID = PostID Post = New UserPost(PostID, Post.Date)
End Set End Set
End Property End Property
Private Property IUserMedia_PostDate As Date? Implements IUserMedia.PostDate Private Property IUserMedia_PostDate As Date? Implements IUserMedia.PostDate
@@ -112,7 +112,7 @@ Namespace API.Base
Return Post.Date Return Post.Date
End Get End Get
Set(ByVal PostDate As Date?) Set(ByVal PostDate As Date?)
Post.Date = PostDate Post = New UserPost(Post.ID, PostDate)
End Set End Set
End Property End Property
Private Property IUserMedia_SpecialFolder As String Implements IUserMedia.SpecialFolder Private Property IUserMedia_SpecialFolder As String Implements IUserMedia.SpecialFolder
@@ -131,6 +131,14 @@ Namespace API.Base
Me.Attempts = Attempts Me.Attempts = Attempts
End Set End Set
End Property End Property
Private Property IUserMedia_Object As Object Implements IUserMedia.Object
Get
Return Me.Object
End Get
Set(ByVal Obj As Object)
Me.Object = Obj
End Set
End Property
#End Region #End Region
Friend Sub New(ByVal URL As String) Friend Sub New(ByVal URL As String)
Me.URL = URL Me.URL = URL
@@ -142,7 +150,7 @@ Namespace API.Base
Me.New(URL) Me.New(URL)
Me.Type = Type Me.Type = Type
End Sub End Sub
Friend Sub New(ByVal m As Plugin.IUserMedia) Friend Sub New(ByVal m As IUserMedia)
[Type] = m.ContentType [Type] = m.ContentType
URL = m.URL URL = m.URL
URL_BASE = m.URL_BASE URL_BASE = m.URL_BASE
@@ -152,6 +160,7 @@ Namespace API.Base
State = m.DownloadState State = m.DownloadState
SpecialFolder = m.SpecialFolder SpecialFolder = m.SpecialFolder
Attempts = m.Attempts Attempts = m.Attempts
Me.Object = m.Object
End Sub End Sub
Friend Sub New(ByVal e As EContainer, ByVal UserInstance As IUserData) Friend Sub New(ByVal e As EContainer, ByVal UserInstance As IUserData)
Type = e.Attribute(Name_MediaType).Value.FromXML(Of Integer)(CInt(Types.Undefined)) Type = e.Attribute(Name_MediaType).Value.FromXML(Of Integer)(CInt(Types.Undefined))

View File

@@ -682,6 +682,7 @@ BlockNullPicture:
LastUpdated = AConvert(Of Date)(x.Value(Name_LastUpdated), ADateTime.Formats.BaseDateTime, Nothing) LastUpdated = AConvert(Of Date)(x.Value(Name_LastUpdated), ADateTime.Formats.BaseDateTime, Nothing)
ScriptUse = x.Value(Name_ScriptUse).FromXML(Of Boolean)(False) ScriptUse = x.Value(Name_ScriptUse).FromXML(Of Boolean)(False)
ScriptData = x.Value(Name_ScriptData) ScriptData = x.Value(Name_ScriptData)
'TODELETE: UserDataBase remove old 'merge' constant
#Disable Warning BC40000 #Disable Warning BC40000
If x.Contains(Name_DataMerging) Then If x.Contains(Name_DataMerging) Then
DataMerging = x.Value(Name_DataMerging).FromXML(Of Boolean)(False) DataMerging = x.Value(Name_DataMerging).FromXML(Of Boolean)(False)
@@ -843,7 +844,7 @@ BlockNullPicture:
End Function End Function
#End Region #End Region
#Region "Download functions and options" #Region "Download functions and options"
Protected Responser As Response Protected Responser As Responser
Protected UseResponserClient As Boolean = False Protected UseResponserClient As Boolean = False
Friend Overridable Sub DownloadData(ByVal Token As CancellationToken) Implements IContentProvider.DownloadData Friend Overridable Sub DownloadData(ByVal Token As CancellationToken) Implements IContentProvider.DownloadData
Dim Canceled As Boolean = False Dim Canceled As Boolean = False
@@ -852,7 +853,7 @@ BlockNullPicture:
UpdateDataFiles() UpdateDataFiles()
UserDescriptionReset() UserDescriptionReset()
If Not Responser Is Nothing Then Responser.Dispose() If Not Responser Is Nothing Then Responser.Dispose()
Responser = New Response Responser = New Responser
If Not HOST.Responser Is Nothing Then Responser.Copy(HOST.Responser) If Not HOST.Responser Is Nothing Then Responser.Copy(HOST.Responser)
'TODO: UserDataBase remove [Responser.DecodersError] 'TODO: UserDataBase remove [Responser.DecodersError]
Responser.DecodersError = New ErrorsDescriber(EDP.SendInLog + EDP.ReturnValue) With { Responser.DecodersError = New ErrorsDescriber(EDP.SendInLog + EDP.ReturnValue) With {

View File

@@ -1,135 +0,0 @@
' Copyright (C) 2023 Andy https://github.com/AAndyProgram
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Namespace API.Instagram
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Friend Class AdditionalSettingsForm : Inherits System.Windows.Forms.Form
<System.Diagnostics.DebuggerNonUserCode()>
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
Private components As System.ComponentModel.IContainer
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
Me.CH_DOWN_TIME = New System.Windows.Forms.CheckBox()
Me.CH_DOWN_TAG = New System.Windows.Forms.CheckBox()
Me.CH_DOWN_SAVED = New System.Windows.Forms.CheckBox()
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
CONTAINER_MAIN.ContentPanel.SuspendLayout()
CONTAINER_MAIN.SuspendLayout()
TP_MAIN.SuspendLayout()
Me.SuspendLayout()
'
'CONTAINER_MAIN
'
'
'CONTAINER_MAIN.ContentPanel
'
CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(234, 78)
CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
CONTAINER_MAIN.LeftToolStripPanelVisible = False
CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
CONTAINER_MAIN.Name = "CONTAINER_MAIN"
CONTAINER_MAIN.RightToolStripPanelVisible = False
CONTAINER_MAIN.Size = New System.Drawing.Size(234, 103)
CONTAINER_MAIN.TabIndex = 0
CONTAINER_MAIN.TopToolStripPanelVisible = False
'
'TP_MAIN
'
TP_MAIN.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
TP_MAIN.ColumnCount = 1
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20.0!))
TP_MAIN.Controls.Add(Me.CH_DOWN_TIME, 0, 0)
TP_MAIN.Controls.Add(Me.CH_DOWN_TAG, 0, 1)
TP_MAIN.Controls.Add(Me.CH_DOWN_SAVED, 0, 2)
TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
TP_MAIN.Location = New System.Drawing.Point(0, 0)
TP_MAIN.Name = "TP_MAIN"
TP_MAIN.RowCount = 4
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MAIN.Size = New System.Drawing.Size(234, 78)
TP_MAIN.TabIndex = 0
'
'CH_DOWN_TIME
'
Me.CH_DOWN_TIME.AutoSize = True
Me.CH_DOWN_TIME.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_DOWN_TIME.Location = New System.Drawing.Point(4, 4)
Me.CH_DOWN_TIME.Name = "CH_DOWN_TIME"
Me.CH_DOWN_TIME.Size = New System.Drawing.Size(226, 19)
Me.CH_DOWN_TIME.TabIndex = 0
Me.CH_DOWN_TIME.Text = "Download Timeline"
Me.CH_DOWN_TIME.UseVisualStyleBackColor = True
'
'CH_DOWN_TAG
'
Me.CH_DOWN_TAG.AutoSize = True
Me.CH_DOWN_TAG.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_DOWN_TAG.Location = New System.Drawing.Point(4, 30)
Me.CH_DOWN_TAG.Name = "CH_DOWN_TAG"
Me.CH_DOWN_TAG.Size = New System.Drawing.Size(226, 19)
Me.CH_DOWN_TAG.TabIndex = 1
Me.CH_DOWN_TAG.Text = "Download Stories and Tagged data"
Me.CH_DOWN_TAG.UseVisualStyleBackColor = True
'
'CH_DOWN_SAVED
'
Me.CH_DOWN_SAVED.AutoSize = True
Me.CH_DOWN_SAVED.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_DOWN_SAVED.Location = New System.Drawing.Point(4, 56)
Me.CH_DOWN_SAVED.Name = "CH_DOWN_SAVED"
Me.CH_DOWN_SAVED.Size = New System.Drawing.Size(226, 19)
Me.CH_DOWN_SAVED.TabIndex = 2
Me.CH_DOWN_SAVED.Text = "Download saved posts"
Me.CH_DOWN_SAVED.UseVisualStyleBackColor = True
'
'AdditionalSettingsForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(234, 103)
Me.Controls.Add(CONTAINER_MAIN)
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
Me.Icon = Global.SCrawler.My.Resources.SiteResources.InstagramIcon_32
Me.KeyPreview = True
Me.MaximizeBox = False
Me.MaximumSize = New System.Drawing.Size(250, 142)
Me.MinimizeBox = False
Me.MinimumSize = New System.Drawing.Size(250, 142)
Me.Name = "AdditionalSettingsForm"
Me.ShowInTaskbar = False
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
Me.Text = "Additional settings"
CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
CONTAINER_MAIN.ResumeLayout(False)
CONTAINER_MAIN.PerformLayout()
TP_MAIN.ResumeLayout(False)
TP_MAIN.PerformLayout()
Me.ResumeLayout(False)
End Sub
Private WithEvents CH_DOWN_TIME As CheckBox
Private WithEvents CH_DOWN_TAG As CheckBox
Private WithEvents CH_DOWN_SAVED As CheckBox
End Class
End Namespace

View File

@@ -1,126 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="CONTAINER_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="TP_MAIN.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
</root>

View File

@@ -1,41 +0,0 @@
' Copyright (C) 2023 Andy https://github.com/AAndyProgram
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Imports PersonalUtilities.Forms
Namespace API.Instagram
Friend Class AdditionalSettingsForm
Private WithEvents MyDefs As DefaultFormOptions
Friend Property MyParameters As SettingsExchangeOptions
Friend Sub New(ByVal Parameters As SettingsExchangeOptions)
InitializeComponent()
MyParameters = Parameters
MyDefs = New DefaultFormOptions(Me, Settings.Design)
End Sub
Private Sub MyForm_Load(sender As Object, e As EventArgs) Handles Me.Load
With MyDefs
.MyViewInitialize(True)
.AddOkCancelToolbar()
With MyParameters
CH_DOWN_TIME.Checked = .DownloadTimeline
CH_DOWN_TAG.Checked = .DownloadStoriesTagged
CH_DOWN_SAVED.Checked = .DownloadSaved
End With
.EndLoaderOperations()
End With
End Sub
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
MyParameters = New SettingsExchangeOptions With {
.DownloadTimeline = CH_DOWN_TIME.Checked,
.DownloadStoriesTagged = CH_DOWN_TAG.Checked,
.DownloadSaved = CH_DOWN_SAVED.Checked,
.Changed = True
}
MyDefs.CloseForm()
End Sub
End Class
End Namespace

View File

@@ -7,11 +7,49 @@
' 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.Functions.RegularExpressions Imports PersonalUtilities.Functions.RegularExpressions
Imports PersonalUtilities.Tools.Web.Clients
Imports PersonalUtilities.Tools.Web.Clients.EventArguments
Imports PersonalUtilities.Tools.Web.Cookies
Namespace API.Instagram Namespace API.Instagram
Friend Module Declarations Friend Module Declarations
Friend Const InstagramSite As String = "Instagram" Friend Const InstagramSite As String = "Instagram"
Friend Const InstagramSiteKey As String = "AndyProgram_Instagram" Friend Const InstagramSiteKey As String = "AndyProgram_Instagram"
Friend ReadOnly FilesPattern As RParams = RParams.DMS(".+?([^/\?]+?\.[\w\d]{3,4})(?=(\?|\Z))", 1, EDP.ReturnValue) Friend ReadOnly FilesPattern As RParams = RParams.DMS(".+?([^/\?]+?\.[\w\d]{3,4})(?=(\?|\Z))", 1, EDP.ReturnValue)
Friend ReadOnly Property DateProvider As New CustomProvider(Function(v, d, p, n, e) ADateTime.ParseUnicode(v)) Friend ReadOnly Property DateProvider As New CustomProvider(Function(v, d, p, n, e) ADateTime.ParseUnicode(v))
Friend Sub UpdateResponser(ByVal Source As IResponse, ByRef Destination As Responser)
Const r_wwwClaimName$ = "x-ig-set-www-claim"
Const r_tokenName$ = "csrftoken"
If Not Source Is Nothing Then
Dim isInternal As Boolean = TypeOf Source Is WebDataResponse
Dim wwwClaimName$, tokenName$
If isInternal Then
wwwClaimName = r_wwwClaimName
tokenName = r_tokenName
Else
wwwClaimName = SiteSettings.Header_IG_WWW_CLAIM
tokenName = SiteSettings.Header_CSRF_TOKEN
End If
Dim wwwClaim$ = String.Empty
Dim token$ = String.Empty
With Source
If isInternal Then
If .HeadersExists Then wwwClaim = .Headers.Value(wwwClaimName)
If .CookiesExists Then token = If(.Cookies.FirstOrDefault(Function(c) c.Name = tokenName)?.Value, String.Empty)
Else
If .HeadersExists Then
wwwClaim = .Headers.Value(wwwClaimName)
token = .Headers.Value(tokenName)
End If
End If
End With
If Not wwwClaim.IsEmptyString Then Destination.Headers.Add(SiteSettings.Header_IG_WWW_CLAIM, wwwClaim)
If Not token.IsEmptyString Then Destination.Headers.Add(SiteSettings.Header_CSRF_TOKEN, token)
If Not isInternal Then
Destination.Cookies.Update(Source.Cookies, CookieKeeper.UpdateModes.ReplaceByNameAll, False, EDP.SendInLog)
Destination.SaveSettings()
End If
End If
End Sub
End Module End Module
End Namespace End Namespace

View File

@@ -9,10 +9,12 @@
Imports SCrawler.Plugin Imports SCrawler.Plugin
Namespace API.Instagram Namespace API.Instagram
Friend Class EditorExchangeOptions Friend Class EditorExchangeOptions
Friend Property GetTimeline As Boolean
Friend Property GetStories As Boolean Friend Property GetStories As Boolean
Friend Property GetTagged As Boolean Friend Property GetTagged As Boolean
Friend Sub New(ByVal h As ISiteSettings) Friend Sub New(ByVal h As ISiteSettings)
With DirectCast(h, SiteSettings) With DirectCast(h, SiteSettings)
GetTimeline = CBool(.GetTimeline.Value)
GetStories = CBool(.GetStories.Value) GetStories = CBool(.GetStories.Value)
GetTagged = CBool(.GetTagged.Value) GetTagged = CBool(.GetTagged.Value)
End With End With

View File

@@ -26,6 +26,7 @@ Namespace API.Instagram
Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel Dim TP_MAIN As System.Windows.Forms.TableLayoutPanel
Me.CH_GET_STORIES = New System.Windows.Forms.CheckBox() Me.CH_GET_STORIES = New System.Windows.Forms.CheckBox()
Me.CH_GET_TAGGED = New System.Windows.Forms.CheckBox() Me.CH_GET_TAGGED = New System.Windows.Forms.CheckBox()
Me.CH_GET_TIMELINE = New System.Windows.Forms.CheckBox()
CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer() CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer()
TP_MAIN = New System.Windows.Forms.TableLayoutPanel() TP_MAIN = New System.Windows.Forms.TableLayoutPanel()
CONTAINER_MAIN.ContentPanel.SuspendLayout() CONTAINER_MAIN.ContentPanel.SuspendLayout()
@@ -39,13 +40,13 @@ Namespace API.Instagram
'CONTAINER_MAIN.ContentPanel 'CONTAINER_MAIN.ContentPanel
' '
CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN) CONTAINER_MAIN.ContentPanel.Controls.Add(TP_MAIN)
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(260, 53) CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(260, 79)
CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
CONTAINER_MAIN.LeftToolStripPanelVisible = False CONTAINER_MAIN.LeftToolStripPanelVisible = False
CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0) CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
CONTAINER_MAIN.Name = "CONTAINER_MAIN" CONTAINER_MAIN.Name = "CONTAINER_MAIN"
CONTAINER_MAIN.RightToolStripPanelVisible = False CONTAINER_MAIN.RightToolStripPanelVisible = False
CONTAINER_MAIN.Size = New System.Drawing.Size(260, 78) CONTAINER_MAIN.Size = New System.Drawing.Size(260, 104)
CONTAINER_MAIN.TabIndex = 0 CONTAINER_MAIN.TabIndex = 0
CONTAINER_MAIN.TopToolStripPanelVisible = False CONTAINER_MAIN.TopToolStripPanelVisible = False
' '
@@ -54,26 +55,28 @@ Namespace API.Instagram
TP_MAIN.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] TP_MAIN.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single]
TP_MAIN.ColumnCount = 1 TP_MAIN.ColumnCount = 1
TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) TP_MAIN.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MAIN.Controls.Add(Me.CH_GET_STORIES, 0, 0) TP_MAIN.Controls.Add(Me.CH_GET_STORIES, 0, 1)
TP_MAIN.Controls.Add(Me.CH_GET_TAGGED, 0, 1) TP_MAIN.Controls.Add(Me.CH_GET_TAGGED, 0, 2)
TP_MAIN.Controls.Add(Me.CH_GET_TIMELINE, 0, 0)
TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill TP_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
TP_MAIN.Location = New System.Drawing.Point(0, 0) TP_MAIN.Location = New System.Drawing.Point(0, 0)
TP_MAIN.Name = "TP_MAIN" TP_MAIN.Name = "TP_MAIN"
TP_MAIN.RowCount = 3 TP_MAIN.RowCount = 4
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!))
TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
TP_MAIN.Size = New System.Drawing.Size(260, 53) TP_MAIN.Size = New System.Drawing.Size(260, 79)
TP_MAIN.TabIndex = 0 TP_MAIN.TabIndex = 0
' '
'CH_GET_STORIES 'CH_GET_STORIES
' '
Me.CH_GET_STORIES.AutoSize = True Me.CH_GET_STORIES.AutoSize = True
Me.CH_GET_STORIES.Dock = System.Windows.Forms.DockStyle.Fill Me.CH_GET_STORIES.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_GET_STORIES.Location = New System.Drawing.Point(4, 4) Me.CH_GET_STORIES.Location = New System.Drawing.Point(4, 30)
Me.CH_GET_STORIES.Name = "CH_GET_STORIES" Me.CH_GET_STORIES.Name = "CH_GET_STORIES"
Me.CH_GET_STORIES.Size = New System.Drawing.Size(252, 19) Me.CH_GET_STORIES.Size = New System.Drawing.Size(252, 19)
Me.CH_GET_STORIES.TabIndex = 0 Me.CH_GET_STORIES.TabIndex = 1
Me.CH_GET_STORIES.Text = "Get stories" Me.CH_GET_STORIES.Text = "Get stories"
Me.CH_GET_STORIES.UseVisualStyleBackColor = True Me.CH_GET_STORIES.UseVisualStyleBackColor = True
' '
@@ -81,26 +84,37 @@ Namespace API.Instagram
' '
Me.CH_GET_TAGGED.AutoSize = True Me.CH_GET_TAGGED.AutoSize = True
Me.CH_GET_TAGGED.Dock = System.Windows.Forms.DockStyle.Fill Me.CH_GET_TAGGED.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_GET_TAGGED.Location = New System.Drawing.Point(4, 30) Me.CH_GET_TAGGED.Location = New System.Drawing.Point(4, 56)
Me.CH_GET_TAGGED.Name = "CH_GET_TAGGED" Me.CH_GET_TAGGED.Name = "CH_GET_TAGGED"
Me.CH_GET_TAGGED.Size = New System.Drawing.Size(252, 19) Me.CH_GET_TAGGED.Size = New System.Drawing.Size(252, 19)
Me.CH_GET_TAGGED.TabIndex = 1 Me.CH_GET_TAGGED.TabIndex = 2
Me.CH_GET_TAGGED.Text = "Get tagged data" Me.CH_GET_TAGGED.Text = "Get tagged data"
Me.CH_GET_TAGGED.UseVisualStyleBackColor = True Me.CH_GET_TAGGED.UseVisualStyleBackColor = True
' '
'CH_GET_TIMELINE
'
Me.CH_GET_TIMELINE.AutoSize = True
Me.CH_GET_TIMELINE.Dock = System.Windows.Forms.DockStyle.Fill
Me.CH_GET_TIMELINE.Location = New System.Drawing.Point(4, 4)
Me.CH_GET_TIMELINE.Name = "CH_GET_TIMELINE"
Me.CH_GET_TIMELINE.Size = New System.Drawing.Size(252, 19)
Me.CH_GET_TIMELINE.TabIndex = 0
Me.CH_GET_TIMELINE.Text = "Get Timeline"
Me.CH_GET_TIMELINE.UseVisualStyleBackColor = True
'
'OptionsForm 'OptionsForm
' '
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(260, 78) Me.ClientSize = New System.Drawing.Size(260, 104)
Me.Controls.Add(CONTAINER_MAIN) Me.Controls.Add(CONTAINER_MAIN)
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
Me.Icon = Global.SCrawler.My.Resources.SiteResources.InstagramIcon_32 Me.Icon = Global.SCrawler.My.Resources.SiteResources.InstagramIcon_32
Me.KeyPreview = True Me.KeyPreview = True
Me.MaximizeBox = False Me.MaximizeBox = False
Me.MaximumSize = New System.Drawing.Size(276, 117) Me.MaximumSize = New System.Drawing.Size(276, 143)
Me.MinimizeBox = False Me.MinimizeBox = False
Me.MinimumSize = New System.Drawing.Size(276, 117) Me.MinimumSize = New System.Drawing.Size(276, 143)
Me.Name = "OptionsForm" Me.Name = "OptionsForm"
Me.ShowInTaskbar = False Me.ShowInTaskbar = False
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
@@ -116,5 +130,6 @@ Namespace API.Instagram
Private WithEvents CH_GET_STORIES As CheckBox Private WithEvents CH_GET_STORIES As CheckBox
Private WithEvents CH_GET_TAGGED As CheckBox Private WithEvents CH_GET_TAGGED As CheckBox
Private WithEvents CH_GET_TIMELINE As CheckBox
End Class End Class
End Namespace End Namespace

View File

@@ -21,6 +21,7 @@ Namespace API.Instagram
.MyViewInitialize(True) .MyViewInitialize(True)
.AddOkCancelToolbar() .AddOkCancelToolbar()
With MyExchangeOptions With MyExchangeOptions
CH_GET_TIMELINE.Checked = .GetTimeline
CH_GET_STORIES.Checked = .GetStories CH_GET_STORIES.Checked = .GetStories
CH_GET_TAGGED.Checked = .GetTagged CH_GET_TAGGED.Checked = .GetTagged
End With End With
@@ -29,6 +30,7 @@ Namespace API.Instagram
End Sub End Sub
Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick Private Sub MyDefs_ButtonOkClick(ByVal Sender As Object, ByVal e As KeyHandleEventArgs) Handles MyDefs.ButtonOkClick
With MyExchangeOptions With MyExchangeOptions
.GetTimeline = CH_GET_TIMELINE.Checked
.GetStories = CH_GET_STORIES.Checked .GetStories = CH_GET_STORIES.Checked
.GetTagged = CH_GET_TAGGED.Checked .GetTagged = CH_GET_TAGGED.Checked
End With End With

View File

@@ -1,23 +0,0 @@
' Copyright (C) 2023 Andy https://github.com/AAndyProgram
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY
Namespace API.Instagram
Friend Structure SettingsExchangeOptions
Friend DownloadTimeline As Boolean
Friend DownloadStoriesTagged As Boolean
Friend DownloadSaved As Boolean
Friend Changed As Boolean
Friend Sub New(ByVal Source As SiteSettings)
With Source
DownloadTimeline = .DownloadTimeline
DownloadStoriesTagged = .DownloadStoriesTagged
DownloadSaved = .DownloadSaved
End With
End Sub
End Structure
End Namespace

View File

@@ -13,9 +13,11 @@ Imports PersonalUtilities.Forms
Imports PersonalUtilities.Functions.XML Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.XML.Base Imports PersonalUtilities.Functions.XML.Base
Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Functions.RegularExpressions
Imports PersonalUtilities.Tools.Web.Clients
Imports PersonalUtilities.Tools.Web.Cookies
Imports Download = SCrawler.Plugin.ISiteSettings.Download Imports Download = SCrawler.Plugin.ISiteSettings.Download
Namespace API.Instagram Namespace API.Instagram
<Manifest(InstagramSiteKey), SeparatedTasks(1), SavedPosts, SpecialForm(False), SpecialForm(True)> <Manifest(InstagramSiteKey), SeparatedTasks(1), SavedPosts, SpecialForm(False)>
Friend Class SiteSettings : Inherits SiteSettingsBase Friend Class SiteSettings : Inherits SiteSettingsBase
#Region "Declarations" #Region "Declarations"
#Region "Images" #Region "Images"
@@ -77,28 +79,23 @@ Namespace API.Instagram
End Class End Class
#End Region #End Region
#Region "Authorization properties" #Region "Authorization properties"
<PropertyOption(ControlText:="Hash", ControlToolTip:="Instagram session hash", IsAuth:=True, AllowNull:=False), PXML("InstaHash"), ControlNumber(0)> <PropertyOption(ControlText:="Hash", ControlToolTip:="Instagram session hash for tagged posts", IsAuth:=True), PXML("InstaHash"), ControlNumber(0)>
Friend ReadOnly Property Hash As PropertyValue Friend ReadOnly Property HashTagged As PropertyValue
Private Const HashSavedPosts_Text As String = "Hash 2" <PropertyOption(ControlText:="x-csrftoken", IsAuth:=True, AllowNull:=False), ControlNumber(2)>
<PropertyOption(ControlText:=HashSavedPosts_Text, ControlToolTip:="Instagram session hash for saved posts", IsAuth:=True), PXML("InstaHashSavedPosts"), ControlNumber(1)>
Friend ReadOnly Property HashSavedPosts As PropertyValue
<PropertyOption(ControlText:="x-csrftoken", ControlToolTip:="Instagram token for tagged data", IsAuth:=True, AllowNull:=False), ControlNumber(2)>
Friend ReadOnly Property CSRF_TOKEN As PropertyValue Friend ReadOnly Property CSRF_TOKEN As PropertyValue
<PropertyOption(ControlText:="x-ig-app-id", IsAuth:=True, AllowNull:=False), ControlNumber(3)> <PropertyOption(ControlText:="x-ig-app-id", IsAuth:=True, AllowNull:=False), ControlNumber(3)>
Friend Property IG_APP_ID As PropertyValue Friend Property IG_APP_ID As PropertyValue
<PropertyOption(ControlText:="x-ig-www-claim", IsAuth:=True, AllowNull:=False), ControlNumber(4)> <PropertyOption(ControlText:="x-ig-www-claim", IsAuth:=True, AllowNull:=False), ControlNumber(4)>
Friend Property IG_WWW_CLAIM As PropertyValue Friend Property IG_WWW_CLAIM As PropertyValue
Private Const SavedPostsUserName_Text As String = "Saved posts user"
<PropertyOption(ControlText:=SavedPostsUserName_Text, ControlToolTip:="Personal profile username", IsAuth:=True), PXML("SavedPostsUserName"), ControlNumber(5)>
Friend ReadOnly Property SavedPostsUserName As PropertyValue
Friend Overrides Function BaseAuthExists() As Boolean Friend Overrides Function BaseAuthExists() As Boolean
Return If(Responser.Cookies?.Count, 0) > 0 And ACheck(IG_APP_ID.Value) And ACheck(IG_WWW_CLAIM.Value) And ACheck(CSRF_TOKEN.Value) Return Responser.CookiesExists And ACheck(IG_APP_ID.Value) And ACheck(IG_WWW_CLAIM.Value) And ACheck(CSRF_TOKEN.Value)
End Function End Function
Private Const Header_IG_APP_ID As String = "x-ig-app-id" Private Const Header_IG_APP_ID As String = "x-ig-app-id"
Private Const Header_IG_WWW_CLAIM As String = "x-ig-www-claim" Friend Const Header_IG_WWW_CLAIM As String = "x-ig-www-claim"
Private Const Header_CSRF_TOKEN As String = "x-csrftoken" Friend Const Header_CSRF_TOKEN As String = "x-csrftoken"
Private _FieldsChangerSuspended As Boolean = False
Private Sub ChangeResponserFields(ByVal PropName As String, ByVal Value As Object) Private Sub ChangeResponserFields(ByVal PropName As String, ByVal Value As Object)
If Not PropName.IsEmptyString Then If Not _FieldsChangerSuspended And Not PropName.IsEmptyString Then
Dim f$ = String.Empty Dim f$ = String.Empty
Select Case PropName Select Case PropName
Case NameOf(IG_APP_ID) : f = Header_IG_APP_ID Case NameOf(IG_APP_ID) : f = Header_IG_APP_ID
@@ -106,41 +103,46 @@ Namespace API.Instagram
Case NameOf(CSRF_TOKEN) : f = Header_CSRF_TOKEN Case NameOf(CSRF_TOKEN) : f = Header_CSRF_TOKEN
End Select End Select
If Not f.IsEmptyString Then If Not f.IsEmptyString Then
Responser.HeadersRemove(f) Responser.Headers.Remove(f)
If Not CStr(Value).IsEmptyString Then Responser.HeadersAdd(f, CStr(Value)) If Not CStr(Value).IsEmptyString Then Responser.Headers.Add(f, CStr(Value))
Responser.SaveSettings() Responser.SaveSettings()
End If End If
End If End If
End Sub End Sub
#End Region #End Region
#Region "Download properties" #Region "Download properties"
<PropertyOption(ControlText:="Request timer", AllowNull:=False), PXML("RequestsWaitTimer"), ControlNumber(6)> <PropertyOption(ControlText:="Request timer", AllowNull:=False), PXML("RequestsWaitTimer"), ControlNumber(20)>
Friend ReadOnly Property RequestsWaitTimer As PropertyValue Friend ReadOnly Property RequestsWaitTimer As PropertyValue
<Provider(NameOf(RequestsWaitTimer), FieldsChecker:=True)> <Provider(NameOf(RequestsWaitTimer), FieldsChecker:=True)>
Private ReadOnly Property RequestsWaitTimerProvider As IFormatProvider Private ReadOnly Property RequestsWaitTimerProvider As IFormatProvider
<PropertyOption(ControlText:="Request timer counter", AllowNull:=False, LeftOffset:=120), PXML("RequestsWaitTimerTaskCount"), ControlNumber(7)> <PropertyOption(ControlText:="Request timer counter", AllowNull:=False, LeftOffset:=120), PXML("RequestsWaitTimerTaskCount"), ControlNumber(21)>
Friend ReadOnly Property RequestsWaitTimerTaskCount As PropertyValue Friend ReadOnly Property RequestsWaitTimerTaskCount As PropertyValue
<Provider(NameOf(RequestsWaitTimerTaskCount), FieldsChecker:=True)> <Provider(NameOf(RequestsWaitTimerTaskCount), FieldsChecker:=True)>
Private ReadOnly Property RequestsWaitTimerTaskCountProvider As IFormatProvider Private ReadOnly Property RequestsWaitTimerTaskCountProvider As IFormatProvider
<PropertyOption(ControlText:="Posts limit timer", AllowNull:=False), PXML("SleepTimerOnPostsLimit"), ControlNumber(8)> <PropertyOption(ControlText:="Posts limit timer", AllowNull:=False), PXML("SleepTimerOnPostsLimit"), ControlNumber(22)>
Friend ReadOnly Property SleepTimerOnPostsLimit As PropertyValue Friend ReadOnly Property SleepTimerOnPostsLimit As PropertyValue
<Provider(NameOf(SleepTimerOnPostsLimit), FieldsChecker:=True)> <Provider(NameOf(SleepTimerOnPostsLimit), FieldsChecker:=True)>
Private ReadOnly Property SleepTimerOnPostsLimitProvider As IFormatProvider Private ReadOnly Property SleepTimerOnPostsLimitProvider As IFormatProvider
<PropertyOption(ControlText:="Get stories"), PXML, ControlNumber(9)> <PropertyOption(ControlText:="Get timeline", ControlToolTip:="Default value for new users"), PXML, ControlNumber(23)>
Friend ReadOnly Property GetTimeline As PropertyValue
<PropertyOption(ControlText:="Get stories", ControlToolTip:="Default value for new users"), PXML, ControlNumber(24)>
Friend ReadOnly Property GetStories As PropertyValue Friend ReadOnly Property GetStories As PropertyValue
<PropertyOption(ControlText:="Get tagged photos"), PXML, ControlNumber(10)> <PropertyOption(ControlText:="Get tagged photos", ControlToolTip:="Default value for new users"), PXML, ControlNumber(25)>
Friend ReadOnly Property GetTagged As PropertyValue Friend ReadOnly Property GetTagged As PropertyValue
<PropertyOption(ControlText:="Tagged notify limit", <PropertyOption(ControlText:="Tagged notify limit",
ControlToolTip:="If the number of tagged posts exceeds this number you will be notified." & vbCr & ControlToolTip:="If the number of tagged posts exceeds this number you will be notified." & vbCr &
"-1 to disable"), PXML, ControlNumber(11)> "-1 to disable"), PXML, ControlNumber(26)>
Friend ReadOnly Property TaggedNotifyLimit As PropertyValue Friend ReadOnly Property TaggedNotifyLimit As PropertyValue
<Provider(NameOf(TaggedNotifyLimit), FieldsChecker:=True)> <Provider(NameOf(TaggedNotifyLimit), FieldsChecker:=True)>
Private ReadOnly Property TaggedNotifyLimitProvider As IFormatProvider Private ReadOnly Property TaggedNotifyLimitProvider As IFormatProvider
#End Region #End Region
#Region "Download ready" #Region "Download ready"
Friend ReadOnly Property DownloadTimeline As XMLValue(Of Boolean) <PropertyOption(ControlText:="Download timeline", ControlToolTip:="Download timeline"), PXML, ControlNumber(10)>
Friend ReadOnly Property DownloadStoriesTagged As XMLValue(Of Boolean) Friend ReadOnly Property DownloadTimeline As PropertyValue
Friend ReadOnly Property DownloadSaved As XMLValue(Of Boolean) <PropertyOption(ControlText:="Download stories", ControlToolTip:="Download stories"), PXML, ControlNumber(11)>
Friend ReadOnly Property DownloadStories As PropertyValue
<PropertyOption(ControlText:="Download tagged", ControlToolTip:="Download tagged posts"), PXML, ControlNumber(12)>
Friend ReadOnly Property DownloadTagged As PropertyValue
#End Region #End Region
#Region "429 bypass" #Region "429 bypass"
Private ReadOnly Property DownloadingErrorDate As XMLValue(Of Date) Private ReadOnly Property DownloadingErrorDate As XMLValue(Of Date)
@@ -202,29 +204,25 @@ Namespace API.Instagram
With Responser With Responser
If .Headers.Count > 0 Then If .Headers.Count > 0 Then
token = .HeadersValue(Header_CSRF_TOKEN) token = .Headers.Value(Header_CSRF_TOKEN)
app_id = .HeadersValue(Header_IG_APP_ID) app_id = .Headers.Value(Header_IG_APP_ID)
www_claim = .HeadersValue(Header_IG_WWW_CLAIM) www_claim = .Headers.Value(Header_IG_WWW_CLAIM)
End If
If Not .Cookies Is Nothing Then
.Cookies.ChangedAllowInternalDrop = False
.Cookies.Changed = False
End If End If
.CookiesExtractMode = Responser.CookiesExtractModes.Response
.CookiesUpdateMode = CookieKeeper.UpdateModes.ReplaceByNameAll
.CookiesExtractedAutoSave = False
End With End With
Dim n() As String = {SettingsCLS.Name_Node_Sites, Site.ToString} Dim n() As String = {SettingsCLS.Name_Node_Sites, Site.ToString}
SavedPostsUserName = New PropertyValue(String.Empty, GetType(String)) HashTagged = New PropertyValue(String.Empty, GetType(String))
Hash = New PropertyValue(String.Empty, GetType(String))
HashSavedPosts = New PropertyValue(String.Empty, GetType(String))
CSRF_TOKEN = New PropertyValue(token, GetType(String), Sub(v) ChangeResponserFields(NameOf(CSRF_TOKEN), v)) CSRF_TOKEN = New PropertyValue(token, GetType(String), Sub(v) ChangeResponserFields(NameOf(CSRF_TOKEN), v))
IG_APP_ID = New PropertyValue(app_id, GetType(String), Sub(v) ChangeResponserFields(NameOf(IG_APP_ID), v)) IG_APP_ID = New PropertyValue(app_id, GetType(String), Sub(v) ChangeResponserFields(NameOf(IG_APP_ID), v))
IG_WWW_CLAIM = New PropertyValue(www_claim, GetType(String), Sub(v) ChangeResponserFields(NameOf(IG_WWW_CLAIM), v)) IG_WWW_CLAIM = New PropertyValue(www_claim, GetType(String), Sub(v) ChangeResponserFields(NameOf(IG_WWW_CLAIM), v))
DownloadTimeline = New XMLValue(Of Boolean)("DownloadTimeline", True, _XML, n) DownloadTimeline = New PropertyValue(True)
DownloadStoriesTagged = New XMLValue(Of Boolean)("DownloadStoriesTagged", True, _XML, n) DownloadStories = New PropertyValue(True)
DownloadSaved = New XMLValue(Of Boolean)("DownloadSaved", True, _XML, n) DownloadTagged = New PropertyValue(False)
RequestsWaitTimer = New PropertyValue(1000) RequestsWaitTimer = New PropertyValue(1000)
RequestsWaitTimerProvider = New TimersChecker(100) RequestsWaitTimerProvider = New TimersChecker(100)
@@ -233,6 +231,7 @@ Namespace API.Instagram
SleepTimerOnPostsLimit = New PropertyValue(60000) SleepTimerOnPostsLimit = New PropertyValue(60000)
SleepTimerOnPostsLimitProvider = New TimersChecker(10000) SleepTimerOnPostsLimitProvider = New TimersChecker(10000)
GetTimeline = New PropertyValue(True)
GetStories = New PropertyValue(False) GetStories = New PropertyValue(False)
GetTagged = New PropertyValue(False) GetTagged = New PropertyValue(False)
TaggedNotifyLimit = New PropertyValue(200) TaggedNotifyLimit = New PropertyValue(200)
@@ -249,90 +248,8 @@ Namespace API.Instagram
UserRegex = RParams.DMS("[htps:/]{7,8}.*?instagram.com/([^/]+)", 1) UserRegex = RParams.DMS("[htps:/]{7,8}.*?instagram.com/([^/]+)", 1)
ImageVideoContains = "instagram.com" ImageVideoContains = "instagram.com"
End Sub End Sub
Private Structure LatestValues
Friend Hash As String
Friend Hash2 As String
Friend Token As String
Friend AppID As String
Friend WwwClaim As String
Friend Exists As Boolean
Friend Sub New(ByVal Source As SiteSettings)
Exists = True
With Source
Hash = AConvert(Of String)(.Hash.Value, String.Empty)
Hash2 = AConvert(Of String)(.HashSavedPosts.Value, String.Empty)
With .Responser
Token = .HeadersValue(Header_CSRF_TOKEN)
AppID = .HeadersValue(Header_IG_APP_ID)
WwwClaim = .HeadersValue(Header_IG_WWW_CLAIM)
End With
End With
End Sub
End Structure
Private LV As LatestValues = Nothing
Private ASO As SettingsExchangeOptions = Nothing
Friend Overrides Sub BeginEdit()
LV = New LatestValues(Me)
ASO = Nothing
MyBase.BeginEdit()
End Sub
Friend Overrides Sub EndEdit()
LV = Nothing
ASO = Nothing
MyBase.EndEdit()
End Sub
Friend Overrides Sub Update()
If LV.Exists Then
Dim __lv As New LatestValues(Me)
If If(Responser.Cookies?.Count, 0) > 0 Then
Dim _cookiesChanged As Boolean = If(Responser.Cookies?.Changed, False)
If Not DownloadTimeline AndAlso (_cookiesChanged Or
(Not LV.Hash = __lv.Hash And Not __lv.Hash.IsEmptyString)) Then DownloadTimeline.Value = True
If Not DownloadSaved AndAlso (_cookiesChanged Or (Not LV.Hash2 = __lv.Hash2 And Not __lv.Hash2.IsEmptyString)) Then DownloadSaved.Value = True
If Not DownloadStoriesTagged AndAlso (
_cookiesChanged Or (
(Not LV.Hash = __lv.Hash Or Not LV.Token = __lv.Token Or Not LV.AppID = __lv.AppID Or Not LV.WwwClaim = __lv.WwwClaim) And
(Not __lv.Hash.IsEmptyString And Not __lv.Token.IsEmptyString And Not __lv.AppID.IsEmptyString And Not __lv.WwwClaim.IsEmptyString)
)) Then DownloadStoriesTagged.Value = True
End If
End If
If ASO.Changed Then
DownloadTimeline.Value = ASO.DownloadTimeline
DownloadStoriesTagged.Value = ASO.DownloadStoriesTagged
DownloadSaved.Value = ASO.DownloadSaved
End If
LV = Nothing
ASO = Nothing
If Not Responser.Cookies Is Nothing Then Responser.Cookies.Changed = False
MyBase.Update()
End Sub
#End Region #End Region
#Region "PropertiesDataChecker" #Region "PropertiesDataChecker"
<PropertiesDataChecker({NameOf(Hash), NameOf(HashSavedPosts)})>
Private Function CheckHashControls(ByVal p As IEnumerable(Of PropertyData)) As Boolean
If p.ListExists(2) Then
Dim h$ = String.Empty
Dim hsp$ = String.Empty
For Each pp As PropertyData In p
Select Case pp.Name
Case NameOf(Hash) : h = AConvert(Of String)(pp.Value, String.Empty)
Case NameOf(HashSavedPosts) : hsp = AConvert(Of String)(pp.Value, String.Empty)
End Select
Next
If h.IsEmptyString And hsp.IsEmptyString Then
Return True
Else
If h = hsp Then
MsgBoxE({"InstaHash for saved posts must be different from InstaHash!", "InstaHash are equal"}, vbCritical)
Return False
Else
Return True
End If
End If
Else
Return False
End If
End Function
<PropertiesDataChecker({NameOf(TaggedNotifyLimit)})> <PropertiesDataChecker({NameOf(TaggedNotifyLimit)})>
Private Function CheckNotifyLimit(ByVal p As IEnumerable(Of PropertyData)) As Boolean Private Function CheckNotifyLimit(ByVal p As IEnumerable(Of PropertyData)) As Boolean
If p.ListExists Then If p.ListExists Then
@@ -351,37 +268,6 @@ Namespace API.Instagram
End If End If
Return False Return False
End Function End Function
<PropertiesDataChecker({NameOf(HashSavedPosts), NameOf(SavedPostsUserName)})>
Private Function CheckSavedOptions(ByVal p As IEnumerable(Of PropertyData)) As Boolean
If p.ListExists Then
Const MsgTitle$ = "Saved posts credentials"
Dim __hash$ = String.Empty
Dim __name$ = String.Empty
Dim _OptionlErrorText$ = $"For download saved posts, you must to set both [{HashSavedPosts_Text}] and [{SavedPostsUserName_Text}]."
For i% = 0 To p.Count - 1
Select Case p(i).Name
Case NameOf(HashSavedPosts) : __hash = p(i).Value
Case NameOf(SavedPostsUserName) : __name = p(i).Value
End Select
Next
If __hash = __name Then
If __hash.IsEmptyString Then
Return True
Else
MsgBoxE({$"[{HashSavedPosts_Text}] and [{SavedPostsUserName_Text}] for saved posts cannot be equal!", MsgTitle}, vbCritical)
End If
Else
If __hash.IsEmptyString Then
MsgBoxE({$"[{HashSavedPosts_Text}] not set.{vbCr}{_OptionlErrorText}", MsgTitle}, vbCritical)
ElseIf __name.IsEmptyString Then
MsgBoxE({$"[{SavedPostsUserName_Text}] not set.{vbCr}{_OptionlErrorText}", MsgTitle}, vbCritical)
Else
Return True
End If
End If
End If
Return False
End Function
#End Region #End Region
#Region "Plugin functions" #Region "Plugin functions"
Friend Overrides Function GetInstance(ByVal What As Download) As IPluginContentProvider Friend Overrides Function GetInstance(ByVal What As Download) As IPluginContentProvider
@@ -389,7 +275,7 @@ Namespace API.Instagram
Case Download.Main : Return New UserData Case Download.Main : Return New UserData
Case Download.SavedPosts Case Download.SavedPosts
Dim u As New UserData Dim u As New UserData
DirectCast(u, UserDataBase).User = New UserInfo With {.Name = CStr(AConvert(Of String)(SavedPostsUserName.Value, String.Empty))} DirectCast(u, UserDataBase).User = New UserInfo With {.Name = Site}
Return u Return u
End Select End Select
Return Nothing Return Nothing
@@ -397,13 +283,7 @@ Namespace API.Instagram
#Region "Downloading" #Region "Downloading"
Friend Property SkipUntilNextSession As Boolean = False Friend Property SkipUntilNextSession As Boolean = False
Friend Overrides Function ReadyToDownload(ByVal What As Download) As Boolean Friend Overrides Function ReadyToDownload(ByVal What As Download) As Boolean
If ActiveJobs < 2 AndAlso Not SkipUntilNextSession AndAlso ReadyForDownload AndAlso BaseAuthExists() Then Return ActiveJobs < 2 AndAlso Not SkipUntilNextSession AndAlso ReadyForDownload AndAlso BaseAuthExists() AndAlso DownloadTimeline.Value
Select Case What
Case Download.Main : Return ACheck(Hash.Value) And DownloadTimeline
Case Download.SavedPosts : Return ACheck(HashSavedPosts.Value) And DownloadSaved
End Select
End If
Return False
End Function End Function
Private ActiveJobs As Integer = 0 Private ActiveJobs As Integer = 0
Private _NextWNM As UserData.WNM = UserData.WNM.Notify Private _NextWNM As UserData.WNM = UserData.WNM.Notify
@@ -432,6 +312,10 @@ Namespace API.Instagram
_NextTagged = .TaggedCheckSession _NextTagged = .TaggedCheckSession
LastDownloadDate.Value = Now LastDownloadDate.Value = Now
LastRequestsCount.Value = .RequestsCount LastRequestsCount.Value = .RequestsCount
_FieldsChangerSuspended = True
IG_WWW_CLAIM.Value = Responser.Headers.Value(Header_IG_WWW_CLAIM)
CSRF_TOKEN.Value = Responser.Headers.Value(Header_CSRF_TOKEN)
_FieldsChangerSuspended = False
End With End With
End Sub End Sub
Friend Overrides Sub DownloadDone(ByVal What As Download) Friend Overrides Sub DownloadDone(ByVal What As Download)
@@ -451,12 +335,14 @@ Namespace API.Instagram
Using f As New OptionsForm(Options) : f.ShowDialog() : End Using Using f As New OptionsForm(Options) : f.ShowDialog() : End Using
End If End If
End Sub End Sub
Friend Overrides Sub OpenSettingsForm() Friend Overrides Function GetUserPostUrl(ByVal User As UserDataBase, ByVal Media As UserMedia) As String
Using f As New AdditionalSettingsForm(If(ASO.Changed, ASO, New SettingsExchangeOptions(Me))) Try
f.ShowDialog() Dim code$ = DirectCast(User, UserData).GetPostCodeById(Media.Post.ID)
If f.DialogResult = DialogResult.OK Then ASO = f.MyParameters If Not code.IsEmptyString Then Return $"https://instagram.com/p/{code}/" Else Return String.Empty
End Using Catch ex As Exception
End Sub Return ErrorsDescriber.Execute(EDP.SendInLog, ex, "Can't open user's post", String.Empty)
End Try
End Function
#End Region #End Region
End Class End Class
End Namespace End Namespace

View File

@@ -9,6 +9,7 @@
Imports System.Net Imports System.Net
Imports System.Threading Imports System.Threading
Imports PersonalUtilities.Functions.XML Imports PersonalUtilities.Functions.XML
Imports PersonalUtilities.Functions.XML.Base
Imports PersonalUtilities.Functions.Messaging Imports PersonalUtilities.Functions.Messaging
Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Functions.RegularExpressions
Imports PersonalUtilities.Tools.Web.Clients Imports PersonalUtilities.Tools.Web.Clients
@@ -20,29 +21,68 @@ Namespace API.Instagram
#Region "XML Names" #Region "XML Names"
Private Const Name_LastCursor As String = "LastCursor" Private Const Name_LastCursor As String = "LastCursor"
Private Const Name_FirstLoadingDone As String = "FirstLoadingDone" Private Const Name_FirstLoadingDone As String = "FirstLoadingDone"
Private Const Name_GetTimeline As String = "GetTimeline"
Private Const Name_GetStories As String = "GetStories" Private Const Name_GetStories As String = "GetStories"
Private Const Name_GetTagged As String = "GetTaggedData" Private Const Name_GetTagged As String = "GetTaggedData"
Private Const Name_TaggedChecked As String = "TaggedChecked" Private Const Name_TaggedChecked As String = "TaggedChecked"
#End Region #End Region
#Region "Declarations" #Region "Declarations"
Private Structure PostKV : Implements IEContainerProvider
Private Const Name_Code As String = "Code"
Private Const Name_Section As String = "Section"
Friend Code As String
Friend ID As String
Friend Section As Sections
Friend Sub New(ByVal _Section As Sections)
Section = _Section
End Sub
Friend Sub New(ByVal _Code As String, ByVal _ID As String, ByVal _Section As Sections)
Code = _Code
ID = _ID
Section = _Section
End Sub
Private Sub New(ByVal e As EContainer)
Code = e.Attribute(Name_Code)
Section = e.Attribute(Name_Section)
ID = e.Value
End Sub
Public Shared Widening Operator CType(ByVal e As EContainer) As PostKV
Return New PostKV(e)
End Operator
Public Overrides Function Equals(ByVal Obj As Object) As Boolean
If Not IsNothing(Obj) AndAlso TypeOf Obj Is PostKV Then
With DirectCast(Obj, PostKV)
Return Code = .Code And ID = .ID And Section = .Section
End With
Else
Return False
End If
End Function
Private Function ToEContainer(Optional ByVal e As ErrorsDescriber = Nothing) As EContainer Implements IEContainerProvider.ToEContainer
Return New EContainer("Post", ID, {New EAttribute(Name_Section, CInt(Section)), New EAttribute(Name_Code, Code)})
End Function
End Structure
Private ReadOnly Property MySiteSettings As SiteSettings Private ReadOnly Property MySiteSettings As SiteSettings
Get Get
Return DirectCast(HOST.Source, SiteSettings) Return DirectCast(HOST.Source, SiteSettings)
End Get End Get
End Property End Property
Private ReadOnly _SavedPostsIDs As New List(Of String) Private ReadOnly PostsKVIDs As List(Of PostKV)
Private ReadOnly PostsToReparse As List(Of PostKV)
Private LastCursor As String = String.Empty Private LastCursor As String = String.Empty
Private FirstLoadingDone As Boolean = False Private FirstLoadingDone As Boolean = False
Friend Property GetTimeline As Boolean = True
Friend Property GetStories As Boolean Friend Property GetStories As Boolean
Friend Property GetTaggedData As Boolean Friend Property GetTaggedData As Boolean
#End Region #End Region
#Region "Exchange options" #Region "Exchange options"
Friend Overrides Function ExchangeOptionsGet() As Object Friend Overrides Function ExchangeOptionsGet() As Object
Return New EditorExchangeOptions(HOST.Source) With {.GetStories = GetStories, .GetTagged = GetTaggedData} Return New EditorExchangeOptions(HOST.Source) With {.GetTimeline = GetTimeline, .GetStories = GetStories, .GetTagged = GetTaggedData}
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 EditorExchangeOptions Then If Not Obj Is Nothing AndAlso TypeOf Obj Is EditorExchangeOptions Then
With DirectCast(Obj, EditorExchangeOptions) With DirectCast(Obj, EditorExchangeOptions)
GetTimeline = .GetTimeline
GetStories = .GetStories GetStories = .GetStories
GetTaggedData = .GetTagged GetTaggedData = .GetTagged
End With End With
@@ -51,6 +91,8 @@ Namespace API.Instagram
#End Region #End Region
#Region "Initializer, loader" #Region "Initializer, loader"
Friend Sub New() Friend Sub New()
PostsKVIDs = New List(Of PostKV)
PostsToReparse = New List(Of PostKV)
End Sub End Sub
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)
If Loading Then If Loading Then
@@ -78,48 +120,128 @@ Namespace API.Instagram
End If End If
Throw New ExitException Throw New ExitException
End Sub End Sub
Friend Sub New()
End Sub
Friend Sub New(ByRef CompleteArg As Boolean)
CompleteArg = True
End Sub
End Class End Class
Private Sub LoadSavePostsKV(ByVal Load As Boolean)
Dim x As XmlFile
Dim f As SFile = MyFilePosts
If Not f.IsEmptyString Then
f.Name &= "_KV"
f.Extension = "xml"
If Load Then
PostsKVIDs.Clear()
x = New XmlFile(f, Protector.Modes.All, False) With {.AllowSameNames = True, .XmlReadOnly = True}
x.LoadData()
If x.Count > 0 Then PostsKVIDs.ListAddList(x, LAP.IgnoreICopier)
x.Dispose()
Else
x = New XmlFile With {.AllowSameNames = True}
x.AddRange(PostsKVIDs)
x.Name = "Posts"
x.Save(f, EDP.SendInLog)
x.Dispose()
End If
End If
End Sub
Private Overloads Function PostKvExists(ByVal pkv As PostKV) As Boolean
Return PostKvExists(pkv.ID, False, pkv.Section) OrElse PostKvExists(pkv.Code, True, pkv.Section)
End Function
Private Overloads Function PostKvExists(ByVal PostCodeId As String, ByVal IsCode As Boolean, ByVal Section As Sections) As Boolean
If Not PostCodeId.IsEmptyString And PostsKVIDs.Count > 0 Then
If PostsKVIDs.FindIndex(Function(p) p.Section = Section AndAlso If(IsCode, p.Code = PostCodeId, p.ID = PostCodeId)) >= 0 Then
Return True
ElseIf Not IsCode Then
Return _TempPostsList.Contains(GetPostIdBySection(PostCodeId, Section)) Or
_TempPostsList.Contains(PostCodeId.Replace($"_{ID}", String.Empty)) Or
_TempPostsList.Contains(GetPostIdBySection(PostCodeId.Replace($"_{ID}", String.Empty), Section))
End If
End If
Return False
End Function
Friend Function GetPostCodeById(ByVal PostID As String) As String
Try
If Not PostID.IsEmptyString Then
Dim f As SFile = MyFilePosts
If Not f.IsEmptyString Then
f.Name &= "_KV"
f.Extension = "xml"
Dim l As List(Of PostKV) = Nothing
Using x As New XmlFile(f, Protector.Modes.All, False) With {.AllowSameNames = True, .XmlReadOnly = True}
x.LoadData()
l.ListAddList(x, LAP.IgnoreICopier)
End Using
Dim code$ = String.Empty
If l.ListExists Then
Dim i% = l.FindIndex(Function(p) p.ID = PostID)
If i >= 0 Then code = l(i).Code
l.Clear()
End If
Return code
End If
End If
Return String.Empty
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.SendInLog, ex, $"{ToStringForLog()}: Cannot find post code by ID ({PostID})", String.Empty)
End Try
End Function
Private Function GetPostIdBySection(ByVal ID As String, ByVal Section As Sections) As String
If Section = Sections.Timeline Then
Return ID
Else
Return $"{Section}_{ID}"
End If
End Function
Private _DownloadingInProgress As Boolean = False
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
Dim s As Sections = Sections.Timeline Dim s As Sections = Sections.Timeline
Dim errorFound As Boolean = False
Try Try
LoadSavePostsKV(True)
_DownloadingInProgress = True
AddHandler Responser.ResponseReceived, AddressOf Responser_ResponseReceived
ThrowAny(Token) ThrowAny(Token)
_InstaHash = String.Empty
HasError = False HasError = False
Dim fc As Boolean = IIf(IsSavedPosts, MySiteSettings.DownloadSaved.Value, MySiteSettings.DownloadTimeline.Value) Dim dt As Boolean = (CBool(MySiteSettings.DownloadTimeline.Value) And GetTimeline) Or IsSavedPosts
If fc And Not LastCursor.IsEmptyString Then If dt And Not LastCursor.IsEmptyString Then
s = IIf(IsSavedPosts, Sections.SavedPosts, Sections.Timeline) s = IIf(IsSavedPosts, Sections.SavedPosts, Sections.Timeline)
DownloadData(LastCursor, s, Token) DownloadData(LastCursor, s, Token)
ThrowAny(Token) ThrowAny(Token)
If Not HasError Then FirstLoadingDone = True If Not HasError Then FirstLoadingDone = True
End If End If
If fc And Not HasError Then If dt And Not HasError Then
s = IIf(IsSavedPosts, Sections.SavedPosts, Sections.Timeline) s = IIf(IsSavedPosts, Sections.SavedPosts, Sections.Timeline)
DownloadData(String.Empty, s, Token) DownloadData(String.Empty, s, Token)
ThrowAny(Token) ThrowAny(Token)
If Not HasError Then FirstLoadingDone = True If Not HasError Then FirstLoadingDone = True
End If End If
If FirstLoadingDone Then LastCursor = String.Empty If FirstLoadingDone Then LastCursor = String.Empty
If IsSavedPosts Then If Not IsSavedPosts AndAlso MySiteSettings.BaseAuthExists() Then
If MySiteSettings.DownloadSaved Then s = Sections.SavedPosts : DownloadPosts(Token) If CBool(MySiteSettings.DownloadStories.Value) And GetStories Then s = Sections.Stories : DownloadData(String.Empty, s, Token)
ElseIf MySiteSettings.BaseAuthExists() Then If CBool(MySiteSettings.DownloadTagged.Value) And ACheck(MySiteSettings.HashTagged.Value) And GetTaggedData Then s = Sections.Tagged : DownloadData(String.Empty, s, Token)
DownloadedTags = 0
If MySiteSettings.DownloadStoriesTagged And GetStories Then s = Sections.Stories : DownloadData(String.Empty, s, Token)
If MySiteSettings.DownloadStoriesTagged And GetTaggedData Then s = Sections.Tagged : DownloadData(String.Empty, s, Token)
End If End If
If WaitNotificationMode = WNM.SkipTemp Or WaitNotificationMode = WNM.SkipCurrent Then WaitNotificationMode = WNM.Notify If WaitNotificationMode = WNM.SkipTemp Or WaitNotificationMode = WNM.SkipCurrent Then WaitNotificationMode = WNM.Notify
Catch eex As ExitException Catch eex As ExitException
Catch ex As Exception Catch ex As Exception
ProcessException(ex, Token, "[API.Instagram.UserData.DownloadDataF]", False, s) errorFound = True
Throw ex
Finally Finally
E560Thrown = False E560Thrown = False
UpdateResponser()
If Not errorFound Then LoadSavePostsKV(False)
End Try End Try
End Sub End Sub
Private _InstaHash As String = String.Empty Private Sub UpdateResponser()
Try
If _DownloadingInProgress AndAlso Not Responser Is Nothing AndAlso Not Responser.Disposed Then
_DownloadingInProgress = False
RemoveHandler Responser.ResponseReceived, AddressOf Responser_ResponseReceived
Declarations.UpdateResponser(Responser, MySiteSettings.Responser)
End If
Catch
End Try
End Sub
Private Sub Responser_ResponseReceived(ByVal Sender As Object, ByVal e As EventArguments.WebDataResponse)
Declarations.UpdateResponser(e, Responser)
End Sub
Private Enum Sections : Timeline : Tagged : Stories : SavedPosts : End Enum Private Enum Sections : Timeline : Tagged : Stories : SavedPosts : End Enum
Private Const StoriesFolder As String = "Stories" Private Const StoriesFolder As String = "Stories"
Private Const TaggedFolder As String = "Tagged" Private Const TaggedFolder As String = "Tagged"
@@ -145,7 +267,7 @@ Namespace API.Instagram
"What do you want to do?", "Waiting for Instagram download...", "What do you want to do?", "Waiting for Instagram download...",
{ {
New MsgBoxButton("Wait") With {.ToolTip = "Wait and ask again when the error is found."}, New MsgBoxButton("Wait") With {.ToolTip = "Wait and ask again when the error is found."},
New MsgBoxButton("Wait (disable current") With {.ToolTip = "Wait and skip future prompts while downloading the current profile."}, New MsgBoxButton("Wait (disable current)") With {.ToolTip = "Wait and skip future prompts while downloading the current profile."},
New MsgBoxButton("Abort") With {.ToolTip = "Abort operation"}, New MsgBoxButton("Abort") With {.ToolTip = "Abort operation"},
New MsgBoxButton("Wait (disable all)") With {.ToolTip = "Wait and skip future prompts while downloading the current session."} New MsgBoxButton("Wait (disable all)") With {.ToolTip = "Wait and skip future prompts while downloading the current session."}
}, },
@@ -180,13 +302,11 @@ Namespace API.Instagram
#Region "Tags" #Region "Tags"
Private TaggedChecked As Boolean = False Private TaggedChecked As Boolean = False
Friend TaggedCheckSession As Boolean = True Friend TaggedCheckSession As Boolean = True
Private DownloadedTags As Integer = 0
Private DownloadTagsLimit As Integer? = Nothing Private DownloadTagsLimit As Integer? = Nothing
Private ReadOnly Property TaggedLimitsNotifications(Optional ByVal v As Integer? = Nothing) As Boolean Private ReadOnly Property TaggedLimitsNotifications(ByVal v As Integer) As Boolean
Get Get
Return Not TaggedChecked AndAlso TaggedCheckSession AndAlso Return Not TaggedChecked AndAlso TaggedCheckSession AndAlso
CInt(MySiteSettings.TaggedNotifyLimit.Value) > 0 AndAlso CInt(MySiteSettings.TaggedNotifyLimit.Value) > 0 AndAlso v > CInt(MySiteSettings.TaggedNotifyLimit.Value)
(Not v.HasValue OrElse v.Value > CInt(MySiteSettings.TaggedNotifyLimit.Value))
End Get End Get
End Property End Property
Private Function SetTagsLimit(ByVal Max As Integer, ByVal p As ANumbers) As DialogResult Private Function SetTagsLimit(ByVal Max As Integer, ByVal p As ANumbers) As DialogResult
@@ -219,8 +339,9 @@ Namespace API.Instagram
End Function End Function
Private Function TaggedContinue(ByVal TaggedCount As Integer) As DialogResult Private Function TaggedContinue(ByVal TaggedCount As Integer) As DialogResult
Dim agi As New ANumbers With {.FormatOptions = ANumbers.Options.GroupIntegral} Dim agi As New ANumbers With {.FormatOptions = ANumbers.Options.GroupIntegral}
Dim msg As New MMessage($"The number of tagged posts by user [{ToString()}] is {TaggedCount.NumToString(agi)}" & vbCr & Dim msg As New MMessage($"The number of already downloaded tagged posts by user [{ToString()}] is {TaggedCount.NumToString(agi)}" & vbCr &
$"This is about {(TaggedCount / 12).RoundUp.NumToString(agi)} requests." & vbCr & "There is currently no way to know how many posts exist." & vbCr &
"One request will be spent per post." & vbCr &
"The tagged data download operation can take a long time.", "The tagged data download operation can take a long time.",
"Too much tagged data", "Too much tagged data",
{ {
@@ -252,40 +373,46 @@ Namespace API.Instagram
Dim URL$ = String.Empty Dim URL$ = String.Empty
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 _DownloadComplete As Boolean = False Dim dValue% = 1
LastCursor = Cursor LastCursor = Cursor
Try Try
Do While Not _DownloadComplete Do While dValue = 1
ThrowAny(Token) ThrowAny(Token)
If Not Ready() Then Thread.Sleep(10000) : ThrowAny(Token) : Continue Do If Not Ready() Then Thread.Sleep(10000) : ThrowAny(Token) : Continue Do
ReconfigureAwaiter() ReconfigureAwaiter()
Try Try
Dim n As EContainer, nn As EContainer, node As EContainer Dim n As EContainer, nn As EContainer
Dim HasNextPage As Boolean = False Dim HasNextPage As Boolean = False
Dim Pinned As Boolean
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 TaggedCount% Dim PostIDKV As PostKV
Dim ENode() As Object = Nothing Dim ENode() As Object = Nothing
NextRequest(True) NextRequest(True)
'Check environment 'Check environment
If Cursor.IsEmptyString And _InstaHash.IsEmptyString Then _ If Not IsSavedPosts Then
_InstaHash = CStr(If(IsSavedPosts, MySiteSettings.HashSavedPosts, MySiteSettings.Hash).Value)
If ID.IsEmptyString Then GetUserId() If ID.IsEmptyString Then GetUserId()
If ID.IsEmptyString Then Throw New ArgumentException("User ID is not detected", "ID") If ID.IsEmptyString Then Throw New ArgumentException("User ID is not detected", "ID")
End If
'Create query 'Create query
Select Case Section Select Case Section
Case Sections.Timeline, Sections.SavedPosts Case Sections.Timeline
URL = $"https://www.instagram.com/api/v1/feed/user/{Name}/username/?count=50" &
If(Cursor.IsEmptyString, String.Empty, $"&max_id={Cursor}")
ENode = Nothing
Case Sections.SavedPosts
SavedPostsDownload(String.Empty, Token)
Exit Sub
Case Sections.Tagged
Dim h$ = AConvert(Of String)(MySiteSettings.HashTagged.Value, String.Empty)
If h.IsEmptyString Then Throw New ExitException
Dim vars$ = "{""id"":" & ID & ",""first"":50,""after"":""" & Cursor & """}" Dim vars$ = "{""id"":" & ID & ",""first"":50,""after"":""" & Cursor & """}"
vars = SymbolsConverter.ASCII.EncodeSymbolsOnly(vars) vars = SymbolsConverter.ASCII.EncodeSymbolsOnly(vars)
URL = $"https://www.instagram.com/graphql/query/?query_hash={_InstaHash}&variables={vars}" URL = $"https://www.instagram.com/graphql/query/?query_hash={h}&variables={vars}"
ENode = {"data", "user", 0} ENode = {"data", "user", 0}
Case Sections.Tagged
URL = $"https://i.instagram.com/api/v1/usertags/{ID}/feed/?count=50&max_id={Cursor}"
ENode = {"items"}
SpecFolder = TaggedFolder SpecFolder = TaggedFolder
Case Sections.Stories Case Sections.Stories
If Not StoriesRequested Then If Not StoriesRequested Then
@@ -303,7 +430,7 @@ Namespace API.Instagram
If StoriesList.ListExists Then If StoriesList.ListExists Then
Continue Do Continue Do
Else Else
Throw New ExitException(_DownloadComplete) Throw New ExitException
End If End If
End Select End Select
@@ -316,78 +443,73 @@ Namespace API.Instagram
'Parsing 'Parsing
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
Using j As EContainer = JsonDocument.Parse(r).XmlIfNothing Using j As EContainer = JsonDocument.Parse(r).XmlIfNothing
n = j.ItemF(ENode).XmlIfNothing n = If(ENode Is Nothing, j, j.ItemF(ENode)).XmlIfNothing
If n.Count > 0 Then If n.Count > 0 Then
Select Case Section Select Case Section
Case Sections.Timeline, Sections.SavedPosts Case Sections.Timeline
If n.Contains("page_info") Then With n
With n("page_info") HasNextPage = .Value("more_available").FromXML(Of Boolean)(False)
EndCursor = .Value("next_max_id")
If If(.Item("items")?.Count, 0) > 0 Then
If Not DefaultParser(.Item("items"), Section, Token) Then Throw New ExitException
Else
HasNextPage = False
End If
End With
Case Sections.Tagged
With n
If .Contains("page_info") Then
With .Item("page_info")
HasNextPage = .Value("has_next_page").FromXML(Of Boolean)(False) HasNextPage = .Value("has_next_page").FromXML(Of Boolean)(False)
EndCursor = .Value("end_cursor") EndCursor = .Value("end_cursor")
End With End With
End If
n = n("edges").XmlIfNothing
If n.Count > 0 Then
For Each nn In n
ThrowAny(Token)
node = nn(0).XmlIfNothing
If IsSavedPosts Then
PostID = node.Value("shortcode")
If Not PostID.IsEmptyString AndAlso _TempPostsList.Contains(PostID) Then Throw New ExitException(_DownloadComplete)
End If
PostID = node.Value("id")
Pinned = CBool(If(node("pinned_for_users")?.Count, 0))
If Not PostID.IsEmptyString And _TempPostsList.Contains(PostID) And Not Pinned Then Throw New ExitException(_DownloadComplete)
_TempPostsList.Add(PostID)
PostDate = node.Value("taken_at_timestamp")
If IsSavedPosts Then
_SavedPostsIDs.Add(PostID)
Else Else
Select Case CheckDatesLimit(PostDate, DateProvider) HasNextPage = False
Case DateResult.Skip : Continue For End If
Case DateResult.Exit : If Not Pinned Then Throw New ExitException(_DownloadComplete) If If(.Item("edges")?.Count, 0) > 0 Then
End Select For Each nn In .Item("edges")
ObtainMedia(node, PostID, PostDate, SpecFolder) PostIDKV = New PostKV(Section)
If nn.Count > 0 AndAlso nn(0).Count > 0 Then
With nn(0)
PostIDKV = New PostKV(.Value("shortcode"), .Value("id"), Section)
If PostKvExists(PostIDKV) Then
Throw New ExitException
Else
If Not DownloadTagsLimit.HasValue OrElse PostsToReparse.Count + 1 < DownloadTagsLimit.Value Then
_TempPostsList.Add(GetPostIdBySection(PostIDKV.ID, Section))
PostsKVIDs.ListAddValue(PostIDKV, LAP.NotContainsOnly)
PostsToReparse.ListAddValue(PostIDKV, LNC)
ElseIf DownloadTagsLimit.HasValue OrElse PostsToReparse.Count + 1 >= DownloadTagsLimit.Value Then
Throw New ExitException
End If
End If
End With
End If End If
Next Next
Else
HasNextPage = False
End If End If
Case Sections.Tagged End With
HasNextPage = j.Value("more_available").FromXML(Of Boolean)(False) If TaggedLimitsNotifications(PostsToReparse.Count) Then
EndCursor = j.Value("next_max_id")
For Each nn In n
PostID = $"Tagged_{nn.Value("id")}"
If Not PostID.IsEmptyString And _TempPostsList.Contains(PostID) Then Throw New ExitException(_DownloadComplete)
_TempPostsList.Add(PostID)
ObtainMedia2(nn, PostID, SpecFolder)
DownloadedTags += 1
If DownloadTagsLimit.HasValue AndAlso DownloadedTags >= DownloadTagsLimit.Value Then Throw New ExitException(_DownloadComplete)
Next
If TaggedLimitsNotifications Then
TaggedCount = j.Value("total_count").FromXML(Of Integer)(0)
TaggedChecked = True TaggedChecked = True
If TaggedLimitsNotifications(TaggedCount) AndAlso If TaggedContinue(PostsToReparse.Count) = DialogResult.Cancel Then Throw New ExitException
TaggedContinue(TaggedCount) = DialogResult.Cancel Then Throw New ExitException(_DownloadComplete)
End If End If
End Select End Select
Else Else
If j.Value("status") = "ok" AndAlso j({"data", "user"}).XmlIfNothing.Count = 0 AndAlso If j.Value("status") = "ok" AndAlso If(j("items")?.Count, 0) = 0 AndAlso
_TempMediaList.Count = 0 AndAlso Section = Sections.Timeline Then _ _TempMediaList.Count = 0 AndAlso Section = Sections.Timeline Then _
UserExists = False : Throw New ExitException(_DownloadComplete) UserExists = False : Throw New ExitException
End If End If
End Using End Using
Else Else
Throw New ExitException(_DownloadComplete) Throw New ExitException
End If End If
_DownloadComplete = True dValue = 0
If HasNextPage And Not EndCursor.IsEmptyString Then DownloadData(EndCursor, Section, Token) If HasNextPage And Not EndCursor.IsEmptyString Then DownloadData(EndCursor, Section, Token)
Catch eex As ExitException Catch eex As ExitException
Throw eex Throw eex
Catch oex As OperationCanceledException When Token.IsCancellationRequested
Exit Do
Catch dex As ObjectDisposedException When Disposed
Exit Do
Catch ex As Exception Catch ex As Exception
If DownloadingException(ex, $"data downloading error [{URL}]", False, Section) = 1 Then Continue Do Else Exit Do dValue = ProcessException(ex, Token, $"data downloading error [{URL}]",, Section, False)
End Try End Try
Loop Loop
Catch eex2 As ExitException Catch eex2 As ExitException
@@ -400,10 +522,10 @@ Namespace API.Instagram
End Sub End Sub
Private Sub DownloadPosts(ByVal Token As CancellationToken) Private Sub DownloadPosts(ByVal Token As CancellationToken)
Dim URL$ = String.Empty Dim URL$ = String.Empty
Dim _DownloadComplete As Boolean = False Dim dValue% = 1
Dim _Index% = 0 Dim _Index% = 0
Try Try
Do While Not _DownloadComplete Do While dValue = 1
ThrowAny(Token) ThrowAny(Token)
If Not Ready() Then Thread.Sleep(10000) : ThrowAny(Token) : Continue Do If Not Ready() Then Thread.Sleep(10000) : ThrowAny(Token) : Continue Do
ReconfigureAwaiter() ReconfigureAwaiter()
@@ -411,13 +533,11 @@ Namespace API.Instagram
Try Try
Dim r$ Dim r$
Dim j As EContainer, jj As EContainer Dim j As EContainer, jj As EContainer
Dim _MediaObtained As Boolean If PostsToReparse.Count > 0 And _Index <= PostsToReparse.Count - 1 Then
If _SavedPostsIDs.Count > 0 And _Index <= _SavedPostsIDs.Count - 1 Then
Dim e As New ErrorsDescriber(EDP.ThrowException) Dim e As New ErrorsDescriber(EDP.ThrowException)
For i% = _Index To _SavedPostsIDs.Count - 1 For i% = _Index To PostsToReparse.Count - 1
_Index = i _Index = i
'URL = $"https://instagram.com/p/{_SavedPostsIDs(i)}/?__a=1" URL = $"https://www.instagram.com/api/v1/media/{PostsToReparse(i).ID}/info/"
URL = $"https://i.instagram.com/api/v1/media/{_SavedPostsIDs(i)}/info/"
ThrowAny(Token) ThrowAny(Token)
NextRequest(((i + 1) Mod 5) = 0) NextRequest(((i + 1) Mod 5) = 0)
ThrowAny(Token) ThrowAny(Token)
@@ -427,17 +547,9 @@ Namespace API.Instagram
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
j = JsonDocument.Parse(r) j = JsonDocument.Parse(r)
If Not j Is Nothing Then If Not j Is Nothing Then
_MediaObtained = False If If(j("items")?.Count, 0) > 0 Then
If j.Contains({"graphql", "shortcode_media"}) Then
With j({"graphql", "shortcode_media"}).XmlIfNothing
If .Count > 0 Then ObtainMedia(.Self, _SavedPostsIDs(i), String.Empty, String.Empty) : _MediaObtained = True
End With
End If
If Not _MediaObtained AndAlso j.Contains("items") Then
With j("items") With j("items")
If .Count > 0 Then For Each jj In .Self : ObtainMedia(jj, PostsToReparse(i).ID) : Next
For Each jj In .Self : ObtainMedia2(jj, _SavedPostsIDs(i)) : Next
End If
End With End With
End If End If
j.Dispose() j.Dispose()
@@ -445,24 +557,79 @@ Namespace API.Instagram
End If End If
Next Next
End If End If
_DownloadComplete = True dValue = 0
Catch eex As ExitException Catch eex As ExitException
Throw eex Throw eex
Catch oex As OperationCanceledException When Token.IsCancellationRequested
Exit Do
Catch dex As ObjectDisposedException When Disposed
Exit Do
Catch ex As Exception Catch ex As Exception
If DownloadingException(ex, $"downloading saved posts error [{URL}]", False, Sections.SavedPosts) = 1 Then Continue Do Else Exit Do dValue = ProcessException(ex, Token, $"downloading posts error [{URL}]",, Sections.Tagged, False)
End Try End Try
Loop Loop
Catch eex2 As ExitException Catch eex2 As ExitException
Catch oex2 As OperationCanceledException When Token.IsCancellationRequested Or oex2.HelpLink = InstAborted Catch oex2 As OperationCanceledException When Token.IsCancellationRequested Or oex2.HelpLink = InstAborted
If oex2.HelpLink = InstAborted Then HasError = True If oex2.HelpLink = InstAborted Then HasError = True
Catch DoEx As Exception Catch DoEx As Exception
ProcessException(DoEx, Token, $"downloading saved posts error [{URL}]",, Sections.SavedPosts) ProcessException(DoEx, Token, $"downloading posts error [{URL}]",, Sections.Tagged)
End Try End Try
End Sub End Sub
Private Sub SavedPostsDownload(ByVal Cursor As String, ByVal Token As CancellationToken)
Dim URL$ = $"https://www.instagram.com/api/v1/feed/saved/posts/?max_id={Cursor}"
Dim HasNextPage As Boolean = False
Dim NextCursor$ = String.Empty
ThrowAny(Token)
Dim r$ = Responser.GetResponse(URL)
Dim nodes As IEnumerable(Of EContainer) = Nothing
If Not r.IsEmptyString Then
Using e As EContainer = JsonDocument.Parse(r)
If If(e?.Count, 0) > 0 Then
With e
HasNextPage = .Value("more_available").FromXML(Of Boolean)(False)
NextCursor = .Value("next_max_id")
If .Contains("items") Then nodes = (From ee As EContainer In .Item("items") Where ee.Count > 0 Select ee(0))
End With
If nodes.ListExists Then
DefaultParser(nodes, Sections.SavedPosts, Token)
If HasNextPage And Not NextCursor.IsEmptyString Then SavedPostsDownload(NextCursor, Token)
End If
End If
End Using
End If
End Sub
Private Function DefaultParser(ByVal Items As IEnumerable(Of EContainer), ByVal Section As Sections, ByVal Token As CancellationToken,
Optional ByVal SpecFolder As String = Nothing) As Boolean
ThrowAny(Token)
If Items.Count > 0 Then
Dim PostIDKV As PostKV
Dim Pinned As Boolean
Dim PostDate$
If SpecFolder.IsEmptyString Then
Select Case Section
Case Sections.Tagged : SpecFolder = TaggedFolder
Case Sections.Stories : SpecFolder = StoriesFolder
Case Else : SpecFolder = String.Empty
End Select
End If
For Each nn In Items
With nn
PostIDKV = New PostKV(.Value("code"), .Value("id"), Section)
Pinned = .Contains("timeline_pinned_user_ids")
If PostKvExists(PostIDKV) And Not Pinned Then Return False
_TempPostsList.Add(PostIDKV.ID)
PostsKVIDs.ListAddValue(PostIDKV, LAP.NotContainsOnly)
PostDate = .Value("taken_at")
If Not IsSavedPosts Then
Select Case CheckDatesLimit(PostDate, DateProvider)
Case DateResult.Skip : Continue For
Case DateResult.Exit : If Not Pinned Then Return False
End Select
End If
ObtainMedia(.Self, PostIDKV.ID, SpecFolder, PostDate)
End With
Next
Return True
Else
Return False
End If
End Function
#End Region #End Region
#Region "Code ID converters" #Region "Code ID converters"
Private Shared Function CodeToID(ByVal Code As String) As String Private Shared Function CodeToID(ByVal Code As String) As String
@@ -485,25 +652,7 @@ Namespace API.Instagram
End Function End Function
#End Region #End Region
#Region "Obtain Media" #Region "Obtain Media"
Private Sub ObtainMedia(ByVal node As EContainer, ByVal PostID As String, ByVal PostDate As String, ByVal SpecFolder As String) Private Sub ObtainMedia(ByVal n As EContainer, ByVal PostID As String, Optional ByVal SpecialFolder As String = Nothing,
Dim CreateMedia As Action(Of EContainer) =
Sub(ByVal e As EContainer)
Dim t As UTypes = If(e.Value("is_video").FromXML(Of Boolean)(False), UTypes.Video, UTypes.Picture)
Dim tmpValue$
If t = UTypes.Picture Then
tmpValue = e.Value("display_url")
Else
tmpValue = e.Value("video_url")
End If
If Not tmpValue.IsEmptyString Then _TempMediaList.ListAddValue(MediaFromData(t, tmpValue, PostID, PostDate, SpecFolder), LNC)
End Sub
If node.Contains({"edge_sidecar_to_children", "edges"}) Then
For Each edge As EContainer In node({"edge_sidecar_to_children", "edges"}) : CreateMedia(edge("node").XmlIfNothing) : Next
Else
CreateMedia(node)
End If
End Sub
Private Sub ObtainMedia2(ByVal n As EContainer, ByVal PostID As String, Optional ByVal SpecialFolder As String = Nothing,
Optional ByVal DateObj As String = Nothing) Optional ByVal DateObj As String = Nothing)
Try Try
Dim img As Predicate(Of EContainer) = Function(_img) Not _img.Name.IsEmptyString AndAlso _img.Name.StartsWith("image_versions") AndAlso _img.Count > 0 Dim img As Predicate(Of EContainer) = Function(_img) Not _img.Name.IsEmptyString AndAlso _img.Name.StartsWith("image_versions") AndAlso _img.Count > 0
@@ -575,7 +724,7 @@ Namespace API.Instagram
DateObj = mDate(n) DateObj = mDate(n)
With n("carousel_media").XmlIfNothing With n("carousel_media").XmlIfNothing
If .Count > 0 Then If .Count > 0 Then
For Each d In .Self : ObtainMedia2(d, PostID, SpecialFolder, DateObj) : Next For Each d In .Self : ObtainMedia(d, PostID, SpecialFolder, DateObj) : Next
End If End If
End With End With
End Select End Select
@@ -588,22 +737,6 @@ Namespace API.Instagram
End Sub End Sub
#End Region #End Region
#Region "GetUserId" #Region "GetUserId"
<Obsolete> Private Sub GetUserId_Old()
Try
Dim r$ = Responser.GetResponse($"https://www.instagram.com/{Name}/?__a=1",, EDP.ThrowException)
If Not r.IsEmptyString Then
Using j As EContainer = JsonDocument.Parse(r).XmlIfNothing
ID = j({"graphql", "user"}, "id").XmlIfNothingValue
End Using
End If
Catch ex As Exception
If Responser.StatusCode = HttpStatusCode.NotFound Or Responser.StatusCode = HttpStatusCode.BadRequest Then
Throw ex
Else
LogError(ex, "get Instagram user id")
End If
End Try
End Sub
Private Sub GetUserId() Private Sub GetUserId()
Try Try
Dim r$ = Responser.GetResponse($"https://i.instagram.com/api/v1/users/web_profile_info/?username={Name}",, EDP.ThrowException) Dim r$ = Responser.GetResponse($"https://i.instagram.com/api/v1/users/web_profile_info/?username={Name}",, EDP.ThrowException)
@@ -652,7 +785,7 @@ Namespace API.Instagram
pid = storyID & s.Value("id") pid = storyID & s.Value("id")
If Not _TempPostsList.Contains(pid) Then If Not _TempPostsList.Contains(pid) Then
ThrowAny(Token) ThrowAny(Token)
ObtainMedia2(s, pid, sFolder) ObtainMedia(s, pid, sFolder)
_TempPostsList.Add(pid) _TempPostsList.Add(pid)
End If End If
Next Next
@@ -731,8 +864,7 @@ Namespace API.Instagram
Dim s As Sections = DirectCast(Section, Sections) Dim s As Sections = DirectCast(Section, Sections)
Select Case s Select Case s
Case Sections.Timeline : MySiteSettings.DownloadTimeline.Value = False Case Sections.Timeline : MySiteSettings.DownloadTimeline.Value = False
Case Sections.SavedPosts : MySiteSettings.DownloadSaved.Value = False Case Else : MySiteSettings.DownloadTagged.Value = False
Case Else : MySiteSettings.DownloadStoriesTagged.Value = False
End Select End Select
MyMainLOG = $"[{s}] downloading is disabled until you update your credentials".ToUpper MyMainLOG = $"[{s}] downloading is disabled until you update your credentials".ToUpper
End If End If
@@ -750,7 +882,7 @@ Namespace API.Instagram
End Function End Function
#End Region #End Region
#Region "Standalone downloader" #Region "Standalone downloader"
Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal r As Response) As IEnumerable(Of UserMedia) Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal r As Responser) As IEnumerable(Of UserMedia)
Try Try
If Not URL.IsEmptyString AndAlso URL.Contains("instagram.com") Then If Not URL.IsEmptyString AndAlso URL.Contains("instagram.com") Then
Dim PID$ = RegexReplace(URL, RParams.DMS(".*?instagram.com/p/([_\w\d]+)", 1)) Dim PID$ = RegexReplace(URL, RParams.DMS(".*?instagram.com/p/([_\w\d]+)", 1))
@@ -758,9 +890,9 @@ Namespace API.Instagram
If Not PID.IsEmptyString Then If Not PID.IsEmptyString Then
Using t As New UserData Using t As New UserData
t.SetEnvironment(Settings(InstagramSiteKey), Nothing, False, False) t.SetEnvironment(Settings(InstagramSiteKey), Nothing, False, False)
t.Responser = New Response t.Responser = New Responser
t.Responser.Copy(r) t.Responser.Copy(r)
t._SavedPostsIDs.Add(PID) t.PostsToReparse.Add(New PostKV With {.ID = PID})
t.DownloadPosts(Nothing) t.DownloadPosts(Nothing)
Return ListAddList(Nothing, t._TempMediaList) Return ListAddList(Nothing, t._TempMediaList)
End Using End Using
@@ -774,7 +906,13 @@ Namespace API.Instagram
#End Region #End Region
#Region "IDisposable Support" #Region "IDisposable Support"
Protected Overrides Sub Dispose(ByVal disposing As Boolean) Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If Not disposedValue And disposing Then _SavedPostsIDs.Clear() If Not disposedValue Then
UpdateResponser()
If disposing Then
PostsKVIDs.Clear()
PostsToReparse.Clear()
End If
End If
MyBase.Dispose(disposing) MyBase.Dispose(disposing)
End Sub End Sub
#End Region #End Region

View File

@@ -88,7 +88,7 @@ Namespace API.LPSG
End If End If
End Sub End Sub
Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken) Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
With Responser : .Mode = Response.Modes.WebClient : .ResetStatus() : End With With Responser : .Mode = Responser.Modes.WebClient : .ResetStatus() : End With
UseResponserClient = True UseResponserClient = True
DownloadContentDefault(Token) DownloadContentDefault(Token)
End Sub End Sub

View File

@@ -14,7 +14,7 @@ Namespace API.PornHub
Friend NotInheritable Class M3U8 Friend NotInheritable Class M3U8
Private Sub New() Private Sub New()
End Sub End Sub
Private Shared Function GetUrlsList(ByVal URL As String, ByVal Responser As Response) As List(Of String) Private Shared Function GetUrlsList(ByVal URL As String, ByVal Responser As Responser) As List(Of String)
Dim appender$ = RegexReplace(URL, Regex_M3U8_FileUrl) Dim appender$ = RegexReplace(URL, Regex_M3U8_FileUrl)
Dim r$ = Responser.GetResponse(URL) Dim r$ = Responser.GetResponse(URL)
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
@@ -35,7 +35,7 @@ Namespace API.PornHub
End If End If
Return Nothing Return Nothing
End Function End Function
Friend Shared Function Download(ByVal URL As String, ByVal Responser As Response, ByVal Destination As SFile) As SFile Friend Shared Function Download(ByVal URL As String, ByVal Responser As Responser, ByVal Destination As SFile) As SFile
Return M3U8Base.Download(GetUrlsList(URL, Responser), Destination, Responser) Return M3U8Base.Download(GetUrlsList(URL, Responser), Destination, Responser)
End Function End Function
End Class End Class

View File

@@ -69,7 +69,7 @@ Namespace API.PornHub
End Function End Function
Friend Overrides Function GetSpecialData(ByVal URL As String, ByVal Path As String, ByVal AskForPath As Boolean) As IEnumerable Friend Overrides Function GetSpecialData(ByVal URL As String, ByVal Path As String, ByVal AskForPath As Boolean) As IEnumerable
If Available(ISiteSettings.Download.Main, True) Then If Available(ISiteSettings.Download.Main, True) Then
Using resp As Response = Responser.Copy Using resp As Responser = Responser.Copy
Dim spf$ = String.Empty Dim spf$ = String.Empty
Dim f As SFile = GetSpecialDataFile(Path, AskForPath, spf) Dim f As SFile = GetSpecialDataFile(Path, AskForPath, spf)
Dim m As UserMedia = UserData.GetVideoInfo(URL, resp, f) Dim m As UserMedia = UserData.GetVideoInfo(URL, resp, f)
@@ -105,17 +105,14 @@ Namespace API.PornHub
With DirectCast(User, UserData) : Return String.Format(UrlPatternUser, .PersonType, .NameTrue) : End With With DirectCast(User, UserData) : Return String.Format(UrlPatternUser, .PersonType, .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
'TODELETE: remove comment Return Media.URL_BASE
Return Media.URL_BASE '$"https://www.pornhub.com/view_video.php?viewkey={Media.Post.ID}"
End Function End Function
#End Region #End Region
#Region "User options" #Region "User options"
Friend Overrides Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean) Friend Overrides Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean)
Dim e As UserExchangeOptions = Nothing If Options Is Nothing OrElse Not TypeOf Options Is UserExchangeOptions Then Options = New UserExchangeOptions(Me)
If Not Options Is Nothing AndAlso TypeOf Options Is UserExchangeOptions Then e = Options
If e Is Nothing Then e = New UserExchangeOptions(Me)
If OpenForm Then If OpenForm Then
Using f As New OptionsForm(e) : f.ShowDialog() : End Using Using f As New OptionsForm(Options) : f.ShowDialog() : End Using
End If End If
End Sub End Sub
#End Region #End Region

View File

@@ -178,7 +178,7 @@ Namespace API.PornHub
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
Try Try
Responser.ResetStatus() Responser.ResetStatus()
If PersonType = PersonTypeUser Then Responser.Mode = Response.Modes.Curl If PersonType = PersonTypeUser Then Responser.Mode = Responser.Modes.Curl
If IsSavedPosts Then VideoPageModel = VideoPageModels.Favorite If IsSavedPosts Then VideoPageModel = VideoPageModels.Favorite
@@ -187,7 +187,7 @@ Namespace API.PornHub
Dim __videoDone As Boolean = False Dim __videoDone As Boolean = False
Dim d% Dim d%
If DownloadVideos Then If DownloadVideos Then
If PersonType = PersonTypeUser Then Responser.Mode = Response.Modes.Curl : Responser.Method = "POST" If PersonType = PersonTypeUser Then Responser.Mode = Responser.Modes.Curl : Responser.Method = "POST"
If VideoPageModel = VideoPageModels.Undefined Then If VideoPageModel = VideoPageModels.Undefined Then
__continue = False __continue = False
d = DownloadUserVideos(page, Token) d = DownloadUserVideos(page, Token)
@@ -216,7 +216,7 @@ Namespace API.PornHub
If DownloadGifs And Not IsSavedPosts Then DownloadUserGifs(Token) If DownloadGifs And Not IsSavedPosts Then DownloadUserGifs(Token)
If DownloadImages Then DownloadUserPhotos(Token) If DownloadImages Then DownloadUserPhotos(Token)
Finally Finally
Responser.Mode = Response.Modes.Default Responser.Mode = Responser.Modes.Default
Responser.Method = "GET" Responser.Method = "GET"
End Try End Try
End Sub End Sub
@@ -346,12 +346,12 @@ Namespace API.PornHub
If PhotoPageModel = PhotoPageModels.Undefined Then If PhotoPageModel = PhotoPageModels.Undefined Then
If DownloadUserPhotos_ModelHub(Token) Then PhotoPageModel = PhotoPageModels.ModelHubPage If DownloadUserPhotos_ModelHub(Token) Then PhotoPageModel = PhotoPageModels.ModelHubPage
ThrowAny(Token) ThrowAny(Token)
If PhotoPageModel = PhotoPageModels.Undefined AndAlso DownloadPhotoOnlyFromModelHub AndAlso If PhotoPageModel = PhotoPageModels.Undefined AndAlso Not DownloadPhotoOnlyFromModelHub AndAlso
DownloadUserPhotos_PornHub(Token) Then PhotoPageModel = PhotoPageModels.PornHubPage DownloadUserPhotos_PornHub(Token) Then PhotoPageModel = PhotoPageModels.PornHubPage
Else Else
Select Case PhotoPageModel Select Case PhotoPageModel
Case PhotoPageModels.ModelHubPage : DownloadUserPhotos_ModelHub(Token) Case PhotoPageModels.ModelHubPage : DownloadUserPhotos_ModelHub(Token)
Case PhotoPageModels.PornHubPage : If DownloadPhotoOnlyFromModelHub Then DownloadUserPhotos_PornHub(Token) Case PhotoPageModels.PornHubPage : If Not DownloadPhotoOnlyFromModelHub Then DownloadUserPhotos_PornHub(Token)
End Select End Select
End If End If
ElseIf Not DownloadPhotoOnlyFromModelHub Then ElseIf Not DownloadPhotoOnlyFromModelHub Then
@@ -359,7 +359,7 @@ Namespace API.PornHub
End If End If
ThrowAny(Token) ThrowAny(Token)
Catch ex As Exception Catch ex As Exception
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 Private Function DownloadUserPhotos_ModelHub(ByVal Token As CancellationToken) As Boolean
@@ -624,7 +624,7 @@ Namespace API.PornHub
End Function End Function
#End Region #End Region
#Region "Standalone downloader" #Region "Standalone downloader"
Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal Responser As Response, ByVal Destination As SFile) As UserMedia Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal Responser As Responser, ByVal Destination As SFile) As UserMedia
Try Try
Dim r$ = Responser.Curl(URL) Dim r$ = Responser.Curl(URL)
If Not r.IsEmptyString Then If Not r.IsEmptyString Then

View File

@@ -136,7 +136,7 @@ Namespace API.Reddit
_CrossPosts.Clear() _CrossPosts.Clear()
If Not IsSavedPosts AndAlso (IsChannel AndAlso Not ChannelInfo Is Nothing) Then If Not IsSavedPosts AndAlso (IsChannel AndAlso Not ChannelInfo Is Nothing) Then
If Not Responser Is Nothing Then Responser.Dispose() If Not Responser Is Nothing Then Responser.Dispose()
Responser = New Response Responser = New Responser
Responser.Copy(MySiteSettings.Responser) Responser.Copy(MySiteSettings.Responser)
ChannelPostsNames.ListAddList(ChannelInfo.PostsAll.Select(Function(p) p.ID), LNC) ChannelPostsNames.ListAddList(ChannelInfo.PostsAll.Select(Function(p) p.ID), LNC)
If Not ViewMode = CView.New Then ChannelPostsNames.ListAddList(ChannelInfo.PostsNames, LNC) If Not ViewMode = CView.New Then ChannelPostsNames.ListAddList(ChannelInfo.PostsNames, LNC)
@@ -524,7 +524,7 @@ Namespace API.Reddit
End Try End Try
End Function End Function
Protected Overrides Sub ReparseVideo(ByVal Token As CancellationToken) Protected Overrides Sub ReparseVideo(ByVal Token As CancellationToken)
Dim RedGifsResponser As Response = Nothing Dim RedGifsResponser As Responser = Nothing
Try Try
ThrowAny(Token) ThrowAny(Token)
Const v2 As UTypes = UTypes.VideoPre + UTypes.m3u8 Const v2 As UTypes = UTypes.VideoPre + UTypes.m3u8
@@ -581,7 +581,7 @@ Namespace API.Reddit
End Sub End Sub
Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken) Protected Overrides Sub ReparseMissing(ByVal Token As CancellationToken)
Dim rList As New List(Of Integer) Dim rList As New List(Of Integer)
Dim RedGifsResponser As Response = Nothing Dim RedGifsResponser As Responser = Nothing
Try Try
If Not ChannelInfo Is Nothing Or SaveToCache Then Exit Sub If Not ChannelInfo Is Nothing Or SaveToCache Then Exit Sub
If ContentMissingExists Then If ContentMissingExists Then
@@ -658,11 +658,11 @@ Namespace API.Reddit
Public Overrides Sub Perform(Optional ByVal Value As Double = 1) Public Overrides Sub Perform(Optional ByVal Value As Double = 1)
End Sub End Sub
End Class End Class
Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal resp As Response, ByVal f As SFile, ByVal SpecialFolder As String) As IEnumerable(Of UserMedia) Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal resp As Responser, ByVal f As SFile, ByVal SpecialFolder As String) As IEnumerable(Of UserMedia)
Try Try
If Not URL.IsEmptyString Then If Not URL.IsEmptyString Then
Using r As New UserData Using r As New UserData
r.Responser = New Response r.Responser = New Responser
r.Responser.Copy(resp) r.Responser.Copy(resp)
r.ParsePost(URL) r.ParsePost(URL)
If r._TempMediaList.Count > 0 Then If r._TempMediaList.Count > 0 Then
@@ -713,7 +713,7 @@ Namespace API.Reddit
End Function End Function
#End Region #End Region
Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken) Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
Dim RedGifsResponser As Response = Nothing Dim RedGifsResponser As Responser = Nothing
Try Try
Const _RFN$ = "RedditVideo" Const _RFN$ = "RedditVideo"
Const RFN$ = _RFN & "{0}" Const RFN$ = _RFN & "{0}"

View File

@@ -33,7 +33,6 @@ Namespace API.RedGifs
<PropertyOption(AllowNull:=False, ControlText:="Token", ControlToolTip:="Bearer token")> <PropertyOption(AllowNull:=False, ControlText:="Token", ControlToolTip:="Bearer token")>
Friend Property Token As PropertyValue Friend Property Token As PropertyValue
<PXML> Friend Property TokenLastDateUpdated As PropertyValue <PXML> Friend Property TokenLastDateUpdated As PropertyValue
<DoNotUse> Friend ReadOnly Property NoCredentialsResponser As Response
Private Const TokenName As String = "authorization" Private Const TokenName As String = "authorization"
#End Region #End Region
#Region "Initializer" #Region "Initializer"
@@ -41,23 +40,11 @@ Namespace API.RedGifs
MyBase.New(RedGifsSite, "redgifs.com") MyBase.New(RedGifsSite, "redgifs.com")
Dim t$ = String.Empty Dim t$ = String.Empty
With Responser With Responser
Dim b As Boolean = Not .Mode = Response.Modes.WebClient Dim b As Boolean = Not .Mode = Responser.Modes.WebClient
.Mode = Response.Modes.WebClient .Mode = Responser.Modes.WebClient
t = .HeadersValue(TokenName) t = .Headers.Value(TokenName)
If b Then .SaveSettings() If b Then .SaveSettings()
End With End With
NoCredentialsResponser = New Response($"{SettingsFolderName}\Responser_{RedGifsSite}_NC.xml") With {
.CookiesEncryptKey = SettingsCLS.CookieEncryptKey,
.CookiesDomain = "redgifs.com"
}
With NoCredentialsResponser
If .File.Exists Then
.LoadSettings()
Else
.Cookies = New CookieKeeper(.CookiesDomain) With {.EncryptKey = SettingsCLS.CookieEncryptKey}
.SaveSettings()
End If
End With
Token = New PropertyValue(t, GetType(String), Sub(v) UpdateResponse(v)) Token = New PropertyValue(t, GetType(String), Sub(v) UpdateResponse(v))
TokenLastDateUpdated = New PropertyValue(Now.AddYears(-1), GetType(Date)) TokenLastDateUpdated = New PropertyValue(Now.AddYears(-1), GetType(Date))
UrlPatternUser = "https://www.redgifs.com/users/{0}/" UrlPatternUser = "https://www.redgifs.com/users/{0}/"
@@ -67,7 +54,7 @@ Namespace API.RedGifs
#End Region #End Region
#Region "Response updater" #Region "Response updater"
Private Sub UpdateResponse(ByVal Value As String) Private Sub UpdateResponse(ByVal Value As String)
Responser.HeadersAdd(TokenName, Value) Responser.Headers.Add(TokenName, Value)
Responser.SaveSettings() Responser.SaveSettings()
End Sub End Sub
#End Region #End Region
@@ -85,7 +72,7 @@ Namespace API.RedGifs
Try Try
Dim r$ Dim r$
Dim NewToken$ = String.Empty Dim NewToken$ = String.Empty
Using resp As New Response : r = resp.GetResponse("https://api.redgifs.com/v2/auth/temporary",, EDP.ThrowException) : End Using Using resp As New Responser : r = resp.GetResponse("https://api.redgifs.com/v2/auth/temporary",, EDP.ThrowException) : End Using
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
Dim j As EContainer = JsonDocument.Parse(r) Dim j As EContainer = JsonDocument.Parse(r)
If Not j Is Nothing Then If Not j Is Nothing Then
@@ -126,7 +113,7 @@ Namespace API.RedGifs
End Function End Function
Friend Overrides Function GetSpecialData(ByVal URL As String, ByVal Path As String, ByVal AskForPath As Boolean) As IEnumerable Friend Overrides Function GetSpecialData(ByVal URL As String, ByVal Path As String, ByVal AskForPath As Boolean) As IEnumerable
If BaseAuthExists() Then If BaseAuthExists() Then
Using resp As Response = Responser.Copy Using resp As Responser = Responser.Copy
Dim m As UserMedia = UserData.GetDataFromUrlId(URL, False, resp, Settings(RedGifsSiteKey)) Dim m As UserMedia = UserData.GetDataFromUrlId(URL, False, resp, Settings(RedGifsSiteKey))
If Not m.State = UStates.Missing And Not m.State = UserData.DataGone And (m.Type = UTypes.Picture Or m.Type = UTypes.Video) Then If Not m.State = UStates.Missing And Not m.State = UserData.DataGone And (m.Type = UTypes.Picture Or m.Type = UTypes.Video) Then
Try Try

View File

@@ -34,21 +34,15 @@ Namespace API.RedGifs
End Sub End Sub
#End Region #End Region
#Region "Download functions" #Region "Download functions"
Private NoCredentialsResponser As Response
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
Try
NoCredentialsResponser = MySettings.NoCredentialsResponser.Copy
DownloadData(1, Token) DownloadData(1, Token)
Finally
NoCredentialsResponser.Dispose()
End Try
End Sub End Sub
Private Overloads Sub DownloadData(ByVal Page As Integer, ByVal Token As CancellationToken) Private Overloads Sub DownloadData(ByVal Page As Integer, ByVal Token As CancellationToken)
Dim URL$ = String.Empty Dim URL$ = String.Empty
Try Try
Dim _page As Func(Of String) = Function() If(Page = 1, String.Empty, $"&page={Page}") Dim _page As Func(Of String) = Function() If(Page = 1, String.Empty, $"&page={Page}")
URL = $"https://api.redgifs.com/v2/users/{Name}/search?order=recent{_page.Invoke}" URL = $"https://api.redgifs.com/v2/users/{Name}/search?order=recent{_page.Invoke}"
Dim r$ = NoCredentialsResponser.GetResponse(URL,, EDP.ThrowException) Dim r$ = Responser.GetResponse(URL,, EDP.ThrowException)
Dim postDate$, postID$ Dim postDate$, postID$
Dim pTotal% = 0 Dim pTotal% = 0
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
@@ -70,7 +64,7 @@ Namespace API.RedGifs
End If End If
If pTotal > 0 And Page < pTotal Then DownloadData(Page + 1, Token) If pTotal > 0 And Page < pTotal Then DownloadData(Page + 1, Token)
Catch ex As Exception Catch ex As Exception
ProcessException(ex, Token, $"data downloading error [{URL}]",, True) ProcessException(ex, Token, $"data downloading error [{URL}]")
End Try End Try
End Sub End Sub
#End Region #End Region
@@ -166,7 +160,7 @@ Namespace API.RedGifs
Return String.Empty Return String.Empty
End If End If
End Function End Function
Friend Shared Function GetDataFromUrlId(ByVal Obj As String, ByVal ObjIsID As Boolean, ByVal Responser As Response, Friend Shared Function GetDataFromUrlId(ByVal Obj As String, ByVal ObjIsID As Boolean, ByVal Responser As Responser,
ByVal Host As Plugin.Hosts.SettingsHost) As UserMedia ByVal Host As Plugin.Hosts.SettingsHost) As UserMedia
Dim URL$ = String.Empty Dim URL$ = String.Empty
Try Try
@@ -239,18 +233,8 @@ Namespace API.RedGifs
#Region "Exception" #Region "Exception"
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
Dim IsNoCredentialsResponser As Boolean = AConvert(Of Boolean)(EObj, False) Dim s As WebExceptionStatus = Responser.Client.Status
Dim s As WebExceptionStatus = -1 Dim sc As HttpStatusCode = Responser.Client.StatusCode
Dim sc As HttpStatusCode = -1
If IsNoCredentialsResponser Then
If Not NoCredentialsResponser Is Nothing Then
s = NoCredentialsResponser.Status
sc = NoCredentialsResponser.StatusCode
End If
Else
s = Responser.Client.Status
sc = Responser.Client.StatusCode
End If
If sc = HttpStatusCode.NotFound Or s = DataGone Then If sc = HttpStatusCode.NotFound Or s = DataGone Then
UserExists = False UserExists = False
ElseIf sc = HttpStatusCode.Unauthorized Then ElseIf sc = HttpStatusCode.Unauthorized Then

View File

@@ -52,7 +52,7 @@ Namespace API.TikTok
Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken) Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken)
DownloadContentDefault(Token) DownloadContentDefault(Token)
End Sub End Sub
Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal Responser As Response, Optional ByVal e As ErrorsDescriber = Nothing) As IEnumerable(Of UserMedia) Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal Responser As Responser, Optional ByVal e As ErrorsDescriber = Nothing) As IEnumerable(Of UserMedia)
Try Try
If Not URL.IsEmptyString Then If Not URL.IsEmptyString Then
Dim PostId$ = String.Empty Dim PostId$ = String.Empty
@@ -61,7 +61,7 @@ Namespace API.TikTok
Dim r$ Dim r$
PostId = RegexEnvir.ExtractPostID(URL) PostId = RegexEnvir.ExtractPostID(URL)
If Not PostId.IsEmptyString Then If Not PostId.IsEmptyString Then
Using resp As Response = Responser.Copy() : r = resp.GetResponse(URL,, EDP.ThrowException) : End Using Using resp As Responser = Responser.Copy() : r = resp.GetResponse(URL,, EDP.ThrowException) : End Using
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
If RegexEnvir.GetVideoData(r, PostId, PostURL, PostDate) Then Return {MediaFromData(PostURL, PostId, PostDate)} If RegexEnvir.GetVideoData(r, PostId, PostURL, PostDate) Then Return {MediaFromData(PostURL, PostId, PostDate)}
End If End If

View File

@@ -34,10 +34,10 @@ Namespace API.Twitter
Private ReadOnly Property Token As PropertyValue Private ReadOnly Property Token As PropertyValue
<PropertyOption(ControlText:="Saved posts user", ControlToolTip:="Personal profile username"), PXML> <PropertyOption(ControlText:="Saved posts user", ControlToolTip:="Personal profile username"), PXML>
Friend ReadOnly Property SavedPostsUserName As PropertyValue Friend ReadOnly Property SavedPostsUserName As PropertyValue
Friend Overrides ReadOnly Property Responser As Response Friend Overrides ReadOnly Property Responser As Responser
Friend Sub New() Friend Sub New()
MyBase.New(TwitterSite) MyBase.New(TwitterSite)
Responser = New Response($"{SettingsFolderName}\Responser_{Site}.xml") Responser = New Responser($"{SettingsFolderName}\Responser_{Site}.xml")
Dim a$ = String.Empty Dim a$ = String.Empty
Dim t$ = String.Empty Dim t$ = String.Empty
@@ -46,8 +46,8 @@ Namespace API.Twitter
If .File.Exists Then If .File.Exists Then
If EncryptCookies.CookiesEncrypted Then .CookiesEncryptKey = SettingsCLS.CookieEncryptKey If EncryptCookies.CookiesEncrypted Then .CookiesEncryptKey = SettingsCLS.CookieEncryptKey
.LoadSettings() .LoadSettings()
a = .HeadersValue(Header_Authorization) a = .Headers.Value(Header_Authorization)
t = .HeadersValue(Header_Token) t = .Headers.Value(Header_Token)
Else Else
.ContentType = "application/json" .ContentType = "application/json"
.Accept = "*/*" .Accept = "*/*"
@@ -55,15 +55,15 @@ Namespace API.Twitter
.Cookies = New CookieKeeper(.CookiesDomain) With {.EncryptKey = SettingsCLS.CookieEncryptKey} .Cookies = New CookieKeeper(.CookiesDomain) With {.EncryptKey = SettingsCLS.CookieEncryptKey}
.CookiesEncryptKey = SettingsCLS.CookieEncryptKey .CookiesEncryptKey = SettingsCLS.CookieEncryptKey
.Decoders.Add(SymbolsConverter.Converters.Unicode) .Decoders.Add(SymbolsConverter.Converters.Unicode)
.HeadersAdd("sec-ch-ua", " Not;A Brand"";v=""99"", ""Google Chrome"";v=""91"", ""Chromium"";v=""91""") .Headers.Add("sec-ch-ua", " Not;A Brand"";v=""99"", ""Google Chrome"";v=""91"", ""Chromium"";v=""91""")
.HeadersAdd("sec-ch-ua-mobile", "?0") .Headers.Add("sec-ch-ua-mobile", "?0")
.HeadersAdd("sec-fetch-dest", "empty") .Headers.Add("sec-fetch-dest", "empty")
.HeadersAdd("sec-fetch-mode", "cors") .Headers.Add("sec-fetch-mode", "cors")
.HeadersAdd("sec-fetch-site", "same-origin") .Headers.Add("sec-fetch-site", "same-origin")
.HeadersAdd(Header_Token, String.Empty) .Headers.Add(Header_Token, String.Empty)
.HeadersAdd("x-twitter-active-user", "yes") .Headers.Add("x-twitter-active-user", "yes")
.HeadersAdd("x-twitter-auth-type", "OAuth2Session") .Headers.Add("x-twitter-auth-type", "OAuth2Session")
.HeadersAdd(Header_Authorization, String.Empty) .Headers.Add(Header_Authorization, String.Empty)
.SaveSettings() .SaveSettings()
End If End If
End With End With
@@ -84,8 +84,8 @@ Namespace API.Twitter
Case NameOf(Token) : f = Header_Token Case NameOf(Token) : f = Header_Token
End Select End Select
If Not f.IsEmptyString Then If Not f.IsEmptyString Then
Responser.HeadersRemove(f) Responser.Headers.Remove(f)
If Not CStr(Value).IsEmptyString Then Responser.HeadersAdd(f, CStr(Value)) If Not CStr(Value).IsEmptyString Then Responser.Headers.Add(f, CStr(Value))
Responser.SaveSettings() Responser.SaveSettings()
End If End If
End If End If

View File

@@ -263,13 +263,13 @@ Namespace API.Twitter
End Sub End Sub
#End Region #End Region
#Region "Get video static" #Region "Get video static"
Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal resp As Response) As IEnumerable(Of UserMedia) Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal resp As Responser) As IEnumerable(Of UserMedia)
Try Try
If URL.Contains("twitter") Then If URL.Contains("twitter") Then
Dim PostID$ = RegexReplace(URL, RParams.DM("(?<=/)\d+", 0)) Dim PostID$ = RegexReplace(URL, RParams.DM("(?<=/)\d+", 0))
If Not PostID.IsEmptyString Then If Not PostID.IsEmptyString Then
Dim r$ Dim r$
Using rc As Response = resp.Copy() : r = rc.GetResponse(String.Format(SinglePostUrl, PostID),, EDP.ReturnValue) : End Using Using rc As Responser = resp.Copy() : r = rc.GetResponse(String.Format(SinglePostUrl, PostID),, EDP.ReturnValue) : End Using
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
Using j As EContainer = JsonDocument.Parse(r) Using j As EContainer = JsonDocument.Parse(r)
If j.ListExists Then If j.ListExists Then

View File

@@ -98,7 +98,7 @@ Namespace API
If Not img Is Nothing Then Return img If Not img Is Nothing Then Return img
Next Next
End If End If
Return GetNullPicture(Settings.MaxLargeImageHeight) Return GetNullPicture(If(Settings.ViewMode.Value = ViewModes.IconLarge, Settings.MaxLargeImageHeight, Settings.MaxSmallImageHeight))
End Function End Function
#End Region #End Region
Friend Overrides ReadOnly Property DownloadedTotal(Optional ByVal Total As Boolean = True) As Integer Friend Overrides ReadOnly Property DownloadedTotal(Optional ByVal Total As Boolean = True) As Integer
@@ -556,7 +556,11 @@ Namespace API
"Cancel"}, vbExclamation) "Cancel"}, vbExclamation)
Dim v% Dim v%
If CollectionValue >= 0 Then If CollectionValue >= 0 Then
v = CollectionValue Select Case CollectionValue
Case 2 : v = 0
Case 3 : v = 1
Case Else : v = MsgBoxE(m)
End Select
ElseIf Multiple Then ElseIf Multiple Then
v = 0 v = 0
Else Else

View File

@@ -57,6 +57,7 @@ Namespace API.XVIDEOS
SiteDomains = New PropertyValue(DomainsDefault, GetType(String), Sub(s) UpdateDomains()) SiteDomains = New PropertyValue(DomainsDefault, GetType(String), Sub(s) UpdateDomains())
DownloadUHD = New PropertyValue(False) DownloadUHD = New PropertyValue(False)
SavedVideosPlaylist = New PropertyValue(String.Empty, GetType(String)) SavedVideosPlaylist = New PropertyValue(String.Empty, GetType(String))
UrlPatternUser = "https://xvideos.com/{0}"
End Sub End Sub
Friend Overrides Sub EndInit() Friend Overrides Sub EndInit()
Initialized = True Initialized = True
@@ -103,11 +104,14 @@ Namespace API.XVIDEOS
End Function End Function
#End Region #End Region
#Region "User: get, check" #Region "User: get, check"
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider, ByVal Channel As Boolean) As String Friend Function GetUserUrlPart(ByVal User As UserData) As String
Dim __user$ = User.Name.Split("_").FirstOrDefault Dim __user$ = User.Name.Split("_").FirstOrDefault
__user &= $"/{User.Name.Replace($"{User}_", String.Empty)}" __user &= $"/{User.Name.Replace($"{__user}_", String.Empty)}"
Return __user Return __user
End Function End Function
Friend Overrides Function GetUserUrl(ByVal User As IPluginContentProvider, ByVal Channel As Boolean) As String
Return String.Format(UrlPatternUser, GetUserUrlPart(User))
End Function
Private Const UserRegexDefault As String = "/(profiles|[\w]*?[-]{0,1}channels)/([^/]+)(\Z|.*?)" Private Const UserRegexDefault As String = "/(profiles|[\w]*?[-]{0,1}channels)/([^/]+)(\Z|.*?)"
Private Const URD As String = ".*?{0}{1}" Private Const URD As String = ".*?{0}{1}"
Friend Overrides Function IsMyUser(ByVal UserURL As String) As ExchangeOptions Friend Overrides Function IsMyUser(ByVal UserURL As String) As ExchangeOptions
@@ -141,7 +145,7 @@ Namespace API.XVIDEOS
Dim f As SFile = GetSpecialDataFile(Path, AskForPath, spf) Dim f As SFile = GetSpecialDataFile(Path, AskForPath, spf)
f.Name = "video" f.Name = "video"
f.Extension = "mp4" f.Extension = "mp4"
Using resp As Response = Responser.Copy Using resp As Responser = Responser.Copy
Using user As New UserData With {.HOST = Settings(XvideosSiteKey)} Using user As New UserData With {.HOST = Settings(XvideosSiteKey)}
DirectCast(user, UserDataBase).User.File = f DirectCast(user, UserDataBase).User.File = f
Dim p As UserMedia = user.Download(URL, resp, DownloadUHD.Value, String.Empty) Dim p As UserMedia = user.Download(URL, resp, DownloadUHD.Value, String.Empty)

View File

@@ -45,14 +45,7 @@ Namespace API.XVIDEOS
UseInternalM3U8Function = True UseInternalM3U8Function = True
End Sub End Sub
Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken)
If Not Settings.UseM3U8 Then If Not Settings.UseM3U8 Then MyMainLOG = $"{ToStringForLog()}: File [ffmpeg.exe] not found" : Exit Sub
If Not Settings.OS64 Then
MyMainLOG = $"XVIDEOS [{ToStringForLog()}]: The plugin only works with x64 OS."
Else
MyMainLOG = $"{ToStringForLog()}: File [ffmpeg.exe] not found"
End If
Exit Sub
End If
If IsSavedPosts Then If IsSavedPosts Then
If Not ACheck(MySettings.SavedVideosPlaylist.Value) Then Throw New ArgumentNullException("SavedVideosPlaylist", "Playlist of saved videos cannot be null") If Not ACheck(MySettings.SavedVideosPlaylist.Value) Then Throw New ArgumentNullException("SavedVideosPlaylist", "Playlist of saved videos cannot be null")
DownloadSavedVideos(Token) DownloadSavedVideos(Token)
@@ -63,18 +56,29 @@ Namespace API.XVIDEOS
Private Sub DownloadUserVideo(ByVal Token As CancellationToken) Private Sub DownloadUserVideo(ByVal Token As CancellationToken)
Dim URL$ = String.Empty Dim URL$ = String.Empty
Try Try
Dim NextPage% = 0 Dim NextPage%, d%
Dim r$ Dim limit% = If(DownloadTopCount, -1)
Dim r$, n$
Dim j As EContainer = Nothing Dim j As EContainer = Nothing
Dim jj As EContainer Dim jj As EContainer
Dim user$ = MySettings.GetUserUrl(Me, False) Dim user$ = MySettings.GetUserUrlPart(Me)
Dim p As UserMedia Dim p As UserMedia
Dim EnvirSet As Boolean = False Dim EnvirSet As Boolean = False
If ID.IsEmptyString Then GetUserID()
For i% = 0 To 1
If i = 1 And ID.IsEmptyString Then Exit For
NextPage = 0
d = 0
n = IIf(i = 0, "u", "url")
Do Do
ThrowAny(Token) ThrowAny(Token)
If i = 0 Then
URL = $"https://www.xvideos.com/{user}/videos/new/{If(NextPage = 0, String.Empty, NextPage)}" URL = $"https://www.xvideos.com/{user}/videos/new/{If(NextPage = 0, String.Empty, NextPage)}"
r = Responser.GetResponse(URL) Else 'Quickies
URL = $"https://www.xvideos.com/quickies-api/profilevideos/all/none/N/{ID}/{NextPage}"
End If
r = Responser.GetResponse(URL,, EDP.ReturnValue)
If Not r.IsEmptyString Then If Not r.IsEmptyString Then
If Not EnvirSet Then UserExists = True : UserSuspended = False : EnvirSet = True If Not EnvirSet Then UserExists = True : UserSuspended = False : EnvirSet = True
j = JsonDocument.Parse(r).XmlIfNothing j = JsonDocument.Parse(r).XmlIfNothing
@@ -86,12 +90,14 @@ Namespace API.XVIDEOS
For Each jj In .Self For Each jj In .Self
p = New UserMedia With { p = New UserMedia With {
.Post = jj.Value("id"), .Post = jj.Value("id"),
.URL = $"https://www.xvideos.com/{jj.Value("u").StringTrimStart("/")}" .URL = $"https://www.xvideos.com/{jj.Value(n).StringTrimStart("/")}"
} }
If Not p.Post.ID.IsEmptyString And Not jj.Value("u").IsEmptyString Then If Not p.Post.ID.IsEmptyString And Not jj.Value(n).IsEmptyString Then
If Not _TempPostsList.Contains(p.Post.ID) Then If Not _TempPostsList.Contains(p.Post.ID) Then
_TempPostsList.Add(p.Post.ID) _TempPostsList.Add(p.Post.ID)
_TempMediaList.Add(p) _TempMediaList.Add(p)
d += 1
If limit > 0 And d = limit Then Exit Do
Else Else
Exit Do Exit Do
End If End If
@@ -106,6 +112,7 @@ Namespace API.XVIDEOS
If Not j Is Nothing Then j.Dispose() If Not j Is Nothing Then j.Dispose()
Exit Do Exit Do
Loop While NextPage < 100 Loop While NextPage < 100
Next
If Not j Is Nothing Then j.Dispose() If Not j Is Nothing Then j.Dispose()
@@ -128,6 +135,10 @@ Namespace API.XVIDEOS
If _TempMediaList.ListExists Then _TempMediaList.RemoveAll(Function(m) m.URL.IsEmptyString) If _TempMediaList.ListExists Then _TempMediaList.RemoveAll(Function(m) m.URL.IsEmptyString)
End Try End Try
End Sub End Sub
Private Sub GetUserID()
Dim r$ = Responser.GetResponse($"https://www.xvideos.com/{MySettings.GetUserUrlPart(Me)}",, EDP.ReturnValue)
If Not r.IsEmptyString Then ID = RegexReplace(r, RParams.DMS("""id_user"":(\d+)", 1, EDP.ReturnValue))
End Sub
Private Sub DownloadSavedVideos(ByVal Token As CancellationToken) Private Sub DownloadSavedVideos(ByVal Token As CancellationToken)
Dim URL$ = MySettings.SavedVideosPlaylist.Value Dim URL$ = MySettings.SavedVideosPlaylist.Value
Try Try
@@ -171,7 +182,7 @@ Namespace API.XVIDEOS
ProcessException(ex, Token, $"data downloading error [{URL}]") ProcessException(ex, Token, $"data downloading error [{URL}]")
End Try End Try
End Sub End Sub
Private Function GetVideoData(ByVal Media As UserMedia, ByVal resp As Response, ByVal DownloadUHD As Boolean) As UserMedia Private Function GetVideoData(ByVal Media As UserMedia, ByVal resp As Responser, ByVal DownloadUHD As Boolean) As UserMedia
Try Try
If Not Media.URL.IsEmptyString Then If Not Media.URL.IsEmptyString Then
Dim r$ = resp.GetResponse(Media.URL) Dim r$ = resp.GetResponse(Media.URL)
@@ -217,7 +228,7 @@ Namespace API.XVIDEOS
Return Nothing Return Nothing
End Try End Try
End Function End Function
Friend Function Download(ByVal URL As String, ByVal resp As Response, ByVal DownloadUHD As Boolean, ByVal ID As String) Friend Function Download(ByVal URL As String, ByVal resp As Responser, ByVal DownloadUHD As Boolean, ByVal ID As String)
Dim m As UserMedia = GetVideoData(New UserMedia(URL, UTypes.VideoPre) With {.Post = ID}, resp, DownloadUHD) Dim m As UserMedia = GetVideoData(New UserMedia(URL, UTypes.VideoPre) With {.Post = ID}, resp, DownloadUHD)
If Not m.URL.IsEmptyString Then If Not m.URL.IsEmptyString Then
Dim f As SFile = m.File Dim f As SFile = m.File

View File

@@ -14,7 +14,7 @@ Namespace API.Xhamster
Friend NotInheritable Class M3U8 Friend NotInheritable Class M3U8
Private Sub New() Private Sub New()
End Sub End Sub
Private Shared Function ParseFirstM3U8(ByVal URL As String, ByVal Responser As Response, ByVal UHD As Boolean) As String Private Shared Function ParseFirstM3U8(ByVal URL As String, ByVal Responser As Responser, ByVal UHD As Boolean) As String
Dim r$, d$ Dim r$, d$
Dim _DataObtained As Boolean = False Dim _DataObtained As Boolean = False
For i% = 0 To 1 For i% = 0 To 1
@@ -38,7 +38,7 @@ Namespace API.Xhamster
Next Next
Return String.Empty Return String.Empty
End Function End Function
Private Shared Function ParseSecondM3U8(ByVal URL As String, ByVal Responser As Response, ByVal Appender As String) As List(Of String) Private Shared Function ParseSecondM3U8(ByVal URL As String, ByVal Responser As Responser, ByVal Appender As String) As List(Of String)
Dim r$ Dim r$
Dim l As List(Of String) Dim l As List(Of String)
For i% = 0 To 1 For i% = 0 To 1
@@ -57,7 +57,7 @@ Namespace API.Xhamster
Next Next
Return Nothing Return Nothing
End Function End Function
Private Shared Function ObtainUrls(ByVal URL As String, ByVal Responser As Response, ByVal UHD As Boolean) As List(Of String) Private Shared Function ObtainUrls(ByVal URL As String, ByVal Responser As Responser, ByVal UHD As Boolean) As List(Of String)
Try Try
Dim file$ = ParseFirstM3U8(URL, Responser, UHD) Dim file$ = ParseFirstM3U8(URL, Responser, UHD)
If Not file.IsEmptyString Then If Not file.IsEmptyString Then
@@ -72,7 +72,7 @@ Namespace API.Xhamster
Responser.UseGZipStream = False Responser.UseGZipStream = False
End Try End Try
End Function End Function
Friend Shared Function Download(ByVal Media As UserMedia, ByVal Responser As Response, ByVal UHD As Boolean) As SFile Friend Shared Function Download(ByVal Media As UserMedia, ByVal Responser As Responser, ByVal UHD As Boolean) As SFile
Return M3U8Base.Download(ObtainUrls(Media.URL, Responser, UHD), Media.File, Responser) Return M3U8Base.Download(ObtainUrls(Media.URL, Responser, UHD), Media.File, Responser)
End Function End Function
End Class End Class

View File

@@ -102,7 +102,7 @@ Namespace API.Xhamster
End Function End Function
Friend Overrides Function GetSpecialData(ByVal URL As String, ByVal Path As String, ByVal AskForPath As Boolean) As IEnumerable Friend Overrides Function GetSpecialData(ByVal URL As String, ByVal Path As String, ByVal AskForPath As Boolean) As IEnumerable
If Available(ISiteSettings.Download.Main, True) Then If Available(ISiteSettings.Download.Main, True) Then
Using resp As Response = Responser.Copy Using resp As Responser = Responser.Copy
Dim spf$ = String.Empty Dim spf$ = String.Empty
Dim f As SFile = GetSpecialDataFile(Path, AskForPath, spf) Dim f As SFile = GetSpecialDataFile(Path, AskForPath, spf)
Dim m As UserMedia = UserData.GetVideoInfo(URL, resp, f) Dim m As UserMedia = UserData.GetVideoInfo(URL, resp, f)
@@ -114,10 +114,10 @@ Namespace API.Xhamster
End If End If
Return Nothing Return Nothing
End Function End Function
Friend Overrides Function Available(ByVal What As ISiteSettings.Download, Silent As Boolean) As Boolean Friend Overrides Function Available(ByVal What As ISiteSettings.Download, ByVal Silent As Boolean) As Boolean
If Settings.UseM3U8 AndAlso MyBase.Available(What, Silent) Then If Settings.UseM3U8 AndAlso MyBase.Available(What, Silent) Then
If What = ISiteSettings.Download.SavedPosts Then If What = ISiteSettings.Download.SavedPosts Then
Return If(Responser.Cookies?.Count, 0) > 0 Return Responser.CookiesExists
Else Else
Return True Return True
End If End If

View File

@@ -219,7 +219,7 @@ Namespace API.Xhamster
End Sub End Sub
#End Region #End Region
#Region "GetM3U8" #Region "GetM3U8"
Private Overloads Function GetM3U8(ByRef m As UserMedia, ByVal URL As String, ByVal Responser As Response, Private Overloads Function GetM3U8(ByRef m As UserMedia, ByVal URL As String, ByVal Responser As Responser,
Optional ByVal e As ErrorsDescriber = Nothing) As Boolean Optional ByVal e As ErrorsDescriber = Nothing) As Boolean
Try Try
If Not URL.IsEmptyString Then If Not URL.IsEmptyString Then
@@ -248,7 +248,7 @@ Namespace API.Xhamster
End Function End Function
#End Region #End Region
#Region "Standalone downloader" #Region "Standalone downloader"
Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal Responser As Response, ByVal Path As SFile) As UserMedia Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal Responser As Responser, ByVal Path As SFile) As UserMedia
Try Try
Using u As New UserData With {.Responser = Responser, .HOST = Settings(XhamsterSiteKey)} Using u As New UserData With {.Responser = Responser, .HOST = Settings(XhamsterSiteKey)}
Dim m As UserMedia = Nothing Dim m As UserMedia = Nothing

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -471,18 +471,25 @@ Namespace DownloadObjects
Dim DownloadedUsersCount% = 0 Dim DownloadedUsersCount% = 0
Dim simple As Boolean = ShowSimpleNotification And ShowNotifications Dim simple As Boolean = ShowSimpleNotification And ShowNotifications
Dim notify As Action = Sub() Dim notify As Action = Sub()
Try
With Downloader.Downloaded With Downloader.Downloaded
If ShowNotifications And .Count > 0 Then .ForEach(Sub(ByVal u As IUserData) If ShowNotifications And .Count > 0 Then
If Keys.Contains(u.Key) Then For indx% = 0 To .Count - 1
With .Item(indx)
If Keys.Contains(.Key) Then
If simple Then If simple Then
DownloadedUsersCount += 1 DownloadedUsersCount += 1
Else Else
ShowNotification(u) ShowNotification(.Self)
End If End If
Keys.Remove(u.Key) Keys.Remove(.Key)
End If End If
End Sub)
End With End With
Next
End If
End With
Catch n_ex As Exception
End Try
End Sub End Sub
Select Case Mode Select Case Mode
Case Modes.All Case Modes.All

View File

@@ -150,8 +150,8 @@ Namespace DownloadObjects
Private Sub BTT_FIND_Click(sender As Object, e As EventArgs) Handles BTT_FIND.Click Private Sub BTT_FIND_Click(sender As Object, e As EventArgs) Handles BTT_FIND.Click
Try Try
If _LatestSelected.ValueBetween(0, LIST_DOWN.Items.Count - 1) AndAlso _LatestSelected.ValueBetween(0, Downloader.Downloaded.Count - 1) Then If _LatestSelected.ValueBetween(0, LIST_DOWN.Items.Count - 1) AndAlso _LatestSelected.ValueBetween(0, Downloader.Downloaded.Count - 1) Then
Dim i% = Settings.Users.IndexOf(_TempUsersList(_LatestSelected)) Dim u As IUserData = Settings.GetUser(_TempUsersList(_LatestSelected), True)
If i >= 0 Then RaiseEvent UserFind(Settings.Users(i).Key) If Not u Is Nothing Then RaiseEvent UserFind(u.Key)
End If End If
Catch ex As Exception Catch ex As Exception
End Try End Try

View File

@@ -115,6 +115,7 @@ Namespace DownloadObjects
Case UserMedia.Types.Video, UserMedia.Types.m3u8 Case UserMedia.Types.Video, UserMedia.Types.m3u8
infoType = UserMedia.Types.Video infoType = UserMedia.Types.Video
MyVideo = New FeedVideo(File) With {.Tag = File, .Dock = DockStyle.Fill, .ContextMenuStrip = CONTEXT_DATA} MyVideo = New FeedVideo(File) With {.Tag = File, .Dock = DockStyle.Fill, .ContextMenuStrip = CONTEXT_DATA}
If MyVideo.HasError Then HasError = True
TP_MAIN.Controls.Add(MyVideo, 0, 1) TP_MAIN.Controls.Add(MyVideo, 0, 1)
BTT_CONTEXT_OPEN_MEDIA.Text &= " video" BTT_CONTEXT_OPEN_MEDIA.Text &= " video"
BTT_CONTEXT_DELETE.Text &= " video" BTT_CONTEXT_DELETE.Text &= " video"

View File

@@ -38,6 +38,7 @@ Namespace DownloadObjects
Private VideoLengthMs As Integer = 0 Private VideoLengthMs As Integer = 0
Private VideoLengthStr As String Private VideoLengthStr As String
Private MediaFile As SFile = Nothing Private MediaFile As SFile = Nothing
Friend ReadOnly HasError As Boolean = False
Public Sub New() Public Sub New()
InitializeComponent() InitializeComponent()
End Sub End Sub
@@ -63,7 +64,6 @@ Namespace DownloadObjects
MyVideo.BackgroundImageLayout = ImageLayout.Zoom MyVideo.BackgroundImageLayout = ImageLayout.Zoom
End If End If
Catch img_set_ex As Exception Catch img_set_ex As Exception
'TODELETE: FeedVideo set BackgroundImage error
ErrorsDescriber.Execute(EDP.SendInLog, img_set_ex, "Error setting background image for media player." & vbCr & ErrorsDescriber.Execute(EDP.SendInLog, img_set_ex, "Error setting background image for media player." & vbCr &
$"File: {File}{vbCr}Image: {f}") $"File: {File}{vbCr}Image: {f}")
End Try End Try
@@ -71,8 +71,8 @@ Namespace DownloadObjects
End If End If
UpdateButtons() UpdateButtons()
Catch ex As Exception Catch ex As Exception
'TODELETE: FeedVideo initialization error
ErrorsDescriber.Execute(EDP.SendInLog, ex, $"Media player initialization error({File})") ErrorsDescriber.Execute(EDP.SendInLog, ex, $"Media player initialization error({File})")
HasError = True
End Try End Try
End Sub End Sub
Private _Disposed As Boolean = False Private _Disposed As Boolean = False

View File

@@ -11,12 +11,12 @@ Imports PersonalUtilities.Tools.Web.Clients
Namespace DownloadObjects Namespace DownloadObjects
Friend Class WebClient2 : Implements IDisposable Friend Class WebClient2 : Implements IDisposable
Protected WC As WebClient Protected WC As WebClient
Protected RC As Response Protected RC As Responser
Private ReadOnly RCERROR As New ErrorsDescriber(EDP.ThrowException) Private ReadOnly RCERROR As New ErrorsDescriber(EDP.ThrowException)
Protected UseResponserClient As Boolean Protected UseResponserClient As Boolean
Friend Sub New() Friend Sub New()
End Sub End Sub
Friend Sub New(ByVal Responser As Response) Friend Sub New(ByVal Responser As Responser)
If Not Responser Is Nothing Then If Not Responser Is Nothing Then
RC = Responser RC = Responser
UseResponserClient = True UseResponserClient = True

View File

@@ -12,7 +12,6 @@ Imports PersonalUtilities.Forms
Imports PersonalUtilities.Forms.Controls Imports PersonalUtilities.Forms.Controls
Imports PersonalUtilities.Forms.Controls.Base Imports PersonalUtilities.Forms.Controls.Base
Imports PersonalUtilities.Tools.Web.Cookies Imports PersonalUtilities.Tools.Web.Cookies
Imports CookieControl = PersonalUtilities.Tools.Web.Cookies.CookieListForm.CookieControl
Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons
Namespace Editors Namespace Editors
Friend Class SiteEditorForm Friend Class SiteEditorForm
@@ -213,12 +212,13 @@ Namespace Editors
Select Case Sender.DefaultButton Select Case Sender.DefaultButton
Case ADB.Edit Case ADB.Edit
If Not Host.Responser Is Nothing Then If Not Host.Responser Is Nothing Then
Using f As New CookieListForm(Host.Responser) With { Using f As New CookieListForm With {.DesignXML = Settings.Design, .UseGrid = False}
.MyDesignXML = Settings.Design, f.SetCollection(Host.Responser.Cookies)
.DisableControls = CookieControl.AddFromInternal + CookieControl.AuthorizeProgram + CookieControl.OpenBrowser
}
f.ShowDialog() f.ShowDialog()
If f.DialogResult = DialogResult.OK Then
f.GetCollection(Host.Responser)
MyDefs.MyOkCancel.EnableOK = True MyDefs.MyOkCancel.EnableOK = True
End If
End Using End Using
SetCookieText() SetCookieText()
End If End If

View File

@@ -106,10 +106,10 @@ Namespace Editors
'BTT_OTHER_SETTINGS 'BTT_OTHER_SETTINGS
' '
Me.BTT_OTHER_SETTINGS.Dock = System.Windows.Forms.DockStyle.Fill Me.BTT_OTHER_SETTINGS.Dock = System.Windows.Forms.DockStyle.Fill
Me.BTT_OTHER_SETTINGS.Location = New System.Drawing.Point(330, 2) Me.BTT_OTHER_SETTINGS.Location = New System.Drawing.Point(329, 2)
Me.BTT_OTHER_SETTINGS.Margin = New System.Windows.Forms.Padding(1) Me.BTT_OTHER_SETTINGS.Margin = New System.Windows.Forms.Padding(1)
Me.BTT_OTHER_SETTINGS.Name = "BTT_OTHER_SETTINGS" Me.BTT_OTHER_SETTINGS.Name = "BTT_OTHER_SETTINGS"
Me.BTT_OTHER_SETTINGS.Size = New System.Drawing.Size(120, 24) Me.BTT_OTHER_SETTINGS.Size = New System.Drawing.Size(121, 24)
Me.BTT_OTHER_SETTINGS.TabIndex = 2 Me.BTT_OTHER_SETTINGS.TabIndex = 2
Me.BTT_OTHER_SETTINGS.Text = "Options (F2)" Me.BTT_OTHER_SETTINGS.Text = "Options (F2)"
TT_MAIN.SetToolTip(Me.BTT_OTHER_SETTINGS, "Other settings") TT_MAIN.SetToolTip(Me.BTT_OTHER_SETTINGS, "Other settings")
@@ -121,7 +121,7 @@ Namespace Editors
'CONTAINER_MAIN.ContentPanel 'CONTAINER_MAIN.ContentPanel
' '
CONTAINER_MAIN.ContentPanel.Controls.Add(Me.TP_MAIN) CONTAINER_MAIN.ContentPanel.Controls.Add(Me.TP_MAIN)
CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(454, 436) CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(454, 461)
CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill
CONTAINER_MAIN.LeftToolStripPanelVisible = False CONTAINER_MAIN.LeftToolStripPanelVisible = False
CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0) CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0)
@@ -162,7 +162,7 @@ Namespace Editors
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26.0!)) Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26.0!))
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26.0!)) Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 26.0!))
Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_MAIN.Size = New System.Drawing.Size(454, 436) Me.TP_MAIN.Size = New System.Drawing.Size(454, 461)
Me.TP_MAIN.TabIndex = 0 Me.TP_MAIN.TabIndex = 0
' '
'TXT_USER 'TXT_USER
@@ -182,7 +182,7 @@ Namespace Editors
Me.TP_SITE.ColumnCount = 3 Me.TP_SITE.ColumnCount = 3
Me.TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 79.0!)) Me.TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 79.0!))
Me.TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) Me.TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!))
Me.TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 122.0!)) Me.TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 123.0!))
Me.TP_SITE.Controls.Add(Me.CH_IS_CHANNEL, 0, 0) Me.TP_SITE.Controls.Add(Me.CH_IS_CHANNEL, 0, 0)
Me.TP_SITE.Controls.Add(Me.CMB_SITE, 1, 0) Me.TP_SITE.Controls.Add(Me.CMB_SITE, 1, 0)
Me.TP_SITE.Controls.Add(Me.BTT_OTHER_SETTINGS, 2, 0) Me.TP_SITE.Controls.Add(Me.BTT_OTHER_SETTINGS, 2, 0)
@@ -225,7 +225,7 @@ Namespace Editors
Me.CMB_SITE.Location = New System.Drawing.Point(84, 3) Me.CMB_SITE.Location = New System.Drawing.Point(84, 3)
Me.CMB_SITE.Margin = New System.Windows.Forms.Padding(3, 2, 3, 3) Me.CMB_SITE.Margin = New System.Windows.Forms.Padding(3, 2, 3, 3)
Me.CMB_SITE.Name = "CMB_SITE" Me.CMB_SITE.Name = "CMB_SITE"
Me.CMB_SITE.Size = New System.Drawing.Size(241, 22) Me.CMB_SITE.Size = New System.Drawing.Size(240, 22)
Me.CMB_SITE.TabIndex = 1 Me.CMB_SITE.TabIndex = 1
Me.CMB_SITE.TextBoxBorderStyle = System.Windows.Forms.BorderStyle.FixedSingle Me.CMB_SITE.TextBoxBorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
' '
@@ -302,7 +302,7 @@ Namespace Editors
Me.TXT_DESCR.Location = New System.Drawing.Point(4, 290) Me.TXT_DESCR.Location = New System.Drawing.Point(4, 290)
Me.TXT_DESCR.Multiline = True Me.TXT_DESCR.Multiline = True
Me.TXT_DESCR.Name = "TXT_DESCR" Me.TXT_DESCR.Name = "TXT_DESCR"
Me.TXT_DESCR.Size = New System.Drawing.Size(446, 142) Me.TXT_DESCR.Size = New System.Drawing.Size(446, 167)
Me.TXT_DESCR.TabIndex = 10 Me.TXT_DESCR.TabIndex = 10
' '
'TXT_USER_FRIENDLY 'TXT_USER_FRIENDLY
@@ -469,7 +469,7 @@ Namespace Editors
Me.Name = "UserCreatorForm" Me.Name = "UserCreatorForm"
Me.ShowInTaskbar = False Me.ShowInTaskbar = False
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
Me.Text = "Create User" Me.Text = "Create user"
CONTAINER_MAIN.ContentPanel.ResumeLayout(False) CONTAINER_MAIN.ContentPanel.ResumeLayout(False)
CONTAINER_MAIN.ResumeLayout(False) CONTAINER_MAIN.ResumeLayout(False)
CONTAINER_MAIN.PerformLayout() CONTAINER_MAIN.PerformLayout()

View File

@@ -241,6 +241,8 @@ Namespace Editors
CMB_SITE.Enabled = False CMB_SITE.Enabled = False
CH_IS_CHANNEL.Checked = User.IsChannel CH_IS_CHANNEL.Checked = User.IsChannel
If Not UserInstance Is Nothing Then If Not UserInstance Is Nothing Then
Text = $"User: {UserInstance.Name}"
If Not UserInstance.FriendlyName.IsEmptyString Then Text &= $" ({UserInstance.FriendlyName})"
TXT_USER.Enabled = False TXT_USER.Enabled = False
TXT_SPEC_FOLDER.TextBoxReadOnly = True TXT_SPEC_FOLDER.TextBoxReadOnly = True
TXT_SPEC_FOLDER.Buttons.Clear() TXT_SPEC_FOLDER.Buttons.Clear()

View File

@@ -10,7 +10,7 @@ Imports PersonalUtilities.Tools.Web.Clients
Namespace EncryptCookies Namespace EncryptCookies
Friend Module EncryptFunction Friend Module EncryptFunction
Friend CookiesEncrypted As Boolean = False Friend CookiesEncrypted As Boolean = False
Friend Sub ValidateCookiesEncrypt(ByRef Responser As Response) Friend Sub ValidateCookiesEncrypt(ByRef Responser As Responser)
If Not Responser Is Nothing Then If Not Responser Is Nothing Then
Dim b As Boolean = False Dim b As Boolean = False
With Responser With Responser

View File

@@ -6,11 +6,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 SCrawler.API Imports SCrawler.API
Imports SCrawler.API.Base Imports SCrawler.API.Base
Friend Class ListImagesLoader Friend Class ListImagesLoader
Private ReadOnly Property MyList As ListView Private ReadOnly Property MyList As ListView
Private Class UserOption : Implements IComparable(Of UserOption) Private Structure UserOption : Implements IComparable(Of UserOption)
Friend ReadOnly User As IUserData Friend ReadOnly User As IUserData
Friend ReadOnly LVI As ListViewItem Friend ReadOnly LVI As ListViewItem
Friend Index As Integer Friend Index As Integer
@@ -19,24 +20,54 @@ Friend Class ListImagesLoader
Return LVI.Name Return LVI.Name
End Get End Get
End Property End Property
Friend [Image] As Image Friend Sub New(ByVal u As IUserData, ByVal l As ListView)
Friend Sub New(ByVal u As IUserData, ByVal l As ListView, ByVal GetImage As Boolean)
User = u User = u
LVI = u.GetLVI(l) LVI = u.GetLVI(l)
Index = u.Index Index = u.Index
If GetImage Then Image = u.GetPicture
End Sub
Friend Sub UpdateImage()
Image = User.GetPicture
End Sub End Sub
Friend Function CompareTo(ByVal Other As UserOption) As Integer Implements IComparable(Of UserOption).CompareTo Friend Function CompareTo(ByVal Other As UserOption) As Integer Implements IComparable(Of UserOption).CompareTo
Return Index.CompareTo(Other.Index) Return Index.CompareTo(Other.Index)
End Function End Function
End Class End Structure
Friend Sub New(ByRef l As ListView) Friend Sub New(ByRef l As ListView)
MyList = l MyList = l
End Sub End Sub
Private UserDataList As List(Of UserOption)
Private UpdateInProgress As Boolean = False
Private ImageThread As Thread
Private Sub UpdateImages()
If UserDataList.ListExists And Not If(ImageThread?.IsAlive, False) Then
ImageThread = New Thread(New ThreadStart(Sub()
Dim ar As IAsyncResult = Nothing
Dim a As Action = Sub()
If UserDataList.ListExists Then
For i% = 0 To UserDataList.Count - 1
With UserDataList(i).User
Select Case Settings.ViewMode.Value
Case View.LargeIcon : MyList.LargeImageList.Images.Add(.Key, .GetPicture())
Case View.SmallIcon : MyList.SmallImageList.Images.Add(.Key, .GetPicture())
End Select
End With
Application.DoEvents()
Next
UserDataList.Clear()
GC.Collect()
End If
If Not ar Is Nothing Then MyList.EndInvoke(ar)
End Sub
If MyList.InvokeRequired Then
ar = MyList.BeginInvoke(a)
Else
a.Invoke
End If
End Sub)) With {.IsBackground = True}
ImageThread.SetApartmentState(ApartmentState.MTA)
ImageThread.Start()
End If
End Sub
Friend Sub Update() Friend Sub Update()
If Not UpdateInProgress Then
UpdateInProgress = True
Dim a As Action = Sub() Dim a As Action = Sub()
With MyList With MyList
.Items.Clear() .Items.Clear()
@@ -56,40 +87,19 @@ Friend Class ListImagesLoader
If Settings.Users.Count > 0 Then If Settings.Users.Count > 0 Then
Settings.Users.Sort() Settings.Users.Sort()
Dim v As View = Settings.ViewMode.Value Dim v As View = Settings.ViewMode.Value
Dim i%
With MyList With MyList
MyList.BeginUpdate() MyList.BeginUpdate()
If Settings.FastProfilesLoading Then If Settings.FastProfilesLoading Then
Settings.Users.ListReindex Settings.Users.ListReindex
Dim UData As List(Of UserOption)
If Settings.ViewModeIsPicture Then UserDataList = (From u As IUserData In Settings.Users Where u.FitToAddParams Select New UserOption(u, MyList)).ListIfNothing
UData = GetUsersWithImages() If UserDataList.ListExists Then UserDataList.Sort()
If UData.ListExists Then
UData.Sort()
Select Case v
Case View.LargeIcon : .LargeImageList.Images.AddRange(UData.Select(Function(u) u.Image).ToArray)
Case View.SmallIcon : .SmallImageList.Images.AddRange(UData.Select(Function(u) u.Image).ToArray)
End Select
End If
Else
UData = (From u As IUserData In Settings.Users Where u.FitToAddParams Select New UserOption(u, MyList, False)).ListIfNothing
If UData.ListExists Then UData.Sort()
End If
If UData.ListExists Then If UserDataList.ListExists Then
If Settings.ViewModeIsPicture Then .Items.AddRange(UserDataList.Select(Function(u) u.LVI).ToArray)
For i = 0 To UData.Count - 1 If Settings.ViewModeIsPicture Then MyList.EndUpdate() : UpdateImages() Else UserDataList.Clear()
Select Case v
Case View.LargeIcon : .LargeImageList.Images.SetKeyName(i, UData(i).Key)
Case View.SmallIcon : .SmallImageList.Images.SetKeyName(i, UData(i).Key)
End Select
Next
End If
.Items.AddRange(UData.Select(Function(u) u.LVI).ToArray)
UData.Clear()
End If End If
Else Else
Dim t As New List(Of Task) Dim t As New List(Of Task)
@@ -107,6 +117,10 @@ Friend Class ListImagesLoader
End With End With
MyList.EndUpdate() MyList.EndUpdate()
End If End If
UpdateInProgress = False
Else
MsgBoxE({"The user list is currently being updated. Please wait for the update operation to complete and try again.", "Update user list"}, vbExclamation)
End If
End Sub End Sub
Friend Sub UpdateUser(ByVal User As IUserData, ByVal Add As Boolean) Friend Sub UpdateUser(ByVal User As IUserData, ByVal Add As Boolean)
Try Try
@@ -172,24 +186,4 @@ Friend Class ListImagesLoader
Return False Return False
End If End If
End Function End Function
Private Function GetUsersWithImages() As List(Of UserOption)
Try
Dim t As New List(Of Task)
Dim l As New List(Of UserOption)
t.AddRange(From u As IUserData In Settings.Users Where u.FitToAddParams Select Task.Run(Sub() l.Add(New UserOption(u, MyList, True))))
If t.Count > 0 Then Task.WaitAll(t.ToArray)
If l.Count > 0 Then
For i% = 0 To l.Count - 1
If l(i) Is Nothing Then Throw New ArgumentNullException("UserOption", $"One of the UserOptions [{i} / {l.Count - 1}] is null.")
If l(i).Image Is Nothing Then l(i).UpdateImage()
Next
End If
Return l
Catch ex As Exception
Return ErrorsDescriber.Execute(EDP.LogMessageValue, ex,
"Image fast loading error." & vbCr &
"Click the ""Refresh"" button to manually refresh the user list." & vbCr &
"[ListImagesLoader.GetUsersWithImages]")
End Try
End Function
End Class End Class

View File

@@ -124,6 +124,7 @@ Partial Public Class MainFrame : Inherits System.Windows.Forms.Form
Me.BTT_TRAY_SHOW_HIDE = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_TRAY_SHOW_HIDE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_TRAY_CLOSE = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_TRAY_CLOSE = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_TRAY_CLOSE_NO_SCRIPT = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_TRAY_CLOSE_NO_SCRIPT = New System.Windows.Forms.ToolStripMenuItem()
Me.BTT_TRAY_CHANNELS = 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()
CONTEXT_SEP_1 = New System.Windows.Forms.ToolStripSeparator() CONTEXT_SEP_1 = New System.Windows.Forms.ToolStripSeparator()
@@ -754,6 +755,7 @@ Partial Public Class MainFrame : Inherits System.Windows.Forms.Form
' '
'BTT_CONTEXT_GROUPS 'BTT_CONTEXT_GROUPS
' '
Me.BTT_CONTEXT_GROUPS.Image = Global.SCrawler.My.Resources.Resources.TagPic_24
Me.BTT_CONTEXT_GROUPS.Name = "BTT_CONTEXT_GROUPS" Me.BTT_CONTEXT_GROUPS.Name = "BTT_CONTEXT_GROUPS"
Me.BTT_CONTEXT_GROUPS.Size = New System.Drawing.Size(221, 22) Me.BTT_CONTEXT_GROUPS.Size = New System.Drawing.Size(221, 22)
Me.BTT_CONTEXT_GROUPS.Text = "Change labels" Me.BTT_CONTEXT_GROUPS.Text = "Change labels"
@@ -824,9 +826,9 @@ Partial Public Class MainFrame : Inherits System.Windows.Forms.Form
' '
'TRAY_CONTEXT 'TRAY_CONTEXT
' '
Me.TRAY_CONTEXT.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_TRAY_PAUSE_AUTOMATION, Me.BTT_TRAY_SILENT_MODE, Me.BTT_TRAY_FEED_SHOW, TRAY_SEP_1, Me.BTT_TRAY_SHOW_HIDE, TRAY_SEP_2, Me.BTT_TRAY_CLOSE, Me.BTT_TRAY_CLOSE_NO_SCRIPT}) Me.TRAY_CONTEXT.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_TRAY_PAUSE_AUTOMATION, Me.BTT_TRAY_SILENT_MODE, Me.BTT_TRAY_FEED_SHOW, Me.BTT_TRAY_CHANNELS, TRAY_SEP_1, Me.BTT_TRAY_SHOW_HIDE, TRAY_SEP_2, Me.BTT_TRAY_CLOSE, Me.BTT_TRAY_CLOSE_NO_SCRIPT})
Me.TRAY_CONTEXT.Name = "TRAY_CONTEXT" Me.TRAY_CONTEXT.Name = "TRAY_CONTEXT"
Me.TRAY_CONTEXT.Size = New System.Drawing.Size(171, 148) Me.TRAY_CONTEXT.Size = New System.Drawing.Size(171, 170)
' '
'BTT_TRAY_PAUSE_AUTOMATION 'BTT_TRAY_PAUSE_AUTOMATION
' '
@@ -883,6 +885,13 @@ Partial Public Class MainFrame : Inherits System.Windows.Forms.Form
Me.BTT_TRAY_CLOSE_NO_SCRIPT.ToolTipText = "Close the program without executing the script" Me.BTT_TRAY_CLOSE_NO_SCRIPT.ToolTipText = "Close the program without executing the script"
Me.BTT_TRAY_CLOSE_NO_SCRIPT.Visible = False Me.BTT_TRAY_CLOSE_NO_SCRIPT.Visible = False
' '
'BTT_TRAY_CHANNELS
'
Me.BTT_TRAY_CHANNELS.Name = "BTT_TRAY_CHANNELS"
Me.BTT_TRAY_CHANNELS.Size = New System.Drawing.Size(170, 22)
Me.BTT_TRAY_CHANNELS.Text = "Channels"
Me.BTT_TRAY_CHANNELS.Image = Global.SCrawler.My.Resources.SiteResources.RedditPic_512
'
'MainFrame 'MainFrame
' '
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
@@ -986,4 +995,5 @@ Partial Public Class MainFrame : Inherits System.Windows.Forms.Form
Friend WithEvents BTT_DOWN_AUTOMATION_PAUSE As ToolStripMenuItem Friend WithEvents BTT_DOWN_AUTOMATION_PAUSE As ToolStripMenuItem
Private WithEvents BTT_TRAY_FEED_SHOW As ToolStripMenuItem Private WithEvents BTT_TRAY_FEED_SHOW As ToolStripMenuItem
Friend WithEvents MENU_DOWN_ALL As ToolStripDropDownButton Friend WithEvents MENU_DOWN_ALL As ToolStripDropDownButton
Private WithEvents BTT_TRAY_CHANNELS As ToolStripMenuItem
End Class End Class

View File

@@ -250,7 +250,6 @@ CloseResume:
#Region "List refill, update" #Region "List refill, update"
Friend Sub RefillList() Friend Sub RefillList()
UserListLoader.Update() UserListLoader.Update()
GC.Collect()
End Sub End Sub
Private Sub UserListUpdate(ByVal User As IUserData, ByVal Add As Boolean) Private Sub UserListUpdate(ByVal User As IUserData, ByVal Add As Boolean)
UserListLoader.UpdateUser(User, Add) UserListLoader.UpdateUser(User, Add)
@@ -380,7 +379,7 @@ CloseResume:
If MyFeed Is Nothing Then MyFeed = New DownloadFeedForm : AddHandler Downloader.FeedFilesChanged, AddressOf MyFeed.Downloader_FilesChanged If MyFeed Is Nothing Then MyFeed = New DownloadFeedForm : AddHandler Downloader.FeedFilesChanged, AddressOf MyFeed.Downloader_FilesChanged
If MyFeed.Visible Then MyFeed.BringToFront() Else MyFeed.Show() If MyFeed.Visible Then MyFeed.BringToFront() Else MyFeed.Show()
End Sub End Sub
Private Sub BTT_CHANNELS_Click(sender As Object, e As EventArgs) Handles BTT_CHANNELS.Click Private Sub BTT_CHANNELS_Click(sender As Object, e As EventArgs) Handles BTT_CHANNELS.Click, BTT_TRAY_CHANNELS.Click
If MyChannels Is Nothing Then If MyChannels Is Nothing Then
MyChannels = New ChannelViewForm MyChannels = New ChannelViewForm
AddHandler MyChannels.OnUsersAdded, AddressOf OnUsersAddedHandler AddHandler MyChannels.OnUsersAdded, AddressOf OnUsersAddedHandler
@@ -1452,8 +1451,8 @@ ResumeDownloadingOperation:
m.Text = "No one user deleted!" m.Text = "No one user deleted!"
m.Style = MsgBoxStyle.Critical m.Style = MsgBoxStyle.Critical
Else Else
m.Text = $"The following users were deleted:{vbNewLine}{removedUsers.ListToStringE(vbNewLine, userProvider)}{vbNewLine.StringDup(2)}" m.Text = $"The following users were deleted:{vbNewLine}{removedUsers.ListToString(vbNewLine)}{vbNewLine.StringDup(2)}"
m.Text &= $"The following users were NOT deleted:{vbNewLine}{leftUsers.ListToStringE(vbNewLine, userProvider)}" m.Text &= $"The following users were NOT deleted:{vbNewLine}{leftUsers.ListToString(vbNewLine)}"
m.Style = MsgBoxStyle.Exclamation m.Style = MsgBoxStyle.Exclamation
End If End If
If b Then Settings.UpdateBlackList() If b Then Settings.UpdateBlackList()

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

View File

@@ -370,6 +370,16 @@ Namespace My.Resources
End Get End Get
End Property End Property
'''<summary>
''' Looks up a localized resource of type System.Drawing.Bitmap.
'''</summary>
Friend ReadOnly Property TagPic_24() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("TagPic_24", 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>

View File

@@ -214,4 +214,7 @@
<data name="TagIcon_32" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="TagIcon_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Icons\TagIcon_32.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Content\Icons\TagIcon_32.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="TagPic_24" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Content\Pictures\TagPic_24.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root> </root>

View File

@@ -80,7 +80,7 @@ Namespace Plugin.Hosts
Friend ReadOnly Property HasSpecialOptions As Boolean = False Friend ReadOnly Property HasSpecialOptions As Boolean = False
Private ReadOnly _ResponserGetMethod As MethodInfo Private ReadOnly _ResponserGetMethod As MethodInfo
Private ReadOnly _ResponserIsContainer As Boolean = False Private ReadOnly _ResponserIsContainer As Boolean = False
Friend ReadOnly Property Responser As Response Friend ReadOnly Property Responser As Responser
Get Get
If Not _ResponserGetMethod Is Nothing Then If Not _ResponserGetMethod Is Nothing Then
Return _ResponserGetMethod.Invoke(Source, Nothing) Return _ResponserGetMethod.Invoke(Source, Nothing)
@@ -190,7 +190,7 @@ Namespace Plugin.Hosts
If m.MemberType = MemberTypes.Property Then If m.MemberType = MemberTypes.Property Then
PropList.Add(New PropertyValueHost(Source, m)) PropList.Add(New PropertyValueHost(Source, m))
With DirectCast(m, PropertyInfo) With DirectCast(m, PropertyInfo)
If .PropertyType Is GetType(Response) AndAlso m.GetCustomAttribute(Of DoNotUse)() Is Nothing Then _ResponserGetMethod = .GetMethod If .PropertyType Is GetType(Responser) AndAlso m.GetCustomAttribute(Of DoNotUse)() Is Nothing Then _ResponserGetMethod = .GetMethod
End With End With
End If End If
With m.GetCustomAttributes() With m.GetCustomAttributes()

View File

@@ -165,12 +165,6 @@
<Compile Include="API\Base\ProfileSaved.vb" /> <Compile Include="API\Base\ProfileSaved.vb" />
<Compile Include="API\Base\SiteSettingsBase.vb" /> <Compile Include="API\Base\SiteSettingsBase.vb" />
<Compile Include="API\Base\Structures.vb" /> <Compile Include="API\Base\Structures.vb" />
<Compile Include="API\Instagram\AdditionalSettingsForm.Designer.vb">
<DependentUpon>AdditionalSettingsForm.vb</DependentUpon>
</Compile>
<Compile Include="API\Instagram\AdditionalSettingsForm.vb">
<SubType>Form</SubType>
</Compile>
<Compile Include="API\Instagram\EditorExchangeOptions.vb" /> <Compile Include="API\Instagram\EditorExchangeOptions.vb" />
<Compile Include="API\Instagram\OptionsForm.Designer.vb"> <Compile Include="API\Instagram\OptionsForm.Designer.vb">
<DependentUpon>OptionsForm.vb</DependentUpon> <DependentUpon>OptionsForm.vb</DependentUpon>
@@ -178,7 +172,6 @@
<Compile Include="API\Instagram\OptionsForm.vb"> <Compile Include="API\Instagram\OptionsForm.vb">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
<Compile Include="API\Instagram\SettingsExchangeOptions.vb" />
<Compile Include="API\LPSG\Declarations.vb" /> <Compile Include="API\LPSG\Declarations.vb" />
<Compile Include="API\LPSG\SiteSettings.vb" /> <Compile Include="API\LPSG\SiteSettings.vb" />
<Compile Include="API\LPSG\UserData.vb" /> <Compile Include="API\LPSG\UserData.vb" />
@@ -414,9 +407,6 @@
</Compile> </Compile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="API\Instagram\AdditionalSettingsForm.resx">
<DependentUpon>AdditionalSettingsForm.vb</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="API\Instagram\OptionsForm.resx"> <EmbeddedResource Include="API\Instagram\OptionsForm.resx">
<DependentUpon>OptionsForm.vb</DependentUpon> <DependentUpon>OptionsForm.vb</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
@@ -584,6 +574,7 @@
<None Include="Content\Icons\SiteIcons\XhamsterIcon_32.ico" /> <None Include="Content\Icons\SiteIcons\XhamsterIcon_32.ico" />
<None Include="Content\Pictures\SitePictures\PornHubPic_16.png" /> <None Include="Content\Pictures\SitePictures\PornHubPic_16.png" />
<None Include="Content\Icons\SiteIcons\PornHubIcon_16.ico" /> <None Include="Content\Icons\SiteIcons\PornHubIcon_16.ico" />
<None Include="Content\Pictures\TagPic_24.png" />
<Content Include="cURL\curl.exe"> <Content Include="cURL\curl.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>

View File

@@ -23,12 +23,11 @@ Friend Class SettingsCLS : Implements IDisposable
Friend Const CookieEncryptKey As String = "SCrawlerCookiesEncryptKeyword" Friend Const CookieEncryptKey As String = "SCrawlerCookiesEncryptKeyword"
Friend ReadOnly Design As XmlFile Friend ReadOnly Design As XmlFile
Private ReadOnly MyXML As XmlFile Private ReadOnly MyXML As XmlFile
Friend ReadOnly OS64 As Boolean
Private ReadOnly FfmpegExists As Boolean Private ReadOnly FfmpegExists As Boolean
Friend ReadOnly FfmpegFile As SFile Friend ReadOnly FfmpegFile As SFile
Friend ReadOnly Property UseM3U8 As Boolean Friend ReadOnly Property UseM3U8 As Boolean
Get Get
Return OS64 And FfmpegExists Return FfmpegExists
End Get End Get
End Property End Property
Private ReadOnly FFMPEGNotification As XMLValue(Of Boolean) Private ReadOnly FFMPEGNotification As XMLValue(Of Boolean)
@@ -67,7 +66,6 @@ Friend Class SettingsCLS : Implements IDisposable
End Sub End Sub
Friend Sub New() Friend Sub New()
RemoveUnusedPlugins() RemoveUnusedPlugins()
OS64 = Environment.Is64BitOperatingSystem
FfmpegFile = "ffmpeg.exe" FfmpegFile = "ffmpeg.exe"
FfmpegExists = FfmpegFile.Exists FfmpegExists = FfmpegFile.Exists
@@ -81,7 +79,7 @@ Friend Class SettingsCLS : Implements IDisposable
LastCollections = New List(Of String) LastCollections = New List(Of String)
FFMPEGNotification = New XMLValue(Of Boolean)("FFMPEGNotification", True, MyXML) FFMPEGNotification = New XMLValue(Of Boolean)("FFMPEGNotification", True, MyXML)
If OS64 And Not FfmpegExists Then If Not FfmpegExists Then
If FFMPEGNotification.Value AndAlso MsgBoxE(New MMessage("[ffmpeg.exe] is missing", "ffmpeg.exe", If FFMPEGNotification.Value AndAlso MsgBoxE(New MMessage("[ffmpeg.exe] is missing", "ffmpeg.exe",
{"OK", New MsgBoxButton("Disable notification") With { {"OK", New MsgBoxButton("Disable notification") With {
.IsDialogResultButton = False, .ToolTip = "Disable ffmpeg missing notification"}}, vbExclamation) With { .IsDialogResultButton = False, .ToolTip = "Disable ffmpeg missing notification"}}, vbExclamation) With {
@@ -259,7 +257,7 @@ Friend Class SettingsCLS : Implements IDisposable
If cUsers.ListExists Then If cUsers.ListExists Then
Dim d As New Dictionary(Of String, List(Of UserInfo)) Dim d As New Dictionary(Of String, List(Of UserInfo))
cUsers = cUsers.ListForEachCopy(Of List(Of UserInfo))(Function(ByVal f As UserInfo, ByVal f_indx As Integer) As UserInfo cUsers = cUsers.ListForEachCopy(Of List(Of UserInfo))(Function(ByVal f As UserInfo, ByVal f_indx As Integer) As UserInfo
Dim m% = IIf(f.Merged Or f.IsVirual, 1, 2) Dim m% = IIf(f.Merged Or f.IsVirtual, 1, 2)
If Not f.Protected AndAlso SFile.GetPath(f.File.CutPath(m - 1).Path).Exists(SFO.Path, False) Then If Not f.Protected AndAlso SFile.GetPath(f.File.CutPath(m - 1).Path).Exists(SFO.Path, False) Then
If Not d.ContainsKey(f.CollectionName) Then If Not d.ContainsKey(f.CollectionName) Then
d.Add(f.CollectionName, New List(Of UserInfo) From {f}) d.Add(f.CollectionName, New List(Of UserInfo) From {f})

View File

@@ -86,6 +86,7 @@ Friend Class UserFinder : Implements IDisposable
.CollectionName = x.Value(UserInfo.Name_Collection), .CollectionName = x.Value(UserInfo.Name_Collection),
.IsChannel = x.Value(UserInfo.Name_IsChannel).FromXML(Of Boolean)(False) .IsChannel = x.Value(UserInfo.Name_IsChannel).FromXML(Of Boolean)(False)
} }
'TODELETE: UserFinder remove old 'merge' constant
#Disable Warning BC40000 #Disable Warning BC40000
If x.Contains(UserDataBase.Name_DataMerging) Then If x.Contains(UserDataBase.Name_DataMerging) Then
u.Merged = x.Value(UserDataBase.Name_DataMerging).FromXML(Of Boolean)(False) u.Merged = x.Value(UserDataBase.Name_DataMerging).FromXML(Of Boolean)(False)
@@ -158,7 +159,7 @@ Friend Class UserFinder : Implements IDisposable
Const MsgTitle$ = "Import users" Const MsgTitle$ = "Import users"
Const DesignNode$ = "ImportUserSelector" Const DesignNode$ = "ImportUserSelector"
Try Try
Dim uStr As Func(Of UserInfo, String) = Function(u) $"{IIf(u.CollectionName.IsEmptyString, String.Empty, $"[{u.CollectionName}]: ")} {u.Site} - {u.Name}" Dim uStr As Func(Of UserInfo, String) = Function(u) $"{IIf(u.CollectionName.IsEmptyString, String.Empty, $"[{u.CollectionName}]: ")}{u.Site} - {u.Name}"
Dim uc As Comparison(Of UserInfo) = Function(ByVal x As UserInfo, ByVal y As UserInfo) As Integer Dim uc As Comparison(Of UserInfo) = Function(ByVal x As UserInfo, ByVal y As UserInfo) As Integer
If Not x.CollectionName.IsEmptyString And Not y.CollectionName.IsEmptyString Then If Not x.CollectionName.IsEmptyString And Not y.CollectionName.IsEmptyString Then
Return x.CollectionName.CompareTo(y.CollectionName) Return x.CollectionName.CompareTo(y.CollectionName)
@@ -182,7 +183,7 @@ Friend Class UserFinder : Implements IDisposable
End If End If
__added = {__added, __dup, __skipped}.ListToString(vbCr.StringDup(2)) __added = {__added, __dup, __skipped}.ListToString(vbCr.StringDup(2))
If Not __added.IsEmptyString Then If Not __added.IsEmptyString Then
Using t As New TextSaver($"LOGs\ImportUsers.txt") With {.ForceAddDateTimeToFileName = True} Using t As New TextSaver("LOGs\ImportUsers.txt") With {.ForceAddDateTimeToFileName = True}
t.Append(__added) t.Append(__added)
If Added.Count > 0 Then If Added.Count > 0 Then
t.AppendLine(vbNewLine.StringDup(2)) t.AppendLine(vbNewLine.StringDup(2))
@@ -296,7 +297,7 @@ Friend Class UserFinder : Implements IDisposable
AddHandler f.AddClick, __add AddHandler f.AddClick, __add
If f.ShowDialog() = DialogResult.OK Then If f.ShowDialog() = DialogResult.OK Then
l.Clear() l.Clear()
l.AddRange(f.DataResult) l.ListAddList(f.DataResult, LAP.NotContainsOnly)
Return l Return l
End If End If
End Using End Using

View File

@@ -39,7 +39,7 @@ Partial Friend Module MainMod
Return Not CollectionName.IsEmptyString Return Not CollectionName.IsEmptyString
End Get End Get
End Property End Property
Friend ReadOnly Property IsVirual As Boolean Friend ReadOnly Property IsVirtual As Boolean
Get Get
Return CollectionModel = UsageModel.Virtual Or UserModel = UsageModel.Virtual Return CollectionModel = UsageModel.Virtual Or UserModel = UsageModel.Virtual
End Get End Get
@@ -123,7 +123,7 @@ Partial Friend Module MainMod
ElseIf Merged And IncludedInCollection Then ElseIf Merged And IncludedInCollection Then
Return $"{ColPath}\{SettingsFolderName}" Return $"{ColPath}\{SettingsFolderName}"
Else Else
If IncludedInCollection And Not IsVirual Then If IncludedInCollection And Not IsVirtual Then
Return $"{ColPath}\{Site}_{Name}\{SettingsFolderName}" Return $"{ColPath}\{Site}_{Name}\{SettingsFolderName}"
ElseIf Not Settings(Plugin) Is Nothing Then ElseIf Not Settings(Plugin) Is Nothing Then
Return $"{Settings(Plugin).Path.PathNoSeparator}\{Name}\{SettingsFolderName}" Return $"{Settings(Plugin).Path.PathNoSeparator}\{Name}\{SettingsFolderName}"